Collective Idea

Collective Idea Logo

Brandon Keepers

Practical Cucumber: Organization

By Brandon Keepers on September 13, 2010 in bdd and cucumber

This post is part of our Practical Cucumber series.

Nobody knows how to organize cucumber features and steps. Unlike our beloved web framework, there are not enforced convention. Every project has it’s own conventions–that is, if it has conventions at all. Here is a pattern that works for us.

Group steps by model

Steps should be reusable. We’ve found the best way to keep track of them is to group them by the primary model they affect. Some steps may affect multiple models, but usually there is an obvious choice. For example, the following step could either go in provider_steps.rb or license_steps.rb.

Given '"$name" is licensed in "$state"' do |name, state|
  provider = Provider.find_by_name!(name)
  Factory(:license, :provider => provider, :state => state)
end

While it is related to the Provider model, there are two good reasons it should go in license_steps.rb

  1. The step is creating a License, while it is only finding a Provider
  2. Provider is the most central model in this app. It will likely have a lot more related steps, so for findability’s sake, we will put it in license_steps.rb

Grouping steps by model makes them easy to find and encourages

Group features by…feature

Brilliant, huh? It seems obvious, but we often see apps where the features are grouped by model. There will be one massive appointment.feature model that has completely unrelated scenarios. Put each feature in it’s own file. It’s up to you to decide what a “feature” is.

Here is one subdirectory of the project that I took the above example from:

$ ls features/scheduling_appointment/
canceling_appointment.feature
client_requesting_appointments_with_insurance.feature
client_requesting_chat_appointment.feature
client_requesting_phone_appointment.feature
client_requesting_video_appointment.feature
client_responding_to_rescheduled_appointment.feature
expiring_pending_appointments.feature
marking_an_appointment_complete.feature
provider_avoiding_scheduling_conflicts.feature
provider_requesting_appointment_with_an_unknown_user.feature
provider_requesting_phone_appointment.feature
provider_responds_to_appointment_request.feature
provider_scheduleing_an_appointment.feature
rescheduling_a_scheduled_appointment.feature

Which brings up another point: don’t be afraid to put features in subdirectories. For any large app, it’s almost essential. Cucumber gets confused when you do this, but you can fix that by adding the following to the options in cucumber.yml:

--require features/step_definitions --require features/support

Thoughts?

What do you do to organize your cucumber features and steps?

This post is part of our Practical Cucumber series.

By Brandon Keepers on September 13, 2010 in bdd and cucumber

6 Comments

  1. Carl Shaulis

    Carl Shaulis October 01, 2010 http://kungfutesting.blogspot.com/

    The .yml file is part of the Cucumber gem. If we add these requires it will work fine locally. How might we easily distribute the change across multiple teams and environments as an automation package? Currently we use Bundler to package all of the gems required for our automation framework. A custom cucumber gem is probably not the best solution. Can we override the .yml file?

  2. G-man

    G-man October 03, 2010

    I’m kind a fan of the RESTful approach for smaller projects.. I group features by Model-CRUD description, as in feature files for: company_create, company_read, company_update, and company delete.

    True, the files can get a little long, but I just keep the few @wip features I’m working on at the top, and run an overall rcov coverage test of everything at the end of the day just to keep myself honest.

    Point is, I know right away where to put a feature by just thinking RESTfully.

    Again, for small projects, the few custom steps I may have just go in an extra_steps.rb file.

    Nice blog!

  3. Daniel Morrison

    Daniel Morrison October 26, 2010 http://collectiveidea.com

    Carl Shaulis: we check the .yml file into git with our projects. You can certainly override it or add to it.

  4. Charlie Cummins

    Charlie Cummins March 18, 2011

    I am looking to do some stand alone testing against a Tapestry web app using cucumber. There are many roles in this application. How should I incorporate the roles in cucumber? Should I incorporate the roles in the directory structure or prefix the feature file names with the role.
    Thanks, Charlie

  5. Charlie Cummins

    Charlie Cummins March 18, 2011

    I am looking to do some stand alone testing against a Tapestry web app using cucumber. There are many roles in this application. How should I incorporate the roles in cucumber? Should I incorporate the roles in the directory structure or prefix the feature file names with the role.
    Thanks, Charlie

  6. Daniel Morrison

    Daniel Morrison March 24, 2011 http://collectiveidea.com

    Charlie Cummins: We’ve had good luck with directories, but if you end up with a lot of directories with only one or two files, try to group by type of action and have each role’s version of that in the directory.

Post a Comment

Contact Us

Find us on Google Maps
Collective Idea
44 East 8th Street, Suite 410
Holland, Michigan 49423 USA 42.790334-86.105251

Follow us on the Interwebs

We are currently available for medium and long term projects. Please get in touch if we can be of service.