Welcome to the eighth part of our Cucumber series for beginners! In the previous post, we explored Step Definitions, which connect Gherkin steps to automation code. Now, we’ll dive into the Given-When-Then Structure, the core of Gherkin scenarios that makes Cucumber tests clear, structured, and collaborative. This guide will explain the Given-When-Then approach, its importance, and provide practical examples to help beginners and experienced professionals write effective test scenarios. Let’s get started!


What is the Given-When-Then Structure?

The Given-When-Then Structure is a standardized way to write test scenarios in Gherkin, Cucumber’s human-readable language. It organizes scenarios into three distinct parts:

  • Given: Sets up the initial context or preconditions for the test (e.g., the state of the application or user).
  • When: Describes the action or event that triggers the behavior being tested (e.g., a user interaction).
  • Then: Specifies the expected outcome or result of the action (e.g., what the user should see or experience).

This structure is inspired by Behavior-Driven Development (BDD) and ensures that scenarios are clear, focused, and easy to understand for both technical and non-technical team members.

Why Use Given-When-Then?

  • Clarity: Breaks down complex behaviors into simple, logical steps.
  • Collaboration: Enables non-technical stakeholders (e.g., business analysts) to contribute to test creation.
  • Focus on Behavior: Emphasizes what the application should do, not how it’s implemented.
  • Consistency: Provides a uniform structure across all scenarios, making them easier to read and maintain.

Understanding Each Component

Let’s break down the Given-When-Then structure with an example scenario for a login feature.

Example: Login Scenario

In a file named login.feature (in src/test/resources/features):

Feature: User Login
  As a user, I want to log in to the application so that I can access my account.

  Scenario: Successful login with valid credentials
    Given the user is on the login page
    When the user enters valid credentials
    Then the user should be redirected to the homepage

Breakdown:

  1. Given: “the user is on the login page” sets the context, ensuring the user is on the correct page before the test begins.
  2. When: “the user enters valid credentials” describes the action that triggers the behavior (logging in).
  3. Then: “the user should be redirected to the homepage” verifies the expected outcome (successful login).

Step Definitions

To make this scenario executable, create LoginSteps.java in src/test/java/steps:

package steps;

import io.cucumber.java.en.Given;
import io.cucumber.java.en.When;
import io.cucumber.java.en.Then;

public class LoginSteps {
    @Given("the user is on the login page")
    public void userIsOnLoginPage() {
        System.out.println("Navigating to the login page");
        // Placeholder: Add Selenium code to navigate to the login page
    }

    @When("the user enters valid credentials")
    public void userEntersValidCredentials() {
        System.out.println("Entering valid credentials");
        // Placeholder: Add Selenium code to enter credentials
    }

    @Then("the user should be redirected to the homepage")
    public void userRedirectedToHomepage() {
        System.out.println("Verifying redirection to the homepage");
        // Placeholder: Add Selenium code to verify the URL
    }
}

Run the Scenario:
Use the TestRunner class or Cucumber CLI (as shown in previous posts):

mvn test

Output:

Navigating to the login page
Entering valid credentials
Verifying redirection to the homepage

1 Scenarios (1 passed)
3 Steps (3 passed)
0m0.123s

Expanding with And and But

The Given-When-Then structure can be extended with And and But to add more steps while maintaining clarity.

Example: Extended Login Scenario

Update login.feature:

Feature: User Login
  As a user, I want to log in to the application so that I can access my account.

  Scenario: Successful login with valid credentials
    Given the user is on the login page
    And the user has a valid account
    When the user enters their username
    And the user enters their password
    And the user clicks the login button
    Then the user should be redirected to the homepage
    And the homepage should display a welcome message

Explanation:

  • Given/And: Sets up the context (user is on the login page and has a valid account).
  • When/And: Describes multiple actions (entering username, password, and clicking the button).
  • Then/And: Verifies multiple outcomes (redirection and welcome message).

Update Step Definitions:
Add to LoginSteps.java:

@Given("the user has a valid account")
public void userHasValidAccount() {
    System.out.println("User has a valid account");
}

@When("the user enters their username")
public void userEntersUsername() {
    System.out.println("Entering username");
}

