Hello Cucumber

It’s a bit difficult to try to use Cucumber following official document. So here I’m documenting my experience on setting up Cucumber together with Junit.

Dependencies

Frist, create a new Maven project, and then setup the dependencies:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<cucumber.version>7.34.3</cucumber.version>
<junit-platform.version>6.0.3</junit-platform.version>
<junit-jupiter.version>6.0.3</junit-jupiter.version>
</properties>

<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<version>${junit-platform.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.27.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit-platform-engine</artifactId>
<version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

Test Runner

Next, create a test runner class src/test/java/org/example/RunCucumberTest.java.

1
2
3
4
5
6
7
8
9
10
11
package org.example;

import org.junit.platform.suite.api.*;

@Suite
@SelectPackages("features")
@IncludeEngines("cucumber")
@ConfigurationParameter(key = "cucumber.plugin", value = "pretty, html:target/cucumber-reports/Cucumber.html")
@ConfigurationParameter(key = "cucumber.glue", value = "org.example.stepdefinitions")
public class RunCucumberTest {
}

Feafure File

Now we are good to create our feature file src/test/resources/features/is_it_friday_yet.feature,

1
2
3
4
5
6
7
8
9
10
11
12
13
Feature: Is it Friday yet?
Everybody wants to know when it's Friday

Scenario Outline: Today is or is not Friday
Given today is "<day>"
When I ask whether it's Friday yet
Then I should be told "<answer>"

Examples:
| day | answer |
| Friday | TGIF |
| Sunday | Nope |
| anything else ! | Nope |

Step Definitions

And step definitions src/test/java/org/example/stepdefinitions/Stepdefs.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package org.example.stepdefinitions;

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

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

class IsItFriday {
static String isItFriday(String today) {
return "Friday".equals(today) ? "TGIF" : "Nope";
}
}

public class Stepdefs {
private String today;
private String actualAnswer;

@Given("today is {string}")
public void today_is(String today) {
this.today = today;
}

@When("I ask whether it's Friday yet")
public void i_ask_whether_it_s_Friday_yet() {
actualAnswer = IsItFriday.isItFriday(today);
}

@Then("I should be told {string}")
public void i_should_be_told(String expectedAnswer) {
assertThat(actualAnswer).isEqualTo(expectedAnswer);
}
}

Let’s run the test with mvnd clean test:

1
2
3
4
5
6
7
8
9
10
11
12
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.424 s -- in org.example.RunCucumberTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] --------------------------------------------------------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] --------------------------------------------------------------------------------------------------------------------------
[INFO] Total time: 3.345 s (Wall Clock)
[INFO] Finished at: 2026-03-09T21:52:04+08:00
[INFO] --------------------------------------------------------------------------------------------------------------------------

A nice report is generated under target/cucumber-reports/Cucumber.html.

Intellij IDEA Plugin

To run test directly within Intellij IDEA, we can install the Cucumber for Java plugin, then we’ll see a green play button next to the feature file.

Tag

We can also tag features or scenarios, e.g.,

1
2
@smoke
Feature: Is it Friday yet?

Tag name can be anything, tag name is NOT Java type, not Java annotation.

With tag, we can run a subset of tests,

1
mvnd clean test -Dcucumber.filter.tags=@smoke

Cucumber with REST-assured

We can also use Cucumber together with REST-assured.

Dependencies

First, add dependencies:

1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>6.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>tools.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>3.1.0</version>
<scope>compile</scope>
</dependency>

Feature File

And then define a feature in file src/test/resources/features/view_comments.feature,

1
2
3
4
5
6
7
8
9
10
11
12
13
Feature:  View comments
User wants to view comments

Scenario Outline: User wants to view comments of a specific post
Given there is a post with id <id>
When user view comments of the post
Then each comment should be with post id equals to <id>
And each comment should be with non-blank body

Examples:
| id |
| 1 |
| 2 |

Step Definitions

Next, create one another step definition class src/test/java/org/example/stepdefinitions/ViewCommentsStepdefs.java,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package org.example.stepdefinitions;

import io.cucumber.java.en.And;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import io.restassured.common.mapper.TypeRef;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;

import java.util.List;

import static io.restassured.RestAssured.given;
import static org.assertj.core.api.Assertions.assertThat;

record Comment(long postId, long id, String name, String email, String body) {
}

public class ViewCommentsStepdefs {
RequestSpecification request;
Response response;
List<Comment> comments;
String BASE_URI = "https://jsonplaceholder.typicode.com";

@Given("there is a post with id {long}")
public void there_is_a_post_with_id(long id) {
request = given()
.baseUri(BASE_URI)
.pathParams("id", id);
}

@When("user view comments of the post")
public void user_view_comments_of_the_post() {
response = request
.get("/posts/{id}/comments");
comments = response.as(new TypeRef<>() {
});
}

@Then("each comment should be with post id equals to {long}")
public void each_comment_should_be_with_post_id_equals_to(long id) {
assertThat(comments).allMatch((comment) -> comment.postId() == id);
}

@And("each comment should be with non-blank body")
public void each_comment_should_be_with_non_blank_body() {
assertThat(comments).noneMatch((comment) -> comment.body().isBlank());
}
}