Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

A thin wrapper around Cucumber.

branch: master
README.textile

Cellophane

Cellophane is a thin wrapper around Cucumber that is intended to make it easier to structure projects in ways that make sense to the people working on them. It has been tested with Cucumber 0.10.0 on Ruby 1.8.7-p302 and Ruby 1.9.2-p0.

Installation

gem install cellophane

Configuration

Project-specific File

Cellophane can be configured project by project through the use of a .cellophane.yaml file that lives in the root of your project. Configurable options are:

Directive
cuke_command

Explanation
Tells Cellophane how to call Cucumber. Defaults to cucumber.

Examples
cuke_command: bundle exec cucumber
cuke_command: script/cucumber
cuke_command: cuke (as in a shell alias)

Directive
cucumber

Explanation
Options you want to pass to Cucumber by default.

Example
cucumber: --format progress --no-profile

Notes
Anything defined by cucumber in the configuration file will be overwritten by the -c/--cucumber command line switch (see below).

Directive
feature_path

Explanation
Root location of your feature files. Defaults features.

Example
feature_path: cuke/features

Notes
The path is relative to your project’s root.

Directive
step_path

Explanation
Location of your step definitions. Defaults to features/step_definitions. It can be defined in two ways:

  1. a path relative to the project root
  2. nested in each feature directory

Examples


step_path: cuke/steps
step_path:
  nested_in: step_definition

Notes
Use the first method if your step defitions follow the structure of your features. For example:

my_project
	- app
	- config
	- cuke
		- features
			- admin
				- reports
				- user_maintenance
			- user
				- communication
				- profile
		- steps
			- admin
				- reports
				- user_maintenance
			- user
				- communication
				- profile
		- support
	- db
	- lib
	- etc, etc

Use the second method if each feature directory has its own step definitions directory:

my_project
	- app
	- config
	- features
		- admin
			- step_definitions
		- user
			- step_definitions
		- visitor
			- step_definitions
		- support
	- db
	- lib
	- etc, etc

Directive
shared

Explanation
Automatically load steps named shared_steps.rb in all directories that comprise the step path for the current feature file. Defaults to true. This option allows you to share steps among features while keeping them organized according to scope.

Examples
shared: global # instead of looking for shared_steps.rb, look for global_steps.rb
shared: false # don’t automatically require shared steps

Notes
Consider the following project structure:

my_project
	- app
	- config
	- cuke
		- features
			- admin
				- reports
				- user_maintenance
			- user
				- communication
				- profile
		- steps
			- admin
				- reports
				- user_maintenance
			- user
				- communication
				- profile
		- support
	- db
	- lib
	- etc, etc

When you run a feature in features/admin/reports/weekly.feature, Cellophane will automatically require shared steps found in the following locations:

steps/admin/reports/shared_steps.rb # steps specific to admin reports
steps/admin/shared_steps.rb # steps specific to admin
steps/shared_steps.rb # steps used by the whole application

If your steps are nested, Cellophane will look for shared steps only in the nested step location. For example, if your project looks like

my_project
	- app
	- config
	- features
		- admin
			- step_definitions
		- user
			- step_definitions
		- visitor
			- step_definitions
		- support
	- db
	- lib
	- etc, etc

and you run a feature in features/admin/email.feature, Cellophane will look for features/admin/step_definitions/shared_steps.rb.

Directive
requires

Explanation
Other directories or files that Cucumber needs to require. It is an array.

Examples
requires: [cuke/support, cuke/steps/shared]

requires:
  - cuke/support
  - cuke/steps/shared

Notes
requires are passed to Cucumber as defined, so absolute paths are respected.

Command Line

Cellophane has the following command line options:

Usage: cellophane [options] PATTERN
    -r, --regexp                     PATTERN is a regular expression. Default is false.
    -t, --tags TAGS                  Tags to include/exclude.
    -c, --cucumber OPTIONS           Options to pass to cucumber.
    -p, --print                      Echo the command instead of calling cucumber.
    -d, --debug                      Require ruby-debug.
    -v, --version                    Display the version.
    -h, --help                       Display this screen.

PATTERN is the pattern of feature files that you are interested in. By default PATTERN is a glob, but by using the -r/--regexp switch, you can pass a Ruby regular expression instead (no slashes necessary). When using a glob, you can specify that files matching the pattern are to be excluded by preceeding the pattern with a tilde (~). You can also combine include and exclude patterns in the same call. See below for examples.