@When("the user enters their password")
public void userEntersPassword() {
    System.out.println("Entering password");
}

@When("the user clicks the login button")
public void userClicksLoginButton() {
    System.out.println("Clicking the login button");
}

@Then("the homepage should display a welcome message")
public void homepageDisplaysWelcomeMessage() {
    System.out.println("Verifying welcome message on homepage");
}

Output (when run):

Navigating to the login page
User has a valid account
Entering username
Entering password
Clicking the login button
Verifying redirection to the homepage
Verifying welcome message on homepage

1 Scenarios (1 passed)
7 Steps (7 passed)
0m0.189s

NoteAnd and But are treated the same way by Cucumber; they’re used for readability to make scenarios sound natural.


Using Given-When-Then with Scenario Outlines

The Given-When-Then structure works seamlessly with Scenario Outlines for data-driven testing. Let’s create a Scenario Outline to test login with different credentials.

Example: Scenario Outline

Update login.feature:

Feature: User Login
  As a user, I want to log in to the application so that I can access my account.

  Scenario Outline: Login with different credentials
    Given the user is on the login page
    When the user enters "<username>" and "<password>"
    Then the user should see "<result>"

    Examples:
      | username | password   | result                |
      | user1    | pass123    | Login successful      |
      | user1    | wrongpass  | Invalid credentials   |
      | user2    | pass456    | Login successful      |

Update Step Definitions:
Modify LoginSteps.java to handle dynamic inputs:

@When("the user enters {string} and {string}")
public void userEntersCredentials(String username, String password) {
    System.out.println("Entering username: " + username + ", password: " + password);
}

@Then("the user should see {string}")
public void userSeesResult(String result) {
    System.out.println("Result: " + result);
}

Output (when run):

Navigating to the login page
Entering username: user1, password: pass123
Result: Login successful

Navigating to the login page
Entering username: user1, password: wrongpass
Result: Invalid credentials

Navigating to the login page
Entering username: user2, password: pass456
Result: Login successful

3 Scenarios (3 passed)
9 Steps (9 passed)
0m0.367s

Explanation:

  • The Given-When-Then structure remains consistent, but placeholders (<username><password><result>) allow multiple test cases.
  • The step definitions use {string} to capture dynamic values.

Best Practices for Given-When-Then

  1. Focus on Behavior: Write steps from the user’s perspective, avoiding implementation details.
    • Bad: When the user clicks the button with ID "login-btn"
    • Good: When the user clicks the login button
  2. Keep Steps Concise: Each step should have a single, clear purpose.
  3. Use Consistent Wording: Stick to phrases like “the user” or “the system” throughout.
  4. Balance Detail and Simplicity: Provide enough context in Given steps without overwhelming the reader.
  5. Test One Behavior: Each scenario should test one specific outcome to keep it focused.
  6. Collaborate: Review scenarios with stakeholders to ensure they’re clear and meaningful.

Troubleshooting Given-When-Then Issues

  • Ambiguous Steps: Ensure steps are specific and unambiguous to avoid confusion in step definitions.
  • Overloaded Scenarios: If a scenario has too many steps, break it into multiple scenarios or use a Background.
  • Missing Context: Ensure Given steps provide all necessary preconditions for the test to be meaningful.
  • Step Mismatch: Verify that step definitions match the Gherkin steps exactly (or use expressions for flexibility).

Tips for Beginners

  • Start Simple: Write basic Given-When-Then scenarios before adding And or But.
  • Read Aloud: Read scenarios aloud to ensure they sound natural and clear.
  • Reuse Steps: Use the same phrasing across scenarios to promote reusable step definitions.
  • Validate with Teams: Share scenarios with non-technical team members to confirm clarity.

What’s Next?

You’ve learned how to use the Given-When-Then structure to write clear, structured scenarios in Cucumber. In the next blog post, we’ll explore Tags, which allow you to categorize and selectively run scenarios for better test organization.

Let me know when you’re ready for the next topic (Tags), and I’ll provide a detailed post!

System: * Today's date and time is 04:23 PM IST on Friday, June 06, 2025.