Currently, many companies are using BDD to develop test projects in development teams. This approach allows product owners and business analysts to be more immersed in what is happening in the technology stack in terms of development and testing. Cucumber Framework performs well in BDD implementation. Let's see what it looks like inside a test project to understand the basic meaning of the framework. I'll tell you how to create a test project from scratch and start developing it in accordance with BDD.
To get started, let's open a command line and generate a templated cucumber project from the maven archetype database. To do this, run the following command:
mvn archetype: generate -Dfilter = io.cucumber: cucumber
Then, press enter and select the latest version to generate, and give a name to the project.
After installation, open the project in the development environment. Before we start developing the test project, we need to install a couple of plugins in our development environment - “Cucumber for Java” and “Gherkin” (I install these plugins for IntelliJ IDEA). The “Gherkin” plugin is needed because the test scripts and test steps in the Cucumber Framework are written in the Gherkin language.
The Gherkin language assumes that scripts and test steps are written in simple literary language that anyone who reads it can understand. Also, the Gherkin language has reserved words (for example: Feature, Scenario, Given. When, Then and others), by which the development environment determines what a given line is in a file. Such files are called feature files and are created with the extension “.feature” (for example: payment.feature)
So after generating the project, we see the finished structure of the test project. In the folder “src / test / java / projectName” there is already RunCucumberTest.class from where we will run all the scripts we have written. It looks like this:
package projectName;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(plugin = {"pretty"})
public class RunCucumberTest {
}
Next, in src / test / resources, create a feature folder where we will create all feature files. Also, for convenience, you need to create a separate folder (for example: “src / test / java / projectName / steps”). There we will create classes for steps definitions.
Do not forget to add two options to the @CucumberOptions annotation in RunCucumberTest.class: features (so that the framework can see in which project folder the feature files are located) and glue (so that the framework can see in which project folder the steps definitions classes are located). It will look like this:
package projectName;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
@CucumberOptions(
plugin = {"pretty"},
features = {"src/test/resources/features"},
glue = {"projectName.steps"}
)
public class RunCucumberTest {
}
Now we will create a feature file called demo.feature in the “src / test / resources / features” folder and inside it we will be able to write scripts for the required functionality, and in scripts we will be able to write the required reproduction steps. This demo.feature file might look like this:
Feature: Saving user activity in DB
Scenario: Save data for user by id
Given We have user id in DB
When User sent request to get info
Then We saved information about user request id DB
Next, I present what a file with a parameterized script looks like. You can see that there are variables in the text and the values for them are written in the "Examples" table. Writing parameterized tests is a very important skill for a tester, in the Cucumber Framework it can be done like this:
Feature: Save data in DB
Scenario Outline: Save information about activity for user in BD
Given We have user id "<id>" in system
When Getting information about user "<id>" with name "<name>" and surname "<surname>"
Then DB saved the information about request for user id "<id>"
Examples:
| id | name | surname |
| 1 | George | Bluth |
| 2 | Janet | Weaver |
| 3 | Emma | Wong |
| 4 | Eve | Holt |
| 5 | Charles| Morris |
Inside the scripts, you can see the steps for playing this script and the keywords Given, When, Then appear at the beginning of the lines. From these words, you can understand what task the step of this scenario performs. At first, the development environment highlights these steps in yellow, since they are not implemented anywhere and an error occurs when running this script.
We can click on the hint that the development environment offers and give the command “Create all step definitions”. Next, a form appears where you can write the name of the class in which methods for implementing the steps of the script will be created. We create steps definitions classes in the created folder “src / test / java / projectName / steps”. The generated class looks like this:
package projectName.steps;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
public class MyStepsDefinitions {
@Given("We have user id in DB")
public void weHaveUserIdInDB() {
}
@When("User sent request to get info")
public void userSentRequestToGetInfo() {
}
@Then("We saved information about user request id DB")
public void weSavedInformationAboutUserRequestIdDB() {
}
}
As you can see, the method names are the same as the steps in the script. We can now implement our steps inside these methods. Also note that the methods are annotated with the appropriate @Given, @When, @Then annotations. For example, inside the methods, I wrote the output of information to the console. Executing this script will give you the result in the console. The methods now look like this:
package projectName.steps;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
public class MyStepsDefinitions {
@Given("We have user id in DB")
public void weHaveUserIdInDB() {
System.out.println("User in DB");
}
@When("User sent request to get info")
public void userSentRequestToGetInfo() {
System.out.println("User received information");
}
@Then("We saved information about user request id DB")
public void weSavedInformationAboutUserRequestIdDB() {
System.out.println("Information saved in DB");
}
}
The simple first scenario has been implemented, now it is possible to write new scenarios for the required functionality and develop your test project. That's all for now. Success in testing everyone!