< Back

Getting Started with Cucumber Testing: A Step-by-Step Guide

Author

b.ignited

Date

24/10/2023

Share this article

In this blog post, we will be creating a basic Java project with Cucumber, TestNG, Maven, and IntelliJ IDEA.

Required tools

A BDD test framework is used to define the behaviour of an application in a concise language which defined by the strict but simple grammar. This grammar is defined in a domain-specific language (DSL), such as:

  • Cucumber (DSL: Gherkin)

  • Behat (DSL: Gherkin)

  • Mocha (DSL: user-defined)

Next, we need a test runner to run our tests automatically, for example:

  • TestNG (Java)

  • JUnit (Java)

  • Mocha (Javascript)

  • ….

An integrated development environment (IDE) to write our tests in.

  • IntelliJ

  • VScode

  • ….

Step 1: Create a project in IntelliJ

Create a new project inside IntelliJ ( File > New > Project ) and choose for a Maven project

Enter a GroupId and Artifactid for your project, then choose a space on your computer where you would like to save your project.

Step 2: Add dependencies and plugins

Adding dependencies to your project is done by editing the pom.xml file. Click on ‘enable Auto-Import' to automatically import dependencies as you add them to the file. There is an alternative way to enable auto-import if this pop-up does not automatically display for you. Go to (File > Settings > search for Maven > select importing > click enable Import Maven Projects automatically)

Then add the following dependencies and plugins to your pom.xml:

<?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>sample.cucumber</groupId> 
    <artifactId>sample.cucumber</artifactId> 
    <version>1.0-SNAPSHOT</version> 
 
    <build> 
        <plugins> 
            <plugin> 
                <groupId>org.apache.maven.plugins</groupId> 
                <artifactId>maven-resources-plugin</artifactId> 
                <version>2.4</version> 
            </plugin> 
            <plugin> 
                <groupId>org.apache.maven.plugins</groupId> 
                <artifactId>maven-surefire-plugin</artifactId> 
                <version>2.14.1</version> 
                <configuration> 
                    <suiteXmlFiles> 
                        <suiteXmlFile>src/test/java/testng.xml</suiteXmlFile> 
                    </suiteXmlFiles> 
                </configuration> 
            </plugin> 
        </plugins> 
    </build> 
 
    <dependencies> 
        <dependency> 
            <groupId>io.cucumber</groupId> 
            <artifactId>cucumber-java</artifactId> 
            <version>4.3.0</version> 
        </dependency> 
 
        <dependency> 
            <groupId>io.cucumber</groupId> 
            <artifactId>cucumber-testng</artifactId> 
            <version>4.3.0</version> 
        </dependency> 
 
    </dependencies> 
     
</project> 

Next, you have to add the cucumber plugin for Java to IntelliJ. This can be done by going to File > settings > plugins > Install JetBrains plugin… > search for cucumber for Java > install.  

IntelliJ will ask to restart after the plugin has been installed, allow IntelliJ to restart and continue with Step 3.

Step 3: Create your testng.xml file

Create a testng.xml file in src/test/Java and add the following lines to the file:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> 
<suite name="Test suite" parallel="methods"> 
    <test name="Google"> 
        <classes> 
            <class name="TestRunner"/> 
        </classes> 
    </test> 
</suite> 

Step 4: Writing a feature file

Create a new folder called “resources” in the src/test directory. Then, create a new folder called “features” in the resources directory. This feature folder holds all our feature files. These are files that contain the description of our steps, written in a DSL language. In our case, we’ll be making use of the DSL called Gherkin. This DSL language has a couple of keywords we can use, namely:

  • Feature
    Is only used for documentation purposes. It has a title, a description, and at least one or more scenarios.

  • Scenario
    A scenario has a title and description, just like a feature. A scenario is actually just another word for a test case. We will create a simple overview of the scenario by describing steps in a specific format. These steps can be described with the following keywords: Given, When and Then.

  • Given, When, Then, ( And, But )
    The following keywords are called steps and can be used to describe a scenario.

    • Given: is used to describe the situation at the start of a scenario

    • When: describes a set of actions that will be taken

    • Then: Is used to verify the result of a when step

    • And: is used to repeat the step type above it

    • But: is used as a syntactic device to repeat the type of step above and mark that the intent is inverse

  • Background
    Important to know is that a background can only be used once per feature file. This keyword is used to define a couple of steps that are common to all scenarios. Most often, this is used to define scenario prerequisites.

  • Scenario Outline & Examples

    It might just so happen that you have multiple scenarios that have the same steps but use different values within. This can be solved with a scenario outline, also known as parameterized test. (See example below)

The above feature file can then be rewritten to:
Time to start with a practical example now that we have explained the basic theory. Create a.feature file in the feature directory. Name this file

 googleSearch.feature.

Then add the following steps to the file:

