Welcome to the twelfth part of our Cucumber series for beginners! In the previous post, we explored Data Tables, which allow you to pass structured data to test steps. Now, we’ll dive into Scenario Hooks, a feature in Cucumber that lets you run setup and teardown code before or after scenarios, features, or steps. This guide will explain what Scenario Hooks are, how to use them, and provide practical examples to make it easy for beginners and valuable for experienced professionals. Let’s get started!


What are Scenario Hooks in Cucumber?

Scenario Hooks are special methods in Cucumber that allow you to execute code at specific points during test execution, such as before or after a scenario, feature, or step. They are typically used for setup tasks (e.g., initializing a browser) or teardown tasks (e.g., closing a browser or cleaning up test data). Hooks are defined in step definition files using annotations like @Before and @After.

Why Use Scenario Hooks?

  • Setup Automation: Initialize resources (e.g., WebDriver for Selenium) before a test runs.
  • Teardown Automation: Clean up resources (e.g., close browser, delete test data) after a test.
  • Consistency: Ensure a consistent environment for each scenario.
  • Separation of Concerns: Keep setup and teardown logic separate from test steps, making scenarios cleaner.

Types of Hooks in Cucumber

Cucumber provides several hook annotations, primarily in Java (since we’re using Cucumber with Java):

  1. @Before: Runs before a scenario. Used for setup tasks.
  2. @After: Runs after a scenario, regardless of whether it passes or fails. Used for teardown tasks.
  3. @BeforeStep: Runs before each step in a scenario.
  4. @AfterStep: Runs after each step in a scenario.
  5. @BeforeAll: Runs once before all scenarios in a test run (static method required).
  6. @AfterAll: Runs once after all scenarios in a test run (static method required).

Hooks can also be tagged to run only for specific scenarios or features, and you can control their execution order using the order parameter.


Using Scenario Hooks

Let’s create a feature file and use hooks to set up and tear down a WebDriver instance for a login scenario. This example assumes you’re testing a web application with Selenium.

Example: Hooks for Login Scenario

Create 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.

  @smoke
  Scenario: Successful login with valid credentials
    Given the user is on the login page
    When the user enters "user1" and "pass123"
    Then the user should be redirected to the homepage

  @regression
  Scenario: Failed login with invalid credentials
    Given the user is on the login page
    When the user enters "user1" and "wrongpass"
    Then the user should see an error message

Step 1: Add Selenium Dependency

Ensure your project has the Selenium dependency in pom.xml:

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>4.25.0</version>
</dependency>

Step 2: Create Step Definitions with Hooks

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;
import io.cucumber.java.Before;
import io.cucumber.java.After;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class LoginSteps {
    private WebDriver driver;

    @Before
    public void setUp() {
        driver = new ChromeDriver();
        System.out.println("Browser initialized");
    }

    @After
    public void tearDown() {
        if (driver != null) {
            driver.quit();
            System.out.println("Browser closed");
        }
    }

    @Given("the user is on the login page")
    public void userIsOnLoginPage() {
        driver.get("https://example.com/login");
        System.out.println("Navigated to login page");
    }

    @When("the user enters {string} and {string}")
    public void userEntersCredentials(String username, String password) {
        System.out.println("Entering username: " + username + ", password: " + password);
        // 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 homepage");
        // Placeholder: Add Selenium code to verify
    }

    @Then("the user should see an error message")
    public void userSeesErrorMessage() {
        System.out.println("Verifying error message");
        // Placeholder: Add Selenium code to verify
    }
}

