Cucumber data table – convert a three column table to a List

Cucumber is a tool for running automated acceptance tests written in a behavior-driven development (BDD) style. Cucumber is written in the Ruby programming language. Cucumber projects are available for other platforms beyond Ruby.

Cucumber works with Ruby, Java, .NET, Flex or web applications written in any language. It has been translated to over 40 spoken languages. – http://cukes.info/

The language that Cucumber understands is called Gherkin.

While Cucumber can be thought of as a “testing” tool, the intent of the tool is to support BDD. This means that the “tests” (plain text feature descriptions with scenarios) are typically written before anything else and verified by business analysts, domain experts, etc. non technical stakeholders. The production code is then written outside-in, to make the stories pass.

Cucumber itself is written in Ruby, but it can be used to “test” code written in Ruby or other languages including but not limited to Java, C# and Python.

In this example I will show you how we can use cucumber’s nice feature that helps us to use tables in our scenarios. The table can easily be converted to a list or map that we can use in our step.

Prerequisites

The following things are required in order to run the application

Eclipse Kepler
JDK 1.8
Have maven 3 installed and configured
Cucumber dependencies in pom.xml

Now we will see the below steps how to create a maven based project in Eclipse
Step 1. Create a standalone maven project in Eclipse

Go to File -> New -> Other. On popup window under Maven select Maven Project. Then click on Next. Select the workspace location – either default or browse the location. Click on Next. Now in next window select the row as highlighted from the below list of archtypes and click on Next button.

maven-arctype-quickstart

Now enter the required fields (Group Id, Artifact Id) as shown below

Group Id : com.roytuts
Artifact Id : cucumber-datatable

Step 2. Modify the pom.xml file as shown below.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.roytuts</groupId>
    <artifactId>cucumber-datatable</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>cucumber-datatable</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <jdk.version>1.8</jdk.version>
        <junit.version>4.11</junit.version>
        <cucumber.version>1.1.5</cucumber.version>
    </properties>

    <dependencies>
        <!-- cucumber -->
        <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>

        <!-- junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${jdk.version}</source>
                    <target>${jdk.version}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Step 3. If you see JRE System Library[J2SE-1.4] then change the version by below process

Do right-click on the project and go to Build -> Configure build path, under Libraries tab click on JRE System Library[J2SE-1.4], click on Edit button and select the appropriate jdk 1.8 from the next window. Click on Finish then Ok.

Step 4. Create src/test/resources folder, if it already does not exist, for putting the resource files.

Do right-click on the project and go New -> Source Folder. Give Folder name: as src/test/resources and click on Finish button.

Step 5. Create a feature files called bonuslist.feature under src/test/resources/cuke/flow/feature with the below content

Feature: An organization pays bonus to its employees due to outstanding profit

"""
The organization also calculates how much extra money it has to pay
to its employees in the financial year
"""

Scenario: An organization pays bonus based on designations
    Given an organization has 100000 employees
    When it pays bonus according to the designation
        | designation | bonus |  noOfEmployees  |
        |      HR     |  1000 |       100       |
        |      PM     | 50000 |      5000       |
        |   Sr. Dev   | 25000 |     15000       |
        |   Jr. Dev   | 15000 |     79900       |
    Then the organization has to pay total extra Rs. 1823600000 to 100000 employees

Step 6. Create a cucumber test runner class

package com.roytuts.cuke.flow;

import org.junit.runner.RunWith;

import cucumber.api.junit.Cucumber;
import cucumber.api.junit.Cucumber.Options;

@RunWith(Cucumber.class)
@Options(features = { "classpath:cuke/flow/feature/employeelist.feature" }, glue = "com.roytuts.cuke.flow.steps", monochrome = true, format = {
        "pretty", "html:target/cucumber", "json:target/Cucumber.json",
        "junit:target/Cucumber.xml" })
public class CukeEmployeeListRunner {

}

features – location of the feature file
glue – the package where the step definition class will be written
monochrome – whether we want the output in console in human readable format
format – in what format and where we want the generated output file

Step 7. Once we run the above class the following steps are generated in the console

