The new Certification Class of REST With Spring is out:

>> CHECK OUT THE COURSE

1. Introduction

Cucumber is a BDD (Behavioral Driven Development) testing framework.

Using the framework to write repetitive scenarios with different permutations of inputs/outputs can be quite time-consuming, difficult to maintain and of course frustrating.

Cucumber came with a solution for reducing this effort by using the concept of Scenario Outline coupled with Examples. In the below section, we will try to take up an example and see how can we minimize this effort.

If you want to read more about the approach and Gherkin language, have a look at this article.

2. Adding Cucumber Support

To add support for Cucumber in a simple Maven project, we will need to add the following dependencies:

<dependency>
    <groupId>info.cukes</groupId>
    <artifactId>cucumber-junit</artifactId>
    <version>1.2.5</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>info.cukes</groupId>
    <artifactId>cucumber-java</artifactId>
    <version>1.2.5</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-library</artifactId>
    <version>1.3</version>
    <scope>test</scope>
</dependency>

Useful links to dependencies from Maven Central: cucumber-junitcucumber-javahamcrest-library

Since these are testing libraries, they don’t need to be shipped with the actual deployable – which is why they’re all test scoped.

3. A Simple Example

Let’s demonstrate both a bloated way and a concise way of writing featured files. Let’s first define the logic we want to write a test for:

Let’s first define the logic we want to write a test for:

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
}

4. Defining Cucumber Tests

4.1. Defining a Feature File

Feature: Calculator
  As a user
  I want to use a calculator to add numbers
  So that I don't need to add myself

  Scenario: Add two numbers -2 & 3
    Given I have a calculator
    When I add -2 and 3
    Then the result should be 1
   
  Scenario: Add two numbers 10 & 15
    Given I have a calculator
    When I add 10 and 15
    Then the result should be 25

As seen here, 2 different combinations of numbers have been put to test here the addition logic. Apart from numbers, all the scenarios are exactly the same.

4.2. “Glue” Code

In order to test out these scenarios, i’s essential to define each step with corresponding code, in order to translate a statement into a functional piece of code:

public class CalculatorRunSteps {

    private int total;

    private Calculator calculator;

    @Before
    private void init() {
        total = -999;
    }

    @Given("^I have a calculator$")
    public void initializeCalculator() throws Throwable {
        calculator = new Calculator();
    }

    @When("^I add (-?\\d+) and (-?\\d+)$")
    public void testAdd(int num1, int num2) throws Throwable {
        total = calculator.add(num1, num2);
    }

    @Then("^the result should be (-?\\d+)$")
    public void validateResult(int result) throws Throwable {
        Assert.assertThat(total, Matchers.equalTo(result));
    }
}

4.3. A Runner Class

In order to integrate features and the glue code, we can use the JUnit runners:

@RunWith(Cucumber.class)
@CucumberOptions(
  features = { "classpath:features/calculator.feature" },
  glue = {"com.baeldung.cucumber.calculator" })
public class CalculatorTest {}

5. Rewriting Features Using Scenario Outlines

We saw in Section 4.1. how defining a feature file can be a time-consuming task and more error prone. The same feature file can be reduced to mere few lines using the Scenario Outline:

Feature: Calculator
  As a user
  I want to use a calculator to add numbers
  So that I don't need to add myself

  Scenario Outline: Add two numbers <num1> & <num2>
    Given I have a calculator
    When I add <num1> and <num2>
    Then the result should be <total>

  Examples: 
    | num1 | num2 | total |
    | -2 | 3 | 1 |
    | 10 | 15 | 25 |
    | 99 | -99 | 0 |
    | -1 | -10 | -11 |

When comparing a regular Scenario Definition with Scenario Outline, values no longer need to be hard-coded in step definitions. Values are replaced with parameters as <parameter_name> in step-definition itself.

At the end of Scenario Outline, values are defined in a pipe-delimited table format using Examples.

A sample to define Examples is shown below:

Examples:
  | Parameter_Name1 | Parameter_Name2 |
  | Value-1 | Value-2 |
  | Value-X | Value-Y |

6. Conclusion

With this quick article, we’ve shown how scenarios can be made generic in nature. And also reduce effort in writing and maintaining these scenarios.

The complete source code of this article can be found over on GitHub.

Go deeper into building a REST API with Spring:

>> CHECK OUT THE COURSE