Background and Hooks for Cucumber-jvm

Explains how Cucumber background steps and hooks can reduce duplication and improve readability in feature files. Includes practical guidance for scenario, tagged, and pseudo-global hooks in Cucumber-JVM test suites.

Coveros Staff

February 20, 2014

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.

Coveros Staff

Coveros Staff

This post represents the collective insights of the Coveros team. Our staff consists of software experts who bring deep experience in secure agile development, DevOps, testing, and software quality. Over the past 20 years, Coveros has trained more than 30,000 professionals and worked with half of the Fortune 100 companies on mission-critical software development challenges. We draw on this extensive experience to share practical insights, proven strategies, and real-world solutions that help organizations build better software faster and more securely.