January 6, 2017

BDD Testing with Cucumber, Java and JUnit

Introduction

BDD (Behaviour-Driven Development) is about designing code by defining your application in terms of behavior.

You start by gathering Tester, Developer and Product Owner (The Three Amigos) and define User Stories. These User Stories are given a Feature name and each Feature is broken down into a Scenario with Steps defines with the keywords: Given, When and Then

Cucumber

Now in Cucumber you write your User Stories (=Feature) in a language called Gherkin. Example:


Feature: Cash withdrawal 

Scenario: Withdrawal from an account in credit 
    Given I have deposited $100.00 in my account 
    When I withdraw $20 
    Then $20 should be dispensed 

Maven Dependency

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>info.cukes</groupId>
    <artifactId>cucumber-java</artifactId>
    <version>${cucumber.version}</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>info.cukes</groupId>
    <artifactId>cucumber-junit</artifactId>
    <version>${cucumber.version}</version>
    <scope>test</scope>
</dependency>

Cucumber Code Structure

All code (production code, test code and gherkin code) must be placed in the same catalog structure.

  • Production Code - src/main/java/se/magnuskkarlsson/examples/cucumber/Account.java
  • Test Code - src/test/java/se/magnuskkarlsson/examples/cucumber/AccountTest.java
  • Test Code - src/test/java/se/magnuskkarlsson/examples/cucumber/AccountSteps.java
  • Gherkin Code - src/test/resources/se/magnuskkarlsson/examples/cucumber/cash_withdrawal.feature

Cucumber Test Code

We need two classes: one JUnit wrapper class and one Cucumber class that implements the steps in your Gherkin Code.

package se.magnuskkarlsson.examples.cucumber;

import org.junit.runner.RunWith;

import cucumber.api.junit.Cucumber;

@RunWith(Cucumber.class)
public class AccountTest {

}
package se.magnuskkarlsson.examples.cucumber;

import static org.hamcrest.CoreMatchers.is;

import org.junit.Assert;

import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class AccountSteps {

    Account account = new Account();

    @Given("^I have deposited \\$(\\d+) in my account$")
    public void deposit(int amount) {
        account.deposit(amount);
    }

    @When("^I withdraw \\$(\\d+)$")
    public void withdraw(int amount) {
        account.withdraw(amount);
    }

    @Then("^My balance should be \\$(\\d+)$")
    public void verifyBalance(int balance) {
        Assert.assertThat(balance, is(account.getBalance()));
    }
}

Verify

You can now either run you JUnit test class AccountTest inside your IDE or run complete test from command line as usual in maven: mvn clean install.

No comments: