Cucumber Features: an overview

20 Apr 2022 | 12 min read
Cucumber features

Intro

Gherkin is a language still used in many test automation frameworks. Sometimes it is because the client requires us to use it, sometimes it is because the team decides to do so.

To be honest, it was not love at first sight for me. I personally have a pretty long journey with Gherkin– from liking it at first, through detesting the language for a while, and then ending up liking it again. In this article I will present the most important Cucumber features together with Java implementation.

Here are all Cucumber features covered in this article:

FeatureDescription
ScenarioSimple scenario
Scenario OutlineRequires user to provide test data in the “Examples” section
Data TablesRequires user to provide test data for test step
Scenario ContextSharing of values between test steps
Cucumber Data TypesData types handled by cucumber
Cucumber Regular ExpressionUsage of regular expression in cucumber scenarios
Cucumber hooksExecutes additional code in test scenarios
Table 1. Cucumber and java features covered in this article

Feature file

First of all, what is a feature file? In the technical world a non-technical approach was created to allow non-technical people to cooperate with the team during the development of an app. The Gherkin language was created as an additional layer in the BDD approach. The Gherkin tests are located in the so-called feature files which are glued with the code (Java, Kotlin, C# etc.). Usually Gherkin is very easy to use, and requires minimum programming knowledge, but there are features which require some coding.

Let’s start with something easy.

Scenario

Here’s the most basic and easiest to use example of the Cucumber test:

Feature: Scenario

 Background: Before Test Scenarios
   Given I execute before step

 @Test
 Scenario: Scenario 
   Given I use the parameterized step of "Scenario 1"

Code Block 1. Scenario

Code Block 1. contains a few things to be explained:

  • Feature: the title of feature file
  • Background: the keyword that allows the user to execute test steps before each test scenario defined in the feature file
  • @Test: Tag which tells the testing framework what test scenario should be executed. “Test” is defined by the user. We can use e.g. “@SmokeTest”
  • Scenario: Test scenario name

Gherkin tests use [Given, When, Then, But] keywords before each test step. In our only test step, except the Background step, we use a parameter in which we pass the value “Scenario 1”.

Now, let’s see what the glued Java code looks like:

@Given("I execute before step")
public void iExecuteBeforeStep() {
   //some implementation
}

@Given("I use the parameterized step of {string}")
public void iUseParametrizedStepOf(String p) {
   //some implementation
}

Code Block 2. Java code implementation of Scenario

Scenario Outline

Let’s do something more complex:

Feature: Scenario Outline

 @Test
 Scenario Outline: Scenario Outline
   Given I run the step with "<parameter1>" and "<parameter2>"
 Examples:
     | parameter1  | parameter2  |
     | parameter1a | parameter2a |
     | parameter1b | parameter2b |

Code Block 3. Scenario Outline

This time we will use the Scenario Outline which allows us to repeat test scenarios with different test data configurations. Code Block 3. contains few things to be explained:

  • Examples: the matrix of test data to be used by test scenarios. The first row is a header with parameter names.

And java implementation:

@Given("I run the step with {string} and {string}")
public void iRunStepWithAnd(String p1, String p2) {
   //some implementation
}

Code Block 4. Java implementation of Scenario Outline

Data Table

The Scenario Outline is very useful, but what if we don’t want to repeat the entire test scenario but just one test step? Gherkin has a way to do that and it is called “Data Table”.

Feature: Data Table

@Test
Scenario: Data Table Scenario
 Given I verify the column contains expected value
 | columnName     | expectedValue     |
 | someColumnName | someExpectedValue |

Code Block 5. Data Table

The Scenario with Data Table does not differ much from the Scenario Outline. The only thing is that we do not put the “Examples” keyword before the table.

The Java implementation looks a bit more complex than in the previous cases:

@Given("I verify the column contains expected value")
public void iVerifyColumnValuesInTableUsingQueryFromFileOnSchema(DataTable dataTable) {
   List<Map<String, String>> data = dataTable.asMaps();
   for (Map<String, String> form : data) {
       String columnName = form.get("columnName");
       String expectedResult = form.get("expectedValue");
       //some implementation
       }
   }
}

Code Block 6. Java implementation of Data Table

To access data from a data table, we create a special variable dataTable of a “DataTable” type. All data will be stored in the List variable.

Scenario Context

Using the Scenario Context we can share data between steps. Let’s assume we have a two steps scenario in which we want to pass value “data” from step 1 to step 2 (Code Block 7).

@Test
Scenario: Scenario Context
 Given I set scenario context value "data"
 Given I use scenario context value

Code Block 7. Scenario Context

