A few months ago, I was selected to give a presentation at the Testnet ‘voorjaarsevenement’. My talk was about Gherkin and how to improve your Feature files and step definitions. It’s time to put it on the blog.
Instead of writing an introduction to Gherkin, it’s better to point you to the Cucumber wiki. They have a very good explanation of it. So let’s move on to the tips & tricks!
Feature file tips
- Avoid long descriptions
Features should have a short and sensible title and description. This improves readability and you do want readable and understandable Feature files, don’t you? So there should be one sentence describing the scope and content.
- Choose a single fomat
I don’t care if you pick “As a [role], I want [feature] so that [benefit]” or “In order to [benefit], as a [role] I want [feature]”. However, pick one and stick with it. Again, this improves the readability. And never forget the benefit, this makes it easier to decide on the business value.
- Features… not big portions of the application
There should only be one Feature per file and the Feature should be reflected in the file name. If you work in larger teams, it is easier to work parallel on smaller Feature files.
- Domain language
Involve the customers and use their domain language. Involve them in writing the user stories or at least have them review them. Keep the language consistent accross all Features (and even projects).
Organize your Features and Scenarios with the same discipline like you would organize code. You can organize them according to execution time: fast (<1/10s), slow (<1s) or glacial (>1s). Or put them in separate subdirectories. Or tag them.
- Use Backgrounds
To avoid repetitions in the feature file, Backgrounds are ideal. However, since the user has to keep the Background in mind while reading or writing the Scenarios, keep them short. Max. 4 lines.
- Don’t include technical stuff
The Feature file is about the user. Starting or stopping the webserver, clearing tables, etc can be implemented in the Step Definitions. it shouldn’t be mentioned in the background.
Of course, don’t use a Background if you have only one Scenario.
- Don’t mix
Don’t mix backgrounds in the Feature file with @before hooks in the Step Definitions. This will drive you nuts when debugging.
- Scenario vs Scenario Outline
In fact it is very simple: if you have only one example, use a Scenario.
If you have more than one example, use a Scenario Outline and a table
Keep your scenarios short.
Hide the implementation details.
- Declarative steps over imperative steps
Using declarative steps is much more concise and about WHAT the user wants to do with the system, not HOW the user wants to do it.
Given I have logged on to the system
Then I should see my new messages
Give I am on the login page
When I fill in the username
And I fill in the password
And I click on the ‘Submit’ button
Then I should be logged on to the system
And I should see my new messages
- AND/OR are keywords
so don’t use them within a step
Given I’m on the homepage and logged on
Given I’m on the homepage
And I’m logged on
- Cover happy and non-happy paths
Testing is more than only proving it works. It’s trying to break the system.
Your library of steps will increase in time, so try to generalize your steps to increase reuse.
You understanding of the domain will increase also, so update your language and the steps.
- Never tag the background
Tags allow you to organize your Features and Scenarios. You can have multiple Tags per Feature or Scenario, so never tag the Background.
- Don’t tag Scenario with same Tag as Feature
Feature Tags are also valid for all child Scenarios, so there is no need to apply the same Tag to the Scenarios.
- What is the benefit of Tagging a Feature
You can Tag individual Scenarios, so think about what value would be added by Tagging an entire Feature. There may not be much use for it. Except perhaps Tagging the Feature with the story number.
- Tag categories
Possible tag categories may be
Frequency of execution: @checkin, @hourly, @daily, @nightly
Dependencies: @local, @database, @fixtures, @proxy
Level: @acceptance, @smoke, @sanity
Environment: @integration, @test, @stage, @live
Some groups also Tag according to progress: @wip, @todo, @implemented, @blocked.
I’m not saying this is bad, if you do, make sure you keep the tags up-to-date! If you can’t do that, don’t use them.
Step Definition Tips
Most of the tips below will increase the reuse of your Step Definitions and the readability of the Feature files.
- Use flexible pluralization
Add a ? after the pluralized word:
Then /^the users? should receive an email$/ do
Now it will match both user and users
- Use non-capturing groups
Instead of (some text), use (?:some text). Now the result is not captures and not passed as an argument to your step definition.
It is especially useful in combination with alternation:
When /^(?I|they) create a profile%/
And /^once the files? (?:have|has) finished processing*/ do
- Consolidate Step definitions
When /^the file is (not)? present$/ do |negate|
negate ? check_if_file_is_not_present : check_if_file_is_present
- Use unanchored regular expressions
Normally you anchor start with ^ and end with $. Sometimes it might be useful to omit one:
Then /^wait (\d+) seconds/ do |seconds|
This will allow for more flexible expressive steps:
Then wait 2 seconds for the calculation to finish
Then wait 5 seconds while the document is converted
Of course this can be dangerous, so I think you can only do this for this example 😉
- Be DRY
Don’t Repeat Yourself.
Refactor when necessary and reuse Step Definitions within a project across Features and perhaps even across projects.
- Parse date/time in a natural way
For most programming languages there are libraries that allow you to parse dates and times in a more natural way. For example in Ruby you have Chronic and in Python you can use parsedatetime or pyparsing.
So there we have it: quite a few tips to improve your Gherkin Feature files, Backgrounds and Step Definitions.
However, most important tip I can give you is to exercise discipline when writing your test automation code:
- treat your code as production code
- refactor when necessary
- run your tests as often as possible
- and don’t be too smart: somebody needs to understand next year. And that person might even be you.