Introduction
Before we dive into best practices and tricks in writing our glue code, we want to cover a few last tricks on keeping our Feature files clean. The first of which is how to utilize the Background feature to pull out common test steps.
Background
Often times when writing multiple scenarios within a singular feature file you see repeated test steps. Initial test steps that are common across all scenarios and scenario outlines can be pulled out into a Background test step. These steps can’t use Example table data, however. These steps get executed before every scenario. This can greatly reduce the number of test steps in the feature file, and increase readability. Below are a few tips outlined for a successful Background setup:
-
Only use Background to setup an environment that the user needs to know
If this is extraneous information to the user, set it up in the implementation, not in the test steps. Remember that the feature files should focus on the What, and not the How. These should be high level steps. We want to keep this simple
-
Keep the Background steps short
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
-
Keep the Background steps vivid
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
-
Don’t make the feature file too long
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
When we look at all of this, we get can see that what was once:
@CCOrg @CCNet
Feature: Testing for login page
Scenario Outline: Check login page
Given I want to use the browser Firefox
When I login to CosmicComix
Then I can see the \<Link> button
@Smoke
Examples:
| **Link** |
| Home |
| Library |
| Store |
| ToS |
Scenario Outline: Check Links
Given I want to use the browser Firefox
When I login to CosmicComix
And I select the \<Link> button
Then I see the text \<HelperText>
@Smoke
Examples:
| **Link** | **HelperText** |
| Home | \[disabled\] |
| Library | see your comics |
| Store | purchase more comics |
| ToS | read through our terms of service |
Can become the simpler:
@CCOrg @CCNet
Feature: Testing for login page
Background:
Given I want to use the browser Firefox
When I login to CosmicComix
Scenario Outline: Check login page
Then I can see the \<Link> button
@Smoke
Examples:
| **Link** |
| Home |
| Library |
| Store |
| ToS |
Scenario Outline: Check Links
And I select the \<Link> button
Then I see the text \<HelperText>
@Smoke
Examples:
| **Link** | **HelperText** |
| Home | \[disabled\] |
| Library | see your comics |
| Store | purchase more comics |
| ToS | read through our terms of service |
However, we can still do better…
Hooks
Hooks allow us to perform actions at various points in the cucumber test cycle. 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. They will run in the opposite order of which they are registered.
Scenario Hooks
Similar to JUnit @Before and @After (however do not include to wrong ones) tagging a method with either of these will cause the method to run before or after (respectively) 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.
Tagged Hooks
We can also indicate that @Before and @After only run with scenarios with certain tags
e.x. @Before(‘@web’) for tests needing a browser launched
Tagged hooks can have multiple tags, and follow similar tagging AND/OR rules that the runner does
Global Hooks
Cucumber doesn’t support global hooks, however, hacks are possible. Something like the below in Java could ensure that we have a method only running once at the beginning of our test
_@Before_ //performed before anything is done
**public void** setup() {
if ( _webEls_ == null ) {
_webEls_ = **new** LoadElements( _xmlFiles_ );
//set our database
if( System._getProperty_( "dataenvironment" ) != **null** ) {
_database_ = Databases._valueOf_( System._getProperty_( "dataenvironment" ).substring(1) );
}
}
_tests_.clear();
_tests_.add( _database_.getValidTestingInterfaces() );
}
_@Before_('@firefox') //performed before each web scenario
**public void** externalWebsite() {
_tests_.add( **new** ExternalWebsite( _webEls_, Browsers._Firefox_ ) );
}
_@Before_('@chrome') //performed before each web scenario
**public void** externalWebsite() {
_tests_.add( **new** ExternalWebsite( _webEls_, Browsers._Chrome_ ) );
}
So…with all of this setup, we can simplify our above steps even more with some tagging.
@CCOrg @CCNet
Feature: Testing for login page
Background:
When I login to CosmicComix
Scenario Outline: Check login page
Then I can see the \<Link> button
@Smoke @Firefox
Examples:
| **Link** |
| Home |
| Library |
| Store |
| ToS |
Scenario Outline: Check Links
And I select the \<Link> button
Then I see the text \<HelperText>
@Smoke @Firefox
Examples:
| **Link** | **HelperText** |
| Home | \[disabled\] |
| Library | see your comics |
| Store | purchase more comics |
| ToS | read through our terms of service |
Of course, depending on how our code was structured, we could potentially move the @Firefox tag higher up – say, the scenario level – but this will allow us to specify different browsers based on the test type. We could also specify more than more browser in our tags, and have the tests run on multiple browsers at once.