Integration Testing With Gherkin

Gökhan Ataş
Insider Engineering
6 min readJun 12, 2023

Integration testing is a crucial step in the development process. It ensures that every component of your program properly interacts with one another. However, as your product gets bigger and more complicated, writing and maintaining integration tests can become difficult and time-consuming.

One approach to simplifying the process of writing integration tests is to use a testing framework that supports behavior-driven development (BDD), such as Gherkin. This article examines Gherkin in more detail and discusses how it can be used to write efficient and maintainable integration tests.

What is Gherkin?

Gherkin is a structured language that clearly explains how a software application behaves, making it simple to understand for both technical and non-technical stakeholders. It is used to write test scenarios in a Given-When-Then format.

The behavior of a software system is described in terms of scenarios and steps. Programming languages like Java, Ruby, or Go are used to create Gherkin step definitions, which specify the software system's behavior being tested at each step of a scenario. The steps specified in a Gherkin feature file are translated into executable code using Gherkin step definitions.

Each step in a Gherkin feature file maps to a step definition in the code, which carries out the required operations and ensures that the system behaves as expected.

The role of step definitions

Let’s suppose there is an endpoint where users can update their profile information. In this case, the feature should be written and explained first.

The reason why the feature keyword has been used is to provide a high-level description of a software feature and to group scenarios related to that description.

For the example endpoint, scenario and its steps can be described as follows:

Explanation of Steps in Gherkin Document:

  1. there are “users” in the database: This step sets up the initial state of the system, stating that there are existing users in the database.
  2. I send a “PUT” request to “/api/user/1” with body: This step defines the action that will be taken by the user, which is to send a PUT request to the “/api/user/1” endpoint with a JSON payload.
  3. the response should have a 200 status code: This step defines the expected response from the API, which should be a 200 status code indicating a successful update.
  4. “users” information with “1” id must match: This step defines the expected outcome of the API call, which is to update the user information with id “1” and verify that the name and surname values have been updated to “Jack” and “London”, respectively.

Then, step definitions are written as follows. In this example, the Go language is used.

func (suite *IntegrationTestSuite) addSteps(suiteContext *godog.TestSuiteContext) {
suiteContext.ScenarioContext().Step(`^I send a "([^"]*)" request to "([^"]*)" with body$`, suite.iSendRequestToWithBody)
suiteContext.ScenarioContext().Step(`^the response should have a (\d+) status code$`, suite.theResponseStatusCodeShouldBe)
suiteContext.ScenarioContext().Step(`^there are "([^"]*)" in the database:$`, suite.thereAreInTheDatabase)
suiteContext.ScenarioContext().Step(`^"([^"]*)" information with "([^"]*)" id must match:$`, suite.informationMustMatch)
}

func (suite *IntegrationTestSuite) iSendRequestToWithBody(method, endpoint string, body *godog.DocString) error {
// Implement code to send the HTTP request with the provided method, endpoint, and body
return nil
}

func (suite *IntegrationTestSuite) theResponseStatusCodeShouldBe(code int) error {
// Implement code to check that the HTTP response status code matches the expected status code
return nil
}

func (suite *IntegrationTestSuite) thereAreInTheDatabase(table string, values *godog.Table) error {
// Implement code to set up the initial state of the system
return nil
}

func (suite *IntegrationTestSuite) informationMustMatch(table string, id int, values *godog.Table) error {
// Implement code to check correctness of given values for given table and id
return nil
}

Explanation of Step Definitions:

The addSteps method adds the step definitions to the test suite context. These step definitions are defined by regular expressions and corresponding Go functions to be executed when the regular expressions match a step in a Gherkin feature file.

  1. iSendRequestToWithBody matches a step where the tester sends an HTTP request with a specified method and endpoint, and a body in the request. The step definition uses the godog.DocString type to capture the body of the request as a string.
  2. theResponseStatusCodeShouldBe matches a step where the tester expects the HTTP response to have a specific status code. The step definition takes an integer parameter that represents the expected status code.
  3. thereAreInTheDatabase matches a step where the tester sets up the initial state of the system by adding data to a database. The step definition takes a string parameter that represents the name of the table and a table object that represents the values to be inserted into the table.
  4. informationMustMatch matches a step where the tester verifies that the information in a database table with a given ID matches a set of expected values. The step definition takes a string parameter that represents the name of the table, an integer parameter that represents the ID of the row to be verified, and a table object that represents the expected values.

How Should the Gherkin Document Be Written?

In an ideal scenario, everyone engaged in the software development process would work together to create the Gherkin document. This includes developers, testers, and product owners. In this way, by including everyone in the process, each requirement will be clearly defined and the whole process will be known by all team members.

At Insider, we follow a similar approach. Our product managers write user stories before presenting a task to the team. During grooming sessions, we discuss how to develop the task based on the user stories, and as a team, we identify any user stories that are not covered and find solutions to them. We also discuss rare cases and work to minimize any potential gaps in the requirements. By the end of the session, we aim to have a Gherkin document with minimal deficiencies that accurately reflects the scope of the task.

What are the Advantages of Gherkin?

Advantages of using Gherkin

Improved collaboration: Gherkin scenarios are written in a language that is easily understood by everyone involved in the software development process. This improves collaboration and ensures everyone including non-technical stakeholders has a common understanding of requirements.

Reduced maintenance costs: Gherkin scenarios can be quickly updated as requirements change because they are simple to understand and maintain. Your integration tests’ total maintenance costs go down as a result.

Better test coverage: By using Gherkin to describe your tests, you can make sure that all of the various scenarios that your application must handle are tested. At Insider, if we encounter any bugs, we add the missed case to our test scenarios in order not to encounter them again. In this way, edge cases are handled and time is also saved.

Better quality: Gherkin tests can serve as living documentation for your program because they are created to be readable by humans. This facilitates comprehension of your application’s operation, which may result in higher quality.

How to Improve Efficiency?

Gif source: https://bloody-disgusting.com/tv/3452007/last-nights-rick-morty-bloodbath/

To get the most out of Gherkin, consider following as best practices.

Keep your scenarios short and focused.

Each scenario should focus on testing a specific feature or behavior of the application.

Use meaningful and concise step definitions.

The step definition should be easy to read and understand.

Avoid duplication.

Try to reuse step definitions whenever possible.

Conclusion

Gherkin is a powerful tool for ensuring that your software application meets its requirements and that all tests are covered. By following best practices for writing Gherkin scenarios, you can improve collaboration, reduce maintenance costs, achieve better test coverage, and enhance the overall quality of your software.

If you liked this post, you can find more at Insider Engineering Blog.

--

--