-
Notifications
You must be signed in to change notification settings - Fork 0
Step Organisation
How do you name step files? What to put in each step? What not to put in steps? Here are some guidelines that will lead to better scenarios.
Technically it doesn’t matter how you name your step files and what steps you put where. You could have one giant file called all_steps.rb and put all your step definitions there. That would be messy.
We recommend creating a steps.rb file for each domain concept. For example, a rule of thumb is to have one file for each major model/database table. In a Curriculum Vitae application we might have:
- employee_steps.rb
- education_steps.rb
- experience_steps.rb
- authentication_steps.rb
The three first ones would contain all the steps related to creating, reading, updating and deleting the various models. The last one steps related to logging in and out.
Each steps.rb file typically contain Given, When and Then steps.
Cucumber doesn’t technically distinguish between these three kind of steps. However, we strongly recommend that you do! These words have been carefully selected for their purpose, and you should know what the purpose is to get into the BDD mindset.
The purpose of givens is to put the system in a known state before the user starts interacting with the system (in the When steps). Avoid talking about user interaction in givens. Examples:
- Create records (model instances) / set up the database state.
- It’s ok to call into the layer “inside” the UI layer here (in Rails: talk to the models).
- Log in a user (An exception to the no-interaction recommendation. Things that “happened earlier” are ok).
And for all the Rails users out there – we recommend using a Given with a multiline table argument to set up records instead of fixtures. This way you can read the scenario and make sense out of it without having to look elsewhere (at the fixtures).
The purpose of When steps is to describe the key action the user performs – or the user interaction. Examples:
- Interact with a web page (Webrat/Watir/Selenium interaction etc should mostly go into When steps).
- Interact with some other user interface element.
- Developing a library? Kicking off some kind of action that has an observable effect somewhere else.
The purpose of Then steps is to observe outcomes. This is where you look at Schrödinger’s cat. The observations should be related to the business value/benefit in your feature description. The observations should also be on some kind of output – that is something that comes out of the system (report, user interface, message) and not something that is deeply buried inside it (that has no business value).
Examples:
- Verify that something related to the Given+When is in the output
- Check that some external system has received the expected message (was an email with specific content sent?)
While it might be tempting to implement Then steps to just look in the database – resist the temptation. You should verify some kind of outcome that is observable for the user (or external system) and databases usually are not.
It’s possible to keep object state in variables inside your step definitions. Be careful about this as it might make your steps more tightly coupled and harder to reuse. There is no absolute rule here - sometimes it's ok to use @variables. You can follow a longer discussion "here":http://www.mail-archive.com/rspec-usersrubyforge.org/msg06268.html