Cucumber Data Table – Convert One Column Table to a List

Introduction

In this post you will see an example on cucumber data table – convert one 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.

Related Post:

Prerequisites

Java at least 1.8, Cucumber 1.2.5/6.10.3, Junit 4.12/5.8.0-M1, Maven 3.6.3

In this example I will show you how you 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 you can use in your step.

Project Setup

Create a maven based project in your favorite IDE or tool. The name of the project is java-cucumber-data-table-to-list. You can use any one of the following pom.xml files according to your version of Cucumber and Junit.

Cucumber 1.2.5, Junit 4.12:

<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>java-cucumber-data-table-to-list</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <url>http://maven.apache.org</url>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <jdk.version>1.8</jdk.version>
        <junit.version>4.12</junit.version>
        <cucumber.version>1.2.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>

Cucumber 6.10.3, Junit 5.8.0-M1:

<?xml version="1.0" encoding="UTF-8"?>

<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>java-cucumber-data-table-to-list</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>12</maven.compiler.source>
		<maven.compiler.target>12</maven.compiler.target>
	</properties>

	<dependencies>
		<dependency>
			<groupId>io.cucumber</groupId>
			<artifactId>cucumber-java</artifactId>
			<version>6.10.3</version>
		</dependency>

		<dependency>
			<groupId>io.cucumber</groupId>
			<artifactId>cucumber-junit</artifactId>
			<version>6.10.3</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.junit.jupiter</groupId>
			<artifactId>junit-jupiter-engine</artifactId>
			<version>5.8.0-M1</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.junit.vintage</groupId>
			<artifactId>junit-vintage-engine</artifactId>
			<version>5.8.0-M1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
			</plugin>
		</plugins>
	</build>
</project>

Test Resources

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.

Feature File

Create a feature files called sum.feature under src/test/resources/cuke/flow/feature with the below content:

Feature: Calculate total from a list of real numbers
Scenario: Calculate summation of a list of real numbers
    Given a list of real numbers
        |25.0|
        |1500.0|
        |580.0|
        |600.0|
    When I calculate the sum of them
    Then I will get 2705.0

Test Runner Class

Create a cucumber test runner class as shown below. The import statements are different for the different version of the Cucumber framework. So make sure you use the correct imports.

package com.roytuts.cuke.flow;

import org.junit.runner.RunWith;

//Cucumber 1.2.5
//import cucumber.api.CucumberOptions;
//import cucumber.api.junit.Cucumber;
//Cucumber 1.2.5

import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;

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

}

In the above class I have configured below features using @CucumberOptions:

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

Running the Runner Class

Once you run the above class the following steps are generated in the console:

Feature: Calculate total from a list of real numbers
  Scenario: Calculate summation of a list of real numbers # cuke/flow/feature/sum.feature:3
    Given a list of real numbers
    When I calculate the sum of them
    Then I will get 2705.0
1 Scenarios (1 undefined)
3 Steps (3 undefined)
0m0.000s
You can implement missing steps with the snippets below:
@Given("^a list of real numbers$")
public void a_list_of_real_numbers(DataTable arg1) throws Throwable {
    // Write code here that turns the phrase above into concrete actions
    // For automatic transformation, change DataTable to one of
    // List<YourType>, List<List<E>>, List<Map<K,V>> or Map<K,V>.
    // E,K,V must be a scalar (String, Integer, Date, enum etc)
    throw new PendingException();
}
@When("^I calculate the sum of them$")
public void i_calculate_the_sum_of_them() throws Throwable {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}
@Then("^I will get (\\d+)\\.(\\d+)$")
public void i_will_get(int arg1, int arg2) throws Throwable {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}

In the above class you see that the methods have been generated from the feature file and you also see that each of the method throws PendingException() because I have not yet implemented any step defined in feature file.

Note: The parameter DataTable in step @Given 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 Definition Class

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

package com.roytuts.cuke.flow.steps;

import java.util.List;

//Cucumber 1.2.5
//import org.hamcrest.CoreMatchers;
//import org.junit.Assert;
//import cucumber.api.java.en.Given;
//import cucumber.api.java.en.Then;
//import cucumber.api.java.en.When;
//Cucumber 1.2.5

import org.junit.jupiter.api.Assertions;

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

public class SumSteps {

	private double sum;
	private List<Double> numbers;

	@Given("^a list of real numbers$")
	public void a_list_of_real_numbers(List<Double> numbers) throws Throwable {
		this.numbers = numbers;
	}

	@When("^I calculate the sum of them$")
	public void I_calculate_the_sum_of_them() throws Throwable {
		for (Double number : numbers) {
			sum += number;
		}
	}

	@Then("^I will get (\\d+\\.\\d+)$")
	public void I_will_get_(Double expectedTotal) throws Throwable {
		// Assert.assertThat(sum, CoreMatchers.is(expectedTotal)); //Junit 4
		Assertions.assertEquals(sum, expectedTotal); //Junit 5
		System.out.println("Actual Sum : " + sum);
	}

}

Now notice I have implemented all steps which I have declared in feature file and now you should not get any exception while you execute the Runner class.

Re-running the Runner Class

Execute the cucumber test runner class I created earlier. You will see the below output in the console.

Feature: Calculate total from a list of real numbers
Actual Sum : 2705.0
  Scenario: Calculate summation of a list of real numbers # cuke/flow/feature/sum.feature:3
    Given a list of real numbers                          # SumSteps.a_list_of_real_numbers(Double>)
    When I calculate the sum of them                      # SumSteps.I_calculate_the_sum_of_them()
    Then I will get 2705.0                                # SumSteps.I_will_get_(Double)
1 Scenarios (1 passed)
3 Steps (3 passed)
0m0.352s

Hope you got an idea on how to convert one column datatable to a list.

Source Code

Download

Leave a Reply

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