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.
Join the DZone community and get the full member experience.
Join For FreeCucumber 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:
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:
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:
Hopefully, this has helped you better understand the Cucumber framework.
Opinions expressed by DZone contributors are their own.
Comments