If you need to pass something through to Cucumber, such as a formatter, use the -c/--cucumber switch. Depending on what it is you are passing through, you might need to enclose it in quotes. Do keep in mind that -c/--cucumber on the command line overrides that defined in the YAML file.

-d/--debug is only useful for Cellophane development and will have no effect on Cucumber.

History

By default, Cucumber expects features to live in features and step definitions to live in features/step_definitions. When running a feature, all step definitions are loaded unless you explicitly require just the ones you want. If you structure your project differently, you have to require files explicitly, which gets old real fast.

After some experimenting with different directory structures, I settled on the following for my own projects:

my_project
	- app
	- config
	- cuke
		- features
		- steps
		- support
	- db
	- lib
	- etc, etc

It’s based on the structure of the spec directory and I find that it fits my brain pretty well. There are three organizational strategies that I found myself following:

  1. separation of features in subdirectories
  2. keeping feature specific steps in files that are named according to the feature
  3. keeping all shared steps in files that are named in a more generalized fashion

For example, a project my look like this:

my_project
	- app
	- config
	- cuke
		- features
			- admin
				- reports
				- user_maintenance
			- user
				- communication
				- profile
		- steps
			- admin
				- reports
				- user_maintenance
			- user
				- communication
				- profile
		- support
	- db
	- lib
	- etc, etc

If the features in cuke/features/admin/reports had any steps that were specific to them, they would live cuke/steps/admin/reports. Any steps that are shared between two or more features would go in files in cuke/support.

To use this structure in Cucumber requires explicitly requiring the files/directories with every run. To run all of the features in cuke/features/admin/reports, I would enter the command

cucumber -r cuke/support -r cuke/steps/admin/reports cuke/features/admin/reports

I got weary of doing that all the time, so I experimented with aliases and profiles, neither of which really met my needs. So I created Cellophane. With it, the same features could be as easy as:

cellophane admin/*

As time went on, more patterns began to emerge from my workflow, and with them, Cellophane gained abilities.

Examples and Notes

Features

Using the example project above:

# run all features
cellophane

# run everything in admin
cellophane admin/*

# run everything in admin, except the reports
cellophane admin/*,~admin/reports/*

# run everything, except the admin reports
cellophane ~admin/reports/*

# run all user_maintenance features regardless of where they are
cellophane */user_maintenance/*

# run all features in files with email in the name
cellophane **/*email*

# or use a regular expression
cellophane -r email

Step Definitions

Cellophane does assume that your steps are defined in files that follow the naming of your features. For each feature file that is found, Cellophane will look for a step file with the same name and automatically require it. To require shared step definitions, put them in a folder and include that folder in the requires section of .cellophane.yaml. Also look into the shared directive of the configuration file, which allows more fine-grained control of shared steps.

For example, if you have a feature defined in <feature path>/admin/user/account_maintenance.feature, Cellophane will automatically require a step definition file located in <step path>/admin/user/account_maintenance_steps.rb. Unless you are using nested step definitions in .cellophane.yaml (step_path: {nested_in: steps }, in which case Cellophane will automatically require <feature path>/admin/user/steps/account_maintenance_steps.rb if it exists.

Tags

You don’t need to use @. You can if you want, but it’s not necessary.

Cellophane supports OR, AND, and NOT tags. Examples will probably illustrate better than words.

OR

cellophane -t one,two
cucumber -t @one,@two

AND

cellophane -t one,+two
cucumber -t @one -t @two

NOT

cellophane -t one,~two
cucumber -t @one -t ~@two

Mixed tags in a logical order

cellophane -t one,two,~three,+four
cucumber -t @one,@two -t @four -t ~@three

Mixed tags not in a logical order

cellophane -t +four,one,~three,two
cucumber -t @one,@two -t @four -t ~@three

I like to tag my scenarios with numeric values so I can easily run a specific scenario at any give time. It may sound a bit unusual, but I find it very handy.

Numeric OR ranges

cellophane -t 1-3
cucumber -t @1,@2,@3

Numeric NOT ranges

cellophane -t ~1-3
cucumber -t ~@1 -t ~@2 -t ~@3

Numeric OR range with a NOT

cellophane -t 1-3,~2
cucumber -t @1,@3
Something went wrong with that request. Please try again.