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.

34 thoughts to “Background and Hooks for Cucumber-jvm

  • Pavan

    How can we glue step definition from a different .jar file? For example, i have more than one project which all uses same set of step definitions. So, can i keep these step definitions in a .jar file and glue that package name while running it? I tried doing it but getting steps are undefined error. Appreciate your help!

    Thanks,
    Pavan

    Reply
    • Max Saperstone

      Hi Pavan,
      I’ve never tried this before, and without some working examples, I’m not sure how to even go about it.
      I’d assume that if you include that jar in your classpath, you’d then need to also include the path to those classes where you define the location of your test steps.

      Reply
  • kattamudi Koteswara

    HI,

    I am working csharp framework with Gherkin BDD Test AUtomation, You know i was unable to get the info related to how to Skip Gherkin scenarios in Csharp as well as tagged hooks at
    at Gherkin scenario level ( nothing but prioritizing the scenarios).

    Please help me out .

    Reply
    • Max Saperstone

      Hi Kattamudi,
      What C# framework are you using? Is this cucumber implemented in C#? Are you trying to skip certain scenarios in a feature, an entire feature, or something else?
      Have you looked at tagging your scenarios, and only running against certain tags. The @wip tag is typically used to indicate a work in progress, and those tests can be easily skipped.

      Reply
  • Chandrakanth B

    If there are multiple after hooks defined, is there any way we can force one of the after hooks to run before the another?

    Reply
    • Max Saperstone

      It really depends on the framework you are using behind Cucumber. Some frameworks have multiple hooks for before/after that you can specify an order to (such as TestNG)

      Reply
  • Garima

    Hi,

    Can we run the background with run time data as parameter?
    If not, is it possible to pass the data to @Before method from the scenario test data?
    Such as passing a db query to be executed before each test scenario.

    Reply
    • Max Saperstone

      Absolutely. Anything you want to setup beforehand definitely belongs in the Background steps.
      What I like to do is use those background steps to call out specific setup steps, which in Java (or whatever other language you are using) would then execute your db query (in your case).
      It is essentially doing the same thing as using the @Before annotation, but it allows the user reading through the Gerkin to have a better understanding of what is going on

      Reply
  • Balaji

    Is it possible to NOT run the background step for a particular scenario? I know its not a sensible thing to do, however business wants it that way.

    Reply
    • Max Saperstone

      If that’s something you are interested in doing, I would suggest moving that scenario out of the feature. The idea of the background steps is to run for similar tests. If a particular test doesn’t need that background, then I would argue it’s not a similar test, and should be moved

      Reply
      • Balaji

        Thats exactly what I said but they(business) seem to think it’ll be more maintainable if you put it all in one feature file. So that option is out. I can always write some steps to backtrack and do my required steps after the background is run. I was just wondering if there was a simpler way to just skip the background for one particular scenario.

        Reply
        • Max Saperstone

          Well, I guess I’m glad we’re on the same page. Anything you’d need to do to get the background steps to run on some scenarios and not others is going to be less maintainable than having two separate feature files (which should require no additional maintenance). So unfortunately, no I’m not aware of anything to meet your criteria. Good luck!

          Reply
  • Balaji

    Thanks anyway.

    Reply
  • Raghu Ram

    Hey,
    I am trying to run the same kind of feature file with scenario outline and inputs were given as table format like yours but my tests are skipping. I am trying to run through command line and my project is maven. Any suggestions

    Reply
    • Max Saperstone

      What command are you using to execute the tests? What does the screen output show? How is your POM configured? Are you providing the correct tags?

      Reply
  • Raghu Ram

    mvn -Dtest=testname test is the command i am using and in my pom file i am using maven surefire plugin.The text file containing my test output says Tests run: 24, Failures: 0, Errors: 0, Skipped: 20, Time elapsed: 0.486 s

    Reply
    • Max Saperstone

      Do the surefire reports give any indication of why they are skipping? Do you have a custom listener or transformer? It seems like either an issue with your pom setup, or your test runner

      Reply
  • Ilayaraja

    I am trying to reuse the @Before and @After hooks in my framework.
    Example :
    I have Feature 1 and Feature 2 with few scenarios in each
    I have @Login – Tagged hooks to run before the first scenario of the feature file
    And I have @Logout – Tagged hook to run after the last scenario in feature file with logout step and quit driver.
    I am trying to reuse the @Login(Before) and @Logout (After) in both feature file, but the issue is that the first feature execute and logs out
    But for the second feature its throwing session id is null though i see the new webdriver is invoked

    Login hook’s class extends the abstract page though.
    public class LoginPage extends AbstractPage {
    public LoginPage(WebDriver driver){
    super(driver);
    }
    Is there a best way to reuse the tagged hooks across the feature?

    Reply
    • Max Saperstone

      this sounds like an issue with your tests not being thread safe. Have you tried running these tests with a debugger? How many Scenarios do you have in each Feature? There is no reason you can’t re-use hooks in multiple feature files, assuming everything is getting properly instantiated.

      Reply
  • amber

    Hi all,

    What would be your approach in my case: Most of the test cases starts with a login which would be some kind of background. Is it actually “normal” to put 60(less or more, it doesnt matter) scenarios into one feature file with the same background or there is another solution?

    Reply
    • Max Saperstone

      Best practice seems to indicate only 12-15 scenarios in a feature. Often times, if you have more than that, you’re really looking at more than one feature, or you can convert some of your scenarios into scenario outlines. If you have that many scenarios, look at splitting them up, and maybe even try grouping them by initial steps, in this sense, pulling out tests cases with login and navigational test steps that match

      Reply
  • Carlos Villa

    Hi Max
    I need to know how run an scenario outline where the example has more of two registers, e.g
    Examples: Buttons
    | letter |
    | A |
    | B |
    but an only session, without the browser is closed.
    I am automation a page where I do an initial logging and so i need to create more than two registers, but the browser is closed for any register and it is open for every new register to create.
    I need to create all the registers in a single session

    Reply
    • Max Saperstone

      First off, you shouldn’t be doing this. Tests should remain independent and idempotent, and what you’re asking for is purposeful dependencies. What happens if A fails? How does that impact B? I would strongly suggest you reconsider how you are writing your tests. Cucumber sees these as independent tests, you should too.
      All that said, how are you opening/closing your browsers? My guess is it’s through a before and after method, which run which with each test. Cucumber doesn’t have a notion of beforeClass or beforeSuite like TestNG and JUnit do. You could instead look at turning your Befores or Afters into Singletons, or instead, look at modifying your listener to use their onStart and onFinish to accomplish that. But again, you shouldn’t, this is bad testing practice

      Reply
  • CS

    Lets say I have a simple scenario and not a scenario outline, which I want to run first on Webapp and then on the desktop app. Can I annotate with both ‘Webapp’ and ‘Desktopapp’ and then have Before for each tags? Will it force the feature to execute first on the web and then on the desktop?

    Example:
    @WebApp @DesktopApp
    Scenario: verify new user page for new apps
    Given user ‘testuser’ exists
    When the user logs in as ‘testuser’
    Then the user should see home page

    Reply
  • Pingback: Using Dependency Injectors to Simplify Your Code in Cucumber

  • Pingback: Making Cucumber Glue Code More Explicit with Transformers - Coveros

  • Aj

    Hey,
    I have @before and @after hooks in my code and there are some condition (As per DB query results ) I want to execute my scenario.
    Consider, I am getting DB query results as True then only my scenario should get executed else scenario should mark as Skipped.
    Using Cucumber with Java and selenium.

    Thanks In advance !!!

    Reply
    • Max Saperstone

      So, I’ve been successful in doing this not using hooks, but instead writing a custom listener.
      If you are running these once before running anything, you override the `onStart` method call with these db queries, and store the responses
      If not, you can run them each time overriding the `onTestStart` method call. Then, simply check for the response, and if it’s a failure, or whatever response you don’t want, you can skip the test by throwing a `SkipException`. I’m in the middle of writing a post on this. I’ll post a link once it’s done which will have more details

      Reply
  • shashi

    Hi Max,

    i ned your help for hooks.

    Can we use @AfterStep and @BeforeStep in Cucumber Selenium Java.
    If yes then what should be gherkin, selenium, cucumber-java version.

    Because where i used @Afterstep this method is not calling at any time.

    Please help me for this.

    Thanks,

    Reply
    • Max Saperstone

      No, unfortunately, before and after are the only supported annotations

      Reply
  • Dinesh

    Hi Max,
    I would like to run some steps before the start of feature file and after the end of feature file. Please guide me which hook i can use in this case.
    Thanks

    Reply
    • Max Saperstone

      Unfortunately, Cucumber doesn’t have annotations like that. You can setup some custom tags to try to deal with this, but I’d wonder why you’d want that. Based on the answer, I’m happy to suggest some alternatives

      Reply
  • piyush

    Hi.. i need to know something, i am looking if there is way to invoke specific hooks from scenario itself, for ex if i have two hooks and i want second hook to invoke but that should be invoked by scenario not by using tagged hooks.

    Reply
    • Max Saperstone

      I’m not certain I follow what you’re looking for. What are you trying to accomplish with this?

      Reply

Leave a comment

Your email address will not be published. Required fields are marked *

X