Even when automating UI tests, it is important to keep your scenarios as readable as possible, or you threaten to lose all benefits from a plain-text approach. In this post I’ll give you some tips that can help you with the basics.
Over the course of time you will probably end up having many features and scenarios. Try to define features logically and avoid having very large feature files containing many scenarios. Organize your features in separate folders.
Tags are a great way to group scenarios or features. A simple example:
All feature runners allow you to filter on any combination of tags.
You can attach any meaning to tags, but I’ve frequently seen them used to indicate long-running scenarios or to group scenarios based on the external integrations they need.
A Scenario or Feature block can have multiple tags, separated with spaces or newlines. If you add a tag on a Feature, it will automatically be added to all Scenarios and Scenario Outlines of that Feature.
Try to summarize the gist of a scenario in a single line. Both scenario and feature names are used in the reports, so it really helps if you do not stick to a single-word-says-all approach.
Consider the following example:
It does not take much effort to add more information:
If you cannot put enough information in the feature or scenario name, consider providing a more elaborate description. You can add any kind of text below a Feature up until the first Scenario, Scenario Outline or Background statement. If you want to add a description at the beginning of a scenario you can do so using a docstring:
Gherkin (the Cucumber syntax) has only a couple of reserved words, but I’ve seen the Given/When/Then keywords misused in many places. A simple example explains the correct use of Given/When/Then:
Use Given to put the system in a known state.
Use When to perform the user actions.
Use Then to verify the outcome.
Use And and But
If you have multiple Given/When/Then statements you should combine them using And steps instead of repeating the same keyword over and over again. This way the overall structure of your scenario remains more clear. Consider the following example:
With only repeating And you get the following improved result:
Use * if you are not really testing anything at all
If you are not really writing a scenario but simply using CWB as a browser script runner, then it does not make much sense to use the Given/When/Then structure. All you’re doing is executing steps in sequence. In that case you can drop the keywords and start every step with a *.
6. Structure large scenarios with comments
Usually it is best to keep your scenarios as short as possible, but sometimes there’s just no easy way around writing that lengthy test. Apart from the reserved words, the only alternative to add some structure to a single scenario is to introduce comments that give context about what’s happening… especially if the steps are not self-explanatory.
7. Use backgrounds (wisely)
If you have multiple scenarios performing the same steps in the beginning, you can extract those steps into a Background section. Each feature can have one Background section and it should be positioned before all Scenarios and Scenario Outlines.
The Background is executed before every Scenario or Scenario Outline example.
However, be careful that in case you have a long background and many scenarios in a single feature: it might become unclear what is involved in running the scenario. Consider refactoring the scenarios to Scenario Outline examples instead, or create a custom step to perform the required actions. If none of those are possible, you can still add a comment or scenario description that explains the state created by the background.
Note that just like a scenario, you can give a background a name and description.
8. Know thy steps
Writing readable scenarios comes down to using the most appropriate step for the job. Sometimes there’s more than one way to perform the same action, consider for instance the following form posting example from the SAHI library:
Which could also be written like:
A list of all standard steps available can be found in the user documentation language reference.
Even though the CWB libraries come with a bunch of standard steps, there’s absolutely no requirement to stick to those. When a standard step becomes very unreadable, consider writing a custom step instead. Especially if you see the same group of steps coming back all over the place, bunch them up in a single custom step to improve readability.
After all, the following classic example:
is easier to understand if you rewrite it like:
Note that if you want to create a loop or apply some conditional logic, a custom step is pretty much the only way to go about this.
If you have any additional tips of your own, don’t hesitate to share them in the comments.