Skip to content

Cucumber

mpfotenhauer edited this page Jul 5, 2018 · 38 revisions

Cucumber is a Behavior-Driven Development(BDD) framework.

Table of Contents

Introduction

BDD is a technique in agile software development to achieve a close collaboration between the quality assurance and the business analysis parts of the team. The team focuses on the targets of the stakeholders. The user stories are written in a natural language that follows a known structure and utilizes certain keywords to provide some kind of API that can be used by the developers later on to implement the test automation.

Cucumber itself is a popular BDD framework that provides some structural elements to orchestrate the test and uses Gherkin a defined set of keywords to differentiate and organize the steps.

Structural elements:

  • Feature is equivalent to a JUnit test class
  • Scenario Outline is matching a JUnit test method
  • Background could be seen as a JUnit @Before annotated method to set up the environment for each test method in the same way
  • Examples is used to set up test data for a Scenario

Keywords:

It is good to know that the keywords are just used to build up a more natural language but the implementation it self doesn't differentiate between. This means you could use the And keyword all the time an it wouldn't make a difference for the execution of the script.

  • Given mostly the start of a scenario, but can be used for prerequisites
  • When a start to describe the interaction with the page
  • Then the keyword to bring up validation phrases
  • And is used to chain all kinds of phrases
  • But can be used to start and chain any kind of negative phrases

Example

The following example show some basic structure of a test case and demonstrates the usage of the keywords.

Feature: Browse

Scenario Outline: Browsing the catalog
  Given The browser "<browser>" is open
  And I am on the homepage of the Posters shop

  When I hover over "<categoryName>" and click on "<subCategoryName>"
  Then I want to be on a category page and see the "<subCategoryName>" as headline
  
  When I click on the product "<productName>"
  Then I want to be on a product detail page and see the "<productName>" as headline

  Examples:
    | browser         | categoryName    | subCategoryName | productName       |
    | Chrome_1024x768 | World of Nature | Animals         | Grizzly Bear      |
    | Chrome_1024x768 | Dining          | Main Dishes     | Tuna Steak        |
    | Chrome_1024x768 | Dining          | Sweets          | Colored Sprinkles |

Browser setup in Cucumber

Neodymium provides an utility class that can be called statically from you Cucumber support (hook) classes. It's called Driver and provides the functionality to setup and tear down WebDrivers. You can choose between the following two ways to setup a WebDriver via Neodymium. The tear down will stay the same for both. Please find a hands on example here: DriverHooks.java.

Setup via the test data

By calling a Cucumber Given step and passing the browser profile name via the standard test data mechanism you can call the Neodymium Driver class to setup the browser.

@Given("^\"([^\"]*)\" is open$")
public static void setUp(final String browserProfileName)
{
    Driver.setUp(browserProfileName);
}

Please see the following example for more hand on experience: Browse.feature

Setup via tagging a scenario with the browser profile name

If you don't need or want the extra step you can create a general before hook, that does the browser setup if it detects a configured browser profile name within the tags of the scenario.

@Before()
public static void setUp(Scenario scenario)
{
    Driver.setUpWithBrowserTag(scenario);
}

Please see the following example for more hand on experience: Search.feature

Note: Since we demonstrate both ways of setting up the WebDriver in the same project we had to add a special tag to the hook and the test case to avoid interferences. Probably you won't need this in your project.

Tear down

To tear down the WebDriver you just need to add a general hook. Beware you need to pass an order number below 10000 to run it after all other After hooks. Doing so you make sure that the browser will be teared down once all standard After steps have been executed.

@After(order = 100)
public void tearDown(Scenario scenario)
{
    Driver.tearDown(scenario);
}

Clean up steps in Cucumber

Sometimes test cases need a special setup on execution. In a perfect test world you could just start your test with a new prepared environment but since this can't be realized in every case you need to clean up after the test execution. Cucumber supports hooks to add an After step after a scenario but you can't share data between different step without further programming. We present an easy solution to the problem below.

How to use dependency injection to share data between the Cucumber steps

We demonstrate how to share data between steps using Cucumber PicoContainer. This technique is used to implement clean up steps for Register.feature

  1. Add Cucumber PicoContainer to to your project
<dependency>
    <groupId>info.cukes</groupId>
    <artifactId>cucumber-picocontainer</artifactId>
    <version>[Should match the Cucumber version of the Neodymium library]</version>
    <scope>test</scope>
</dependency>
  1. Implement a global storage object that can hold the data that is supposed to be shared. Please see GlobalStorage.java example.
    • This should ideally be a POJO that just holds data fields that can be other POJOs.
  2. Use dependency injection to set data. Please see DataSetup.java example.
    • The GlobalStorage is passed in via constructor dependency injection into the setup class.
    • We introduced this extra class in order to avoid messing up your page objects with data set up for cucumber. One reason is that this would be needlessly executed during the Neodymium test. The other reason is that the a second constructor would be needed, since the Selenide page concept relies on a constructer without arguments and this causes more struggle for the page object code.
  3. Use dependency injection to read the data. Please see UserHooks.java example.
    • The GlobalStorage is passed in via constructor dependency injection into the hook class.
    • The @After annotation registers a hook after a scenario which is tagged with the tag given to the annotation. See Cucumber documentation for more information.
Clone this wiki locally