Firstly we need to build a special class called ScenarioContext with scenario context features of setting and getting data (Code Block 8). Our scenario context is a HashMap with a key-value pair. We will be identifying values by its key.

  • scenarioContext(): HashMap of key-value pair
  • setContext(): key-value method to store scenario context data
  • getContext(): method to get data providing key
public class ScenarioContext {

   private  Map<String, Object> scenarioContext;

   public scenarioContext(){
       scenarioContext = new HashMap<>();
   }

   public void setContext(Context key, Object value) {
       scenarioContext.put(key.toString(), value);
   }

   public Object getContext(Context key){
       return scenarioContext.get(key.toString());
   }

}

public enum Context {
   ID;
}

Code Block 8. Java implementation of Scenario Context class

Having this we can make use of implemented methods. In step 1 we then set the value in the scenario context and in step 2 we get the value (Code Block 9).

ScenarioContext scenarioContext = new ScenarioContext();

@Given("I set scenario context value {string}")
public void iSetScenarioContextValue(String value) {
   scenarioContext.setContext(Context.ID, value);
}

@Given("I use scenario context value")
public void iUseScenarioContextValue() {
   String sharedValue = scenarioContext.getContext(Context.ID).toString();
}

Code Block 9. Scenario Context steps

Cucumber Data Types

Cucumber handles a limited number of data types. We can define strings, integers and float values but in the case of boolean values we need to code some workarounds.

@Test
Scenario: Scenario with variables
 Given I use string "string", int 1, float 1.1 and boolean "false"

Code Block 10. Cucumber Data Types

The Java code would look something like this:

@Given("I use string {string}, int {int}, float {float} and boolean {string}")
public void iUseStringIntFloatAndBoolean(String var1, int var2, double var3, String var4) {
   boolean f = Boolean.valueOf(var4);
   //some code
}

Code Block 11. Java implementation of Cucumber Data Types

Cucumber Regular Expression

This is another frequently used feature. Code Block 12 shows a two steps scenario which differ only by using different variable values (var1 and var2). This is in fact just one step, and in the Java code (Code Block 13) we define only one method but with regex and one parameter var.

@Test
Scenario: Regular Expression scenario
 Given I use variable var1
 Given I use variable var2

Code Block 12. Regular Expression in Cucumber

@Given("^I use variable (.*)")
public void examTimeTableInSummerSeason(String var) {
   if (var.equals("var1")){
       //some code
   }
   else if(var.equals("var2")){
       //some code
   }
}

Code Block 13. Java implementation of Cucumber regular expression

Cucumber Hooks

Last but not least: Cucumber hooks.

Code block 14 presents the 4 most important hooks:

  • @Before: Executes code before each test scenario
  • @After: Executes code after each test scenario
  • @BeforeStep: Executes code before each test step
  • @AfterStep: Executes code after each test step
@Before
public void beforeScenario() {
   //some code
}

@After
public void afterScenario() {
   //some code
}

@BeforeStep
public void beforeStep() {
   //some code
}

@AfterStep
public void afterStep() {
   //some code
}

Code Block 14. Cucumber Hooks

Summary

I hope I convinced you to use Gherkin in your tests. These few features will make your tests more readable and easier to understand by non-technical people. Also for new joiners it will be easier to understand the business logic and decrease their time to onboard.

The controller of your personal data is Miquido sp. z ograniczoną odpowiedzialnością sp.k. with its registered office in Krakow, ul. Zabłocie 43a, 30-701 Kraków. We process the above information in order to answer your questions, contact you and conduct business communication, and if you tick the checkbox, to send you messages containing commercial, business and marketing materials.
The basis for the processing of your data is Miquido's legitimate interest - informing customers about news and changes to our offer as well as providing information about products that may be useful in their business. You can unsubscribe from the marketing communications at any time. You also have the right to access data, the right to request rectification, deletion or limitation of their processing, data transfer, the right to object, as well as the right to lodge a complaint to the supervisory body. Full information about processing of personal data can be found in the Privacy Policy.

Show more

Want to talk about your project?

Hi, I’m Sebastian, Account Executive at Miquido. Fill in the form to the right and I’ll get in touch with you soon!


    0/2000

    The controller of your personal data is Miquido sp. z ograniczoną odpowiedzialnością sp.k. with its registered office in Krakow, ul. Zabłocie 43a, 30-701 Kraków. We process the above information in order to answer your questions, contact you and conduct business communication, and if you tick the checkbox, to send you messages containing commercial, business and marketing materials.
    The basis for the processing of your data is your consent and Miquido's legitimate interest.You can unsubscribe from the marketing communications at any time. You also have the right to access data, the right to request rectification, deletion or limitation of their processing, data transfer, the right to object, as well as the right to lodge a complaint to the supervisory body. Full information about processing of personal data can be found in the Privacy Policy.
    Show more

    We have received your message. One of our colleagues will get back to you shortly. Have a great day!