Sometimes you need some pre conditions to run your scenario or a group of scenarios sharing the same steps repeatedly. You can use background or hooks to setup these conditions. How to know what is the best to use ? Well, depends of the case. So today, I will give some examples with best practices when you should use background and when you should use hooks.
Step definition files have a corresponding method available in the before(condition) do . . .
method, which has however a matching after(condition) do . . .
method as well.
Use Background only to setup a pre-condition that the user needs to know
If it is not a trivial information to the user, set it up in the implementation (hooks), not in the test steps. Remember feature files should focus on What, and not How. These should be high level steps. We want to keep this simple. So, for this reason you avoid give too many details like this type of steps: “When I press the button”.
When using hooks
You can use hooks to run before/after each scenario, a group of scenarios according to the tags, all the scenarios in a feature or all the scenarios of your project. They will run before the first step of your scenario, like the background, but it won’t need any step in your feature file.
@Before and @After each scenario
Similar to JUnit @Before and @After tagging a method with either of these will cause the method to run before or after each scenario runs. Common functionality like starting or stop browsers are nice to place in these hooks. They reduce the number of common test steps in each scenario. Before
hooks will be run before the first step of each scenario. They will run in the same order of which they are registered. After hooks will be run after the last step of each scenario, even when there are failing, undefined, pending or skipped steps.
You may want to finish the tests after the first failure (could be useful in some cases like Continuous Integration when fast feedback is important), for those cases add the command (ruby) in your hook:
Cucumber.wants_to_quit = true if s.failed?
@AfterStep
You have also the possibility to create an after step hook and add for example a take screenshot action. This hook will run after each step of you scenario and you can also filter for certain scenarios using tags. This is only available for Ruby language at the moment, not for Java.
@Around
Around
hooks will run “around” a scenario. This can be used to wrap the execution of a scenario in a block. The Around hook receives a scenario object and a block (Proc) object. The scenario will be executed when you invoke block.call
.
The following example (ruby) will cause scenarios tagged with @fast
to fail if the execution takes longer than 0.5 seconds:
Around('@fast') do |scenario, block| Timeout.timeout(0.5) do block.call end end
Tagged hooks
You can filter what are the scenarios that will run this hook every time before start the scenario or after the scenario ends. The condition which enables the before/after block is the tag (false
or nil)
. Tagged hooks can have multiple tags, and follow similar tagging AND/OR rules that the runner does. You can OR and AND tags in much the same way as you can when running Cucumber from the command line.
e.x. @Before(‘@mobile’, ‘˜@login’) for tests needing a mobile browser launched and are not tagged as login
e.x. @Before(‘@mobile, ˜@login’) for tests needing a mobile browser launched or are not tagged as login
@Before all scenarios
If you have a hook you only want to run once before all the scenarios, use a global variable. Example (ruby):
Before do
$dunit ||= false # define a variable before we can reference its value
return $dunit if $dunit # bail if $dunit TRUE
step "run the really slow log in method" # otherwise do it.
$dunit = true # don't do it again.
end
@AfterConfiguration
You may also provide an AfterConfiguration
hook that will be run after Cucumber has been configured. This hook will run only once; after support has been loaded but before features are loaded. You can use this hook to extend Cucumber, for example you could affect how features are loaded or register custom formatters programatically.
When using background
Short Backgrounds
When using background keep it as short as possible. These steps won’t be written out each time the user reads the scenario, so it’s best to have something simple that the user can remember while reading through your feature file.
Vigorous Backgrounds
Similar to the above, since these steps won’t be listed with each scenario, the more vivid, the test step is, the easier time the user will have remembering it.
Short Feature files
It’s best to keep these feature files smaller, so that the Background information is more readily available. The general rule of thumb is to keep the file small enough to still see the Background test steps at the top of page when reading any scenario.
These two methods are powerful tools, but be aware to not use them excessively.
Resources:
https://github.com/cucumber/cucumber/wiki/Hooks
https://github.com/cucumber/cucumber/wiki/Cucumber-Backgrounder
https://seleniumbycharan.wordpress.com/2015/08/25/use-of-background-hooks-tags-in-cucumber-jvm/