Explanation:

  • @Before: Initializes a Chrome WebDriver before each scenario.
  • @After: Closes the browser after each scenario, ensuring no resources are left open.
  • Shared WebDriver: The driver instance is shared across steps within a scenario.
  • Placeholder URL: The driver.get uses a placeholder URL (https://example.com/login); replace it with your application’s login URL in a real project.

Step 3: Run the Scenarios

Use the TestRunner class or Cucumber CLI:

mvn test

Output:

Browser initialized
Navigated to login page
Entering username: user1, password: pass123
Verifying redirection to homepage
Browser closed

Browser initialized
Navigated to login page
Entering username: user1, password: wrongpass
Verifying error message
Browser closed

2 Scenarios (2 passed)
6 Steps (6 passed)
0m2.345s

Note: The actual time will vary depending on Selenium’s browser initialization.


Using Tagged Hooks

You can restrict hooks to run only for specific scenarios by associating them with tags.

Example: Tagged Hooks

Update LoginSteps.java to use tagged hooks:

@Before("@smoke")
public void setUpForSmoke() {
    driver = new ChromeDriver();
    driver.manage().window().maximize();
    System.out.println("Browser initialized and maximized for smoke test");
}

@After("@smoke")
public void tearDownForSmoke() {
    if (driver != null) {
        driver.quit();
        System.out.println("Browser closed for smoke test");
    }
}

@Before("@regression")
public void setUpForRegression() {
    driver = new ChromeDriver();
    System.out.println("Browser initialized for regression test");
}

@After("@regression")
public void tearDownForRegression() {
    if (driver != null) {
        driver.quit();
        System.out.println("Browser closed for regression test");
    }
}

Explanation:

  • The @Before("@smoke") and @After("@smoke") hooks run only for the @smoke scenario.
  • The @Before("@regression") and @After("@regression") hooks run only for the @regression scenario.
  • The smoke test hook maximizes the browser window as an additional setup step.

Run only @smoke scenarios:

mvn cucumber:test -Dcucumber.features=src/test/resources/features -Dcucumber.glue=steps -Dcucumber.filter.tags="@smoke"

Output:

Browser initialized and maximized for smoke test
Navigated to login page
Entering username: user1, password: pass123
Verifying redirection to homepage
Browser closed for smoke test

1 Scenarios (1 passed)
3 Steps (3 passed)
0m1.789s

Controlling Hook Execution Order

If multiple @Before or @After hooks apply to a scenario, you can control their execution order using the order parameter.

Example: Ordered Hooks

Update LoginSteps.java:

@Before(order = 1)
public void setUpFirst() {
    System.out.println("First setup: Initializing environment");
}

@Before(order = 2)
public void setUpSecond() {
    driver = new ChromeDriver();
    System.out.println("Second setup: Initializing browser");
}

@After(order = 2)
public void tearDownFirst() {
    if (driver != null) {
        driver.quit();
        System.out.println("First teardown: Closing browser");
    }
}

@After(order = 1)
public void tearDownSecond() {
    System.out.println("Second teardown: Cleaning up environment");
}

Explanation:

  • @Before: Lower order values run first (e.g., order = 1 before order = 2).
  • @After: Higher order values run first (e.g., order = 2 before order = 1).
  • This ensures the environment is set up before the browser and cleaned up after the browser is closed.

Output (for one scenario):

First setup: Initializing environment
Second setup: Initializing browser
Navigated to login page
Entering username: user1, password: pass123
Verifying redirection to homepage
First teardown: Closing browser
Second teardown: Cleaning up environment

Best Practices for Scenario Hooks

  1. Keep Hooks Lightweight: Avoid heavy logic in hooks; use them for essential setup/teardown tasks.
  2. Use Tagged Hooks: Restrict hooks to specific scenarios to optimize execution time.
  3. Handle Resources Safely: Ensure resources (e.g., browsers, database connections) are properly closed in @After hooks.
  4. Avoid Scenario Dependencies: Hooks should not rely on the outcome of previous scenarios.
  5. Log Clearly: Add logging (e.g., System.out.println) to debug hook execution.
  6. Test Hooks Independently: Verify hooks work correctly by running tagged scenarios.

Troubleshooting Hook Issues

  • Hooks Not Running: Ensure the hook annotations (@Before, @After) are correctly imported from io.cucumber.java.
  • Wrong Hook Execution: Check tag filters or order parameters if hooks run unexpectedly.
  • Resource Leaks: Verify that @After hooks clean up resources to prevent memory leaks (e.g., unclosed browsers).
  • Step Conflicts: Ensure hooks don’t interfere with step definitions (e.g., by resetting shared state).

Tips for Beginners

  • Start with Basic Hooks: Use simple @Before and @After hooks for browser setup/teardown.
  • Test Tagged Hooks: Experiment with tags to see how hooks apply to specific scenarios.
  • Add Logging: Use print statements to track hook execution during development.
  • Use with Selenium: Hooks are ideal for managing WebDriver instances in web testing.

What’s Next?

You’ve learned how to use Scenario Hooks to manage setup and teardown tasks in Cucumber tests. In the next blog post, we’ll explore Cucumber Expressions, which provide a flexible way to match Gherkin steps with step definitions using parameters.

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

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