Intermediate Chapter 8 · 11 min read

Hooks — Before, After & Around

Set up and tear down test state with hooks — Before/After scenario, Before/After step, Before/After all, and conditional hooks with tags.

Hooks — Setup & Teardown

Hooks run code at specific points in the Cucumber lifecycle: before/after each scenario, before/after each step, and before/after the entire test run. They're essential for browser setup, screenshot capture, and cleanup.

Hooks.java
package com.bdd.course.hooks;

import io.cucumber.java.*;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class Hooks {

    private static WebDriver driver;

    // Runs once before ALL scenarios
    @BeforeAll
    public static void beforeAll() {
        System.out.println("=== Test Suite Starting ===");
    }

    // Runs before EACH scenario
    @Before
    public void beforeScenario(Scenario scenario) {
        driver = new ChromeDriver();
        driver.manage().window().maximize();
        System.out.println("Starting: " + scenario.getName());
    }

    // Tagged hook — only runs for @ui scenarios
    @Before("@ui")
    public void beforeUiScenario() {
        System.out.println("UI scenario — browser ready");
    }

    // Runs after EACH scenario
    @After
    public void afterScenario(Scenario scenario) {
        // Screenshot on failure
        if (scenario.isFailed() && driver != null) {
            byte[] screenshot = ((TakesScreenshot) driver)
                .getScreenshotAs(OutputType.BYTES);
            scenario.attach(screenshot, "image/png",
                scenario.getName());
            System.out.println("Screenshot captured for: "
                + scenario.getName());
        }

        if (driver != null) {
            driver.quit();
        }
        System.out.println("Finished: " + scenario.getName()
            + " [" + scenario.getStatus() + "]");
    }

    // Runs once after ALL scenarios
    @AfterAll
    public static void afterAll() {
        System.out.println("=== Test Suite Complete ===");
    }

    // Before each step (less common)
    @BeforeStep
    public void beforeStep(Scenario scenario) {
        // Useful for logging or timing
    }

    // After each step
    @AfterStep
    public void afterStep(Scenario scenario) {
        // Capture screenshot after each step for reporting
    }

    public static WebDriver getDriver() {
        return driver;
    }
}
environment.py
# features/environment.py — Behave hooks
from selenium import webdriver
import os, datetime

def before_all(context):
    """Runs once before all features"""
    print("=== Test Suite Starting ===")
    context.config.setup_logging()

def before_feature(context, feature):
    """Runs before each feature file"""
    print(f"Feature: {feature.name}")

def before_scenario(context, scenario):
    """Runs before each scenario"""
    context.driver = webdriver.Chrome()
    context.driver.maximize_window()
    context.driver.implicitly_wait(10)
    print(f"Starting: {scenario.name}")

def before_tag(context, tag):
    """Conditional hook based on tags"""
    if tag == "ui":
        print("UI scenario - browser ready")
    if tag == "api":
        print("API scenario - no browser needed")

def after_scenario(context, scenario):
    """Runs after each scenario"""
    # Screenshot on failure
    if scenario.status == "failed" and hasattr(context, 'driver'):
        os.makedirs("reports/screenshots", exist_ok=True)
        timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
        path = f"reports/screenshots/{scenario.name}_{timestamp}.png"
        context.driver.save_screenshot(path)
        print(f"Screenshot: {path}")

    if hasattr(context, 'driver'):
        context.driver.quit()
    print(f"Finished: {scenario.name} [{scenario.status}]")

def after_feature(context, feature):
    """Runs after each feature file"""
    print(f"Feature complete: {feature.name}")

def after_all(context):
    """Runs once after all features"""
    print("=== Test Suite Complete ===")

def before_step(context, step):
    """Runs before each step (for logging)"""
    pass

def after_step(context, step):
    """Runs after each step"""
    if step.status == "failed":
        print(f"FAILED STEP: {step.name}")

Cucumber BDD Intermediate Hooks — Before, After & Around

Written by PV

© 2026 All Rights Reserved