Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

BDD: Cucumber in Action

DZone's Guide to

BDD: Cucumber in Action

Cucumber is an open-source tool that is used to support Behavior Driven Development with plain text specifications. Let's take a look at a working example.

· DevOps Zone
Free Resource

The Nexus Suite is uniquely architected for a DevOps native world and creates value early in the development pipeline, provides precise contextual controls at every phase, and accelerates DevOps innovation with automation you can trust. Read how in this ebook.

Cucumber is an open-source tool that is used to support Behavior Driven Development with plain text specifications. Implementations of Cucumber exist for number of platforms, including Java.

BDD generally comes into action with Agile-based development where every shippable piece of code includes a bunch of features. So, while development of a feature is under progress before that, there should be scenarios and test cases made available in order to ensure that the feature is doing what it is intend to do. Cucucmber is making this possible in scenarios that specify in a plain text file very precisely and clearly using plain English to include details validating the feature with respect to the scenarios. Cucumber is getting executed in automated tests the same as it is in unit tests. 

When Cucumber executes a Step in a Scenario, it looks for a matching Step Definition to execute. To do this, the Step Definitons use regular expressions to form the method name that matches with the feature's scenario. Cucumber takes the feature file as an input where Steps are defined and links it with the Step Definition, which is a Java code.

Step Definitions sources must be placed in a file where Cucumber can find them. Let's take a look at a working example.

The project structure will look like the below picture:

Image title

The Java code is supposed to go under Test. This file will be in the src/main/java folder.

Calculator.java:

package test.cucumber.calc;
/**
 * Actual calculator business class which is suppose to get tested
 * @author arun.pandey
 */
public class Calculator {
  private int val1;
  private int val2;

  public Calculator(int val1, int val2){
    this.val1 = val1;
    this.val2 = val2;
  }
  public int add(){
    return val1 + val2;
  }
  public int subtract(){
    return val1 - (val2);
  }
  public int multiply(){
    return val1 * val2;
  }
  public int divison(){
    return val1/val2;
  }
}


Now, let's create the feature that will have the scenario seen below:.

Calc.feature:

Feature: Calculator
    Scenario: calculate add
        Given I have a calc with 12 3
        When I ask it to say add
        Then it should answer with add 15

    Scenario: calculate subtract
        Given I have a calc with 12 3
        When I ask it to say subtract
        Then it should answer with sub 9 

    Scenario: calculate multiply
        Given I have a calc with 12 3
        When I ask it to say multiply
        Then it should answer with mul 36 

    Scenario: calculate divide
        Given I have a calc with 12 3
        When I ask it to say divide
        Then it should answer with div 4   

The next step is to create the Step Definition for the above features, as shown below:

CalculatoeStepDefs.java:

package test.cucumber.calc
import static org.junit.Assert.assertEquals;

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

/**
 * This is to define the testing steps as per feature definition
 * @author arun.pandey
 *
 */
public class CalculatorStepDefs {
  private Calculator calc;
  private int res;

  @Given("^I have a calc with (\\d+) (\\d+)$")
  public void I_have_a_calc_with(int arg1, int arg2) throws Throwable {
    calc = new Calculator(arg1, arg2);
  }

  @When("^I ask it to say add$")
  public void I_ask_it_to_say_add() throws Throwable {
    res = calc.add();
  }

  @Then("^it should answer with add (\\d+)$")
  public void it_should_answer_with_add(int expectedRes) throws Throwable {
    assertEquals(expectedRes, res);
  }

  @When("^I ask it to say subtract$")
  public void I_ask_it_to_say_subtract() throws Throwable {
    res = calc.subtract();
  }

  @Then("^it should answer with sub (\\d+)$")
  public void it_should_answer_with_sub(int expectedRes) throws Throwable {
    assertEquals(expectedRes, res);
  }

  @When("^I ask it to say multiply$")
  public void I_ask_it_to_say_multiply() throws Throwable {
    res = calc.multiply();
  }

  @Then("^it should answer with mul (\\d+)$")
  public void it_should_answer_with_mul(int expectedRes) throws Throwable {
    assertEquals(expectedRes, res);
  }

  @When("^I ask it to say divide$")
  public void I_ask_it_to_say_divide() throws Throwable {
    res = calc.divison();
  }

  @Then("^it should answer with div (\\d+)$")
  public void it_should_answer_with_div(int expectedRes) throws Throwable {
    assertEquals(expectedRes, res);
  }
}

Next, let's create the actual main class that will be responsible for the execution of the test cases.

RunCukesTest.java:

package test.cucumber
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;

/**
 * Main class to invoke the tests, and it must be run as JUnit TC's
 * @author arun.pandey
 */
@RunWith(Cucumber.class)
@CucumberOptions(format = {"html:target/cucumber-html-report", "json:target/cucumber-json-report.json"})   
public class RunCukesTest {

}

Now, let's execute the RunCukeTest.java and run it as the JUnit test cases. You can see the result in Eclipse below:

Image title

If you have added the Maven support in your project, then you can run it as mvn clean install.

You should see the result below:

Image title

Hopefully, this has helped you better understand the Cucumber framework.

The DevOps Zone is brought to you in partnership with Sonatype Nexus.  See how the Nexus platform infuses precise open source component intelligence into the DevOps pipeline early, everywhere, and at scale. Read how in this ebook

Topics:
bdd ,devops ,cucumber ,open source

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}