Feature: Google Search Function 
 
  Scenario: Google searching for cucumber 
    Given I am on the Google home page 
    When I search for "cucumber" 
    Then the title of the page should start with "cucumber" 

The example scenario seen above is easy to understand, even for people who are not technical, such as businesspeople.

Only half the work is done, though. We will have to add a TestRunner and write test steps before being able to run the scenario.

Step 5: Writing a TestRunner

It’s time to implement our TestRunner code. Add the following code under the src/test/java directory inside TestRunner class.

import cucumber.api.CucumberOptions; 
import cucumber.api.testng.CucumberFeatureWrapper; 
import cucumber.api.testng.PickleEventWrapper; 
import cucumber.api.testng.TestNGCucumberRunner; 
import org.testng.annotations.AfterClass; 
import org.testng.annotations.BeforeClass; 
import org.testng.annotations.DataProvider; 
import org.testng.annotations.Test; 
 
@CucumberOptions( 
        features = "src/test/resources/features", 
        glue = { "stepdefs" }, 
        tags = {"not @Ignore","not @ignore"}, 
        plugin = { 
                "pretty", 
                "html:target/cucumber-reports/cucumber-pretty", 
                "junit:target/cucumber-reports/junit.xml", 
                "json:target/cucumber-reports/CucumberTestReport.json", 
                "rerun:target/cucumber-reports/rerun.txt" 
        }) 
public class TestRunner { 
  private TestNGCucumberRunner testNGCucumberRunner; 
 
  @BeforeClass(alwaysRun = true) 
  public void setUpClass() throws Exception { 
    testNGCucumberRunner = new TestNGCucumberRunner(this.getClass()); 
  } 
 
  @Test(groups = "cucumber", description = "Runs Cucumber Feature", dataProvider = "scenarios") 
  public void scenario(PickleEventWrapper pickleEvent, CucumberFeatureWrapper cucumberFeature) throws Throwable { 
    testNGCucumberRunner.runScenario(pickleEvent.getPickleEvent());; 
  } 
 
  @DataProvider 
  public Object[][] scenarios() { 
    return testNGCucumberRunner.provideScenarios(); 
  } 
 
  @AfterClass(alwaysRun = true) 
  public void tearDownClass() throws Exception { 
    testNGCucumberRunner.finish(); 
  } 
} 

@CucumberOptions takes a couple of parameters, such as features and glue. The features' parameter is used to tell the runner where your .feature files are located. Glue defines where the code backing our Gherking steps, which we will add in the next steps.

Step 6: Create Step Definitions

IntelliJ will highlight our scenario steps in the feature files, which are not backed by an actual implementation. Luckily, adding the implementation behind a step is straightforward.
Put the caret in one of the yellow steps and press ALT+ENTER, IntelliJ will now as to create the stop definition:

IntelliJ will then ask where to put the stepdefinitions. Important is to place the stepdefs at the spot that you have defined as glue in the @cucumberoptions.

You will notice that a new file has been created once you press okay. This file will have the following structure inside:

public class Stepdefs { 
 
  @Given("^I am on the Google home page$") 
  public void iAmOnTheGoogleHomePage() throws Throwable { 
    // Write code here that turns the phrase above into concrete actions 
    throw new PendingException(); 
  } 
 
  @When("^I search for \"([^\"]*)\"$") 
  public void iSearchFor(String arg0) throws Throwable { 
    // Write code here that turns the phrase above into concrete actions 
    throw new PendingException(); 
  } 
 
  @Then("^the title of the page should start with \"([^\"]*)\"$") 
  public void theTitleOfThePageShouldStartWith(String arg0) throws Throwable { 
    // Write code here that turns the phrase above into concrete actions 
    throw new PendingException(); 
  } 
} 

Once you delete and write the correct Java code for the steps, you can execute the test.

The test will be properly exactable once you replace the "throw new PendingException ()" with actual useful Java code, like done in the example below:

public class Stepdefs { 
 
  @Given("^I am on the Google home page$") 
  public void iAmOnTheGoogleHomePage() throws Throwable { 
    System.out.println("Start a webDriver and navigate to the google homepage"); 
  } 
 
  @When("^I search for \"([^\"]*)\"$") 
  public void iSearchFor(String arg0) throws Throwable { 
    System.out.println("Search for the given parameter"); 
  } 
 
  @Then("^the title of the page should start with \"([^\"]*)\"$") 
  public void theTitleOfThePageShouldStartWith(String arg0) throws Throwable { 
    System.out.println("check that the title of the page starts with the specified parameter"); 
  } 
} 

Congratulations

You have successfully learned how to create a basic Java project using Cucumber, TestNG, Maven, and IntelliJ IDEA.

By following the steps outlined in this blog post, you now have a solid foundation for implementing test frameworks and running automated tests.

If you encounter any issues or if there's something that isn't working as expected during the setup process, please don't hesitate to reach out to us for assistance.