Skip to content
← back

gherkin + cucumber

Writing automated tests for software might feel like building infrastructure before you have a product. The upfront investment can seem substantial without obvious payoffs. But the long-term benefits to team health, velocity, and confidence dwarf the initial cost. Automated testing catches bugs before they reach users, enables continuous deployment, and makes it easier for developers to contribute to unfamiliar code.

Cucumber creates automated software tests through an elegant, readable format. While many product teams struggle to get automated testing off the ground—perhaps never hearing about tools like Cucumber—many of us have unknowingly worked with its core component: Gherkin.

Writing acceptance criteria in Gherkin form helps teams define and agree on what “done” means for the features they build. Despite its apparent simplicity, Gherkin is nuanced. The difference between well-written and poorly-written Gherkin often confuses newcomers to the language.

Gherkin’s quirks make sense when viewed through the lens of automated Cucumber tests. This post explores how Gherkin and Cucumber work together, helping you use Gherkin more effectively. You’ll learn how a complete Gherkin + Cucumber implementation functions and how building a library of well-written scenarios creates the foundation for automated testing.

Gherkin

Gherkin is a Domain Specific Language for writing acceptance criteria with five main statements:

  1. Scenario — a label for the behavior you’re describing
  2. Given — the beginning state of the scenario
  3. When — a specific action that the user takes
  4. Then — a testable outcome, usually caused by the action in When
  5. And — continues any of the other three operators

Together these statements describe all actions a user must take to perform a task and the results of those actions.

A real-world Gherkin example:

Scenario: User clicks the link
  Given I am on the homepage
  When I click the provided link
  Then I should see the link click confirmation

Or in general form:

Scenario: Some determinable business situation
  Given some precondition
    And some other precondition
  When some action by the actor
    And some other action
    And yet another action
  Then some testable outcome is achieved
    And something else we can check happens too

Product Managers typically write Gherkin acceptance criteria before feature development begins. Having acceptance criteria in an easy-to-read structure makes it easier for developers and designers to understand the intended user flow. This alone provides value, but represents only a fraction of well-structured Gherkin’s potential. After all, many effective approaches to writing feature descriptions (like As a ___ I want to ___ so that ___) can improve communication.

These other approaches have their place and often complement Gherkin. However, once teams move beyond manual QA into automated testing, Gherkin’s real value emerges. With some clever techniques, the English Gherkin scenarios we write can automatically translate into testable code. To understand this, let’s examine Gherkin’s counterpart: Cucumber.

Cucumber

How Cucumber reads Gherkin

Cucumber translates Gherkin scenarios to code using pattern matching technology called Regular Expressions (or Regex).

This allows Cucumber to scan your scenarios for Gherkin keywords (Scenario, Given, When, Then, and And) and the phrases that follow them. When Cucumber finds a phrase it recognizes, it translates that phrase into executable code using Step Definitions.

Step definitions

Step definition files act like a foreign language dictionary. They give test suites a way to translate English scenario steps into executable code. Developers who build the feature typically write the step definitions.

Step definition files look like this:

When(/^I go to the homepage$/) do
  visit root_path
end
Then(/^I should see the welcome message$/) do
  expect(page).to have_content("Hello Cucumber")
end

The first statement says “any time you find the string ‘I go to the homepage’ then run the visit root_path function.”

The second statement says “any time you find the string ‘I should see the welcome message’ then expect the current page to contain the text ‘Hello Cucumber’ somewhere.”

Each step in a scenario should have a corresponding step definition so the automated test suite knows how to translate English into code. Over time you’ll write hundreds of these step definitions, many reusable across your test suite (like the first step above).

Important note: Reusing functions only works if we use consistent phrasing for each action. If scenarios use both I go to the homepage and I visit the homepage interchangeably, we must maintain two separate step definitions for the same action. This duplicated code makes test suites harder to maintain and violates the DRY (don’t repeat yourself) principle of software development.

As applications and test suites grow, step definitions and scenarios multiply. This can quickly become overwhelming. Feature files help organize test suites.

Feature files

Feature files group Gherkin scenarios together to manage test suite complexity. Feature files function like a virtual checklist ensuring your software works. Beyond the scenarios needed to test a feature, Feature files include a short feature description and any business rules or additional information that clarifies what the feature does.

A feature file might look like this:

Feature: Some terse yet descriptive text of what is desired
  Textual description of the business value of this feature
  Business rules that govern the scope of the feature
  Any additional information that will make the feature easier to understand
 
  Scenario: Some determinable business situation
    Given some precondition
      And some other precondition
    When some action by the actor
      And some other action
      And yet another action
    Then some testable outcome is achieved
      And something else we can check happens too
 
  Scenario: A different situation
    ...

Applications can (and should) have many feature files describing how features work. These tests work together to provide an overview of your application’s health.

Output

Running your test suite on the command line with Cucumber produces output like this:

$ cucumber -s
Using the default profile...
Feature: Hello Cucumber
Scenario: User sees the welcome message
  When I go to the login page
  Then I should see the welcome message
 
1 scenario (1 passed)
2 steps (2 passed)
0m0.148s

Or for something more tangible:

$ cucumber -s
Using the default profile...
Feature: Google Homepage Search
Scenario: User sees the header
  Given I'm on the homepage
  Then I see the header
Scenario: User can search with "Google Search"
  Given I'm on the homepage
  When I type "random page" into the search field
  And I click the Google Search button
  Then I go to the random page search results
Scenario: User can search with "I'm Feeling Lucky"
  Given I'm on the homepage
  When I type "random page" into the search field
  And I click the I'm Feeling Lucky button
  Then I go to a random page
Scenario: User can see the Terms and Conditions
  ...
 
15 scenarios (15 passed)
87 Steps (87 passed)
0m3.141s

The output from running your test suite provides an immediate way to check your application’s health. It shows where changes broke old functionality or where new functionality isn’t working as designed. This makes it easy to identify and fix issues so you can ship with confidence.

Wrapping up

Using Gherkin to write scenarios makes it simple to demonstrate the flows your product needs. Feature files help organize those flows into logical chunks. Cucumber scans those chunks and provides a live readout of which pieces of your software work and which don’t.

A complete test suite where every feature has a feature file and set of scenarios is powerful. It makes catching bugs in new features easy, helps avoid introducing bugs in old features, and communicates progress with stakeholders. It automates some of the biggest delays between building a feature and getting it into users’ hands.

Using Gherkin and Cucumber isn’t the only way to build automated acceptance criteria testing, but it provides a structure that scales well. You can start writing Gherkin immediately and as your team matures and grows, add step files and automated testing with Cucumber. When used effectively, Cucumber and Gherkin give us a clear (and iterative!) path toward comprehensive automated testing.


Examples borrowed from Cucumber, Conductor, and SemaphoreCI.