@Given("^an organization has (\\d+) employees$")
public void an_organization_has_employees(int arg1) throws Throwable {
    // Express the Regexp above with the code you wish you had
    throw new PendingException();
}

@When("^it pays bonus according to the designation$")
public void it_pays_bonus_according_to_the_designation(DataTable arg1) throws Throwable {
    // Express the Regexp above with the code you wish you had
    // For automatic conversion, change DataTable to List<YourType>
    throw new PendingException();
}

@Then("^the organization has to pay total extra Rs. (\\d+) to (\\d+) employees$")
public void the_organization_has_to_pay_total_extra_Rs_to_employees(int arg1, int arg2) throws Throwable {
    // Express the Regexp above with the code you wish you had
    throw new PendingException();
}

Note: The parameter DataTable in step @When can be converted to any one of List<YourType>, List<List<E>>, List<Map<K,V>> or Map<K,V>, where E, K, V must be scalar, i.e., String, Integer, Date, enum, Double etc.

Step 8. Create a step definition class that will hold all generated steps with implementations. Modify the generated steps according to our needs

package com.roytuts.cuke.flow.steps;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import java.util.List;

import com.roytuts.cuke.model.EmpBonus;

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

public class BonusListSteps {

    private int totalEmployee;
    private int totalBonusAmt;

    @Given("^an organization has (\\d+) employees$")
    public void an_organization_has_employees(int totalEmployee)
            throws Throwable {
        this.totalEmployee = totalEmployee;
    }

    @When("^it pays bonus according to the designation$")
    public void it_pays_bonus_according_to_the_designation(
            List<EmpBonus> empBonus) throws Throwable {
        for (EmpBonus empBonus2 : empBonus) {
            Integer noOfEmployee = empBonus2.getNoOfEmployees();
            Integer bonusAmt = empBonus2.getBonus();
            totalBonusAmt += noOfEmployee * bonusAmt;
        }
    }

    @Then("^the organization has to pay total extra Rs. (\\d+) to (\\d+) employees$")
    public void the_organization_has_to_pay_total_extra_Rs_to_employees(
            int expTotalMoney, int expTotalEmployee) throws Throwable {
        assertThat(totalBonusAmt, is(expTotalMoney));
        assertThat(totalEmployee, is(expTotalEmployee));
    }

}

Step 9. Create a model class

package com.roytuts.cuke.model;

public class EmpBonus {

    private String designation;
    private Integer bonus;
    private Integer noOfEmployees;

    public String getDesignation() {
        return designation;
    }

    public void setDesignation(String designation) {
        this.designation = designation;
    }

    public Integer getBonus() {
        return bonus;
    }

    public void setBonus(Integer bonus) {
        this.bonus = bonus;
    }

    public Integer getNoOfEmployees() {
        return noOfEmployees;
    }

    public void setNoOfEmployees(Integer noOfEmployees) {
        this.noOfEmployees = noOfEmployees;
    }

}

Step 10. Run the cucumber test runner class at step 6. You will see the below output in the console.

Feature: An organization pays bonus to its employees due to outstanding profit
 
  """
  The organization also calculates how much extra money it has to pay
  to its employees in the financial year
  """

  Scenario: An organization pays bonus based on designations                        # cuke/flow/feature/bonuslist.feature:8
    Given an organization has 100000 employees                                      # BonusListSteps.an_organization_has_employees(int)
    When it pays bonus according to the designation                                 # BonusListSteps.it_pays_bonus_according_to_the_designation(EmpBonus>)
    Then the organization has to pay total extra Rs. 1823600000 to 100000 employees # BonusListSteps.the_organization_has_to_pay_total_extra_Rs_to_employees(int,int)

1 Scenarios (1 passed)
3 Steps (3 passed)
0m0.157s

That’s all. Thanks for reading.

Soumitra Roy Sarkar

I am a professional Web developer, Enterprise Application developer, Software Engineer and Blogger. Connect me on Roy Tutorials Twitter Facebook  Google Plus Linkedin Or Email Me

Leave a Reply

Your email address will not be published. Required fields are marked *