CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-cucumber--cucumber-java

Cucumber-JVM Java library providing annotation-based step definitions for Behavior-Driven Development (BDD) testing

Pending
Overview
Eval results
Files

runtime-context.mddocs/

Runtime Context

Access to scenario information, status, and reporting capabilities during test execution. The runtime context provides comprehensive access to scenario metadata, execution status, and powerful reporting features for enhanced test visibility and debugging.

Capabilities

Scenario Interface

Provides access to scenario information and reporting capabilities in hooks and step definitions.

/**
 * Main scenario interface for accessing test execution context
 */
public final class Scenario {
    
    /**
     * Get all tags associated with this scenario
     * @return Collection of tag names including '@' prefix
     */
    Collection<String> getSourceTagNames();
    
    /**
     * Get current execution status of the scenario
     * @return Current status (most severe status of executed steps)
     */
    Status getStatus();
    
    /**
     * Check if scenario has failed
     * @return true if status is FAILED
     */
    boolean isFailed();
    
    /**
     * Attach binary data to the test report
     * @param data Binary data (e.g., screenshots, files)
     * @param mediaType MIME type (e.g., "image/png", "application/json")
     * @param name Human-readable name for the attachment
     */
    void attach(byte[] data, String mediaType, String name);
    
    /**
     * Attach text data to the test report  
     * @param data Text content
     * @param mediaType MIME type (e.g., "text/plain", "text/html")
     * @param name Human-readable name for the attachment
     */
    void attach(String data, String mediaType, String name);
    
    /**
     * Log text message to the test report
     * @param text Message to log
     */
    void log(String text);
    
    /**
     * Get scenario name from feature file
     * @return Scenario name
     */
    String getName();
    
    /**
     * Get unique identifier for this scenario execution
     * @return Scenario ID (not stable across executions)
     */
    String getId();
    
    /**
     * Get URI of the feature file containing this scenario
     * @return Feature file URI
     */
    URI getUri();
    
    /**
     * Get line number of scenario in feature file
     * @return Line number (or example row line for scenario outlines)
     */
    Integer getLine();
}

Usage Examples:

import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.Scenario;
import java.util.Collection;

public class ScenarioContextExamples {
    
    @Before
    public void beforeScenario(Scenario scenario) {
        // Log scenario start
        scenario.log("Starting scenario: " + scenario.getName());
        
        // Check scenario tags for setup decisions
        Collection<String> tags = scenario.getSourceTagNames();
        
        if (tags.contains("@database")) {
            scenario.log("Initializing database for scenario");
            initializeDatabase();
        }
        
        if (tags.contains("@web")) {
            scenario.log("Starting web driver");
            startWebDriver();
        }
        
        // Log scenario metadata
        scenario.log("Feature file: " + scenario.getUri());
        scenario.log("Line number: " + scenario.getLine());
        scenario.log("Scenario ID: " + scenario.getId());
    }
    
    @After
    public void afterScenario(Scenario scenario) {
        // Log scenario completion
        Status status = scenario.getStatus();
        scenario.log("Scenario completed with status: " + status);
        
        // Handle failed scenarios
        if (scenario.isFailed()) {
            scenario.log("❌ Scenario failed: " + scenario.getName());
            
            // Take screenshot for web tests
            if (scenario.getSourceTagNames().contains("@web")) {
                byte[] screenshot = takeScreenshot();
                scenario.attach(screenshot, "image/png", "Failure Screenshot");
            }
            
            // Attach error logs
            String errorLog = getErrorLog();
            scenario.attach(errorLog, "text/plain", "Error Log");
            
            // Attach system state
            String systemInfo = getSystemInfo();
            scenario.attach(systemInfo, "application/json", "System State");
        } else {
            scenario.log("✅ Scenario passed successfully");
        }
        
        // Cleanup based on tags
        Collection<String> tags = scenario.getSourceTagNames();
        if (tags.contains("@cleanup")) {
            scenario.log("Performing cleanup for @cleanup tag");
            performCleanup();
        }
    }
}

Status Enumeration

Represents the execution status of scenarios and steps.

/**
 * Execution status enumeration for scenarios and steps
 */
public enum Status {
    
    /** Step/scenario executed successfully */
    PASSED,
    
    /** Step/scenario was skipped */
    SKIPPED,
    
    /** Step is marked as pending (not yet implemented) */
    PENDING,
    
    /** No matching step definition found */
    UNDEFINED,
    
    /** Multiple matching step definitions found */
    AMBIGUOUS,
    
    /** Step/scenario execution failed */
    FAILED,
    
    /** Step was not executed (unused) */
    UNUSED
}

Usage Examples:

import io.cucumber.java.After;
import io.cucumber.java.Status;
import io.cucumber.java.Scenario;

public class StatusHandlingExamples {
    
    @After
    public void handleScenarioStatus(Scenario scenario) {
        Status status = scenario.getStatus();
        
        switch (status) {
            case PASSED:
                scenario.log("✅ All steps passed successfully");
                recordSuccessMetrics();
                break;
                
            case FAILED:
                scenario.log("❌ One or more steps failed");
                handleFailure(scenario);
                break;
                
            case SKIPPED:
                scenario.log("⏭️ Scenario was skipped");
                recordSkippedTest();
                break;
                
            case PENDING:
                scenario.log("⏳ Scenario has pending steps");
                reportPendingSteps();
                break;
                
            case UNDEFINED:
                scenario.log("❓ Scenario has undefined steps");
                reportUndefinedSteps();
                break;
                
            case AMBIGUOUS:
                scenario.log("⚠️ Scenario has ambiguous step definitions");
                reportAmbiguousSteps();
                break;
                
            case UNUSED:
                scenario.log("⭕ Scenario was not executed");
                break;
                
            default:
                scenario.log("❓ Unknown status: " + status);
        }
    }
    
    private void handleFailure(Scenario scenario) {
        // Specific failure handling
        scenario.log("Failure details for: " + scenario.getName());
        
        // Attach debug information
        String debugInfo = gatherDebugInformation();
        scenario.attach(debugInfo, "text/plain", "Debug Information");
        
        // Send failure notification
        sendFailureNotification(scenario.getName(), scenario.getUri().toString());
    }
}

Attachment and Logging

Comprehensive reporting capabilities for attaching files, screenshots, and logging information.

/**
 * Binary attachment with media type specification
 */
public void attach(byte[] data, String mediaType, String name);

/**
 * Text attachment with media type specification  
 */
public void attach(String data, String mediaType, String name);

/**
 * Simple text logging
 */
public void log(String text);

Usage Examples:

import io.cucumber.java.After;
import io.cucumber.java.AfterStep;
import io.cucumber.java.Before;
import io.cucumber.java.Scenario;
import java.io.File;
import java.nio.file.Files;

public class AttachmentExamples {
    
    @Before("@web")
    public void beforeWebScenario(Scenario scenario) {
        scenario.log("🌐 Starting web scenario: " + scenario.getName());
        
        // Attach browser configuration
        String browserConfig = getBrowserConfiguration();
        scenario.attach(browserConfig, "application/json", "Browser Configuration");
    }
    
    @AfterStep("@screenshot")
    public void takeScreenshotAfterStep(Scenario scenario) {
        // Take screenshot after each step for visual tests
        byte[] screenshot = takeScreenshot();
        scenario.attach(screenshot, "image/png", "Step Screenshot");
        
        scenario.log("📸 Screenshot captured after step");
    }
    
    @After
    public void attachTestResults(Scenario scenario) {
        // Always attach test execution log
        String executionLog = getExecutionLog();
        scenario.attach(executionLog, "text/plain", "Execution Log");
        
        if (scenario.isFailed()) {
            // Attach comprehensive failure information
            attachFailureDetails(scenario);
        }
        
        // Attach performance metrics
        String performanceData = getPerformanceMetrics();
        scenario.attach(performanceData, "application/json", "Performance Metrics");
    }
    
    private void attachFailureDetails(Scenario scenario) {
        scenario.log("🔍 Collecting failure details...");
        
        // Screenshot for UI tests
        if (scenario.getSourceTagNames().contains("@web")) {
            byte[] screenshot = takeScreenshot();
            scenario.attach(screenshot, "image/png", "Failure Screenshot");
            scenario.log("📸 Failure screenshot captured");
        }
        
        // Browser logs for web tests
        if (scenario.getSourceTagNames().contains("@web")) {
            String browserLogs = getBrowserLogs();
            scenario.attach(browserLogs, "text/plain", "Browser Console Logs");
        }
        
        // Database state for data tests
        if (scenario.getSourceTagNames().contains("@database")) {
            String dbState = getDatabaseState();
            scenario.attach(dbState, "application/json", "Database State");
        }
        
        // API response for integration tests
        if (scenario.getSourceTagNames().contains("@api")) {
            String lastResponse = getLastApiResponse();
            scenario.attach(lastResponse, "application/json", "Last API Response");
        }
        
        // System logs
        String systemLogs = getSystemLogs();
        scenario.attach(systemLogs, "text/plain", "System Logs");
        
        // Stack trace
        String stackTrace = getStackTrace();
        scenario.attach(stackTrace, "text/plain", "Stack Trace");
        
        scenario.log("🔍 Failure details collection complete");
    }
    
    // Example of attaching various file types
    public void attachVariousFileTypes(Scenario scenario) {
        try {
            // HTML report
            String htmlReport = generateHtmlReport();
            scenario.attach(htmlReport, "text/html", "Test Report");
            
            // JSON data
            String jsonData = getTestData();
            scenario.attach(jsonData, "application/json", "Test Data");
            
            // XML configuration
            String xmlConfig = getXmlConfiguration();
            scenario.attach(xmlConfig, "application/xml", "Configuration");
            
            // CSV data
            String csvData = getCsvData();
            scenario.attach(csvData, "text/csv", "Data Export");
            
            // Binary file
            File logFile = new File("application.log");
            if (logFile.exists()) {
                byte[] logContent = Files.readAllBytes(logFile.toPath());
                scenario.attach(logContent, "application/octet-stream", "Application Log");
            }
            
            // PDF report
            byte[] pdfReport = generatePdfReport();
            scenario.attach(pdfReport, "application/pdf", "PDF Report");
            
        } catch (Exception e) {
            scenario.log("⚠️ Error attaching files: " + e.getMessage());
        }
    }
}

Scenario Metadata Access

Access detailed scenario metadata for conditional logic and reporting.

public class ScenarioMetadataExamples {
    
    @Before
    public void analyzeScenario(Scenario scenario) {
        // Basic metadata
        String name = scenario.getName();
        String uri = scenario.getUri().toString();
        Integer line = scenario.getLine();
        String id = scenario.getId();
        
        scenario.log("📋 Scenario Analysis:");
        scenario.log("  Name: " + name);
        scenario.log("  File: " + uri);
        scenario.log("  Line: " + line);
        scenario.log("  ID: " + id);
        
        // Tag analysis
        Collection<String> tags = scenario.getSourceTagNames();
        scenario.log("  Tags: " + String.join(", ", tags));
        
        // Conditional setup based on metadata
        if (name.toLowerCase().contains("slow")) {
            scenario.log("⏰ Slow test detected - increasing timeouts");
            increaseTimeouts();
        }
        
        if (uri.contains("critical")) {
            scenario.log("🚨 Critical test - enabling detailed logging");
            enableDetailedLogging();
        }
        
        // Tag-based configuration
        configureBasedOnTags(scenario, tags);
    }
    
    private void configureBasedOnTags(Scenario scenario, Collection<String> tags) {
        if (tags.contains("@performance")) {
            scenario.log("⚡ Performance test - starting profiler");
            startProfiler();
        }
        
        if (tags.contains("@security")) {
            scenario.log("🔒 Security test - enabling security monitoring");
            enableSecurityMonitoring();
        }
        
        if (tags.contains("@integration")) {
            scenario.log("🔗 Integration test - checking external services");
            checkExternalServices();
        }
        
        if (tags.contains("@smoke")) {
            scenario.log("💨 Smoke test - using minimal setup");
            useMinimalSetup();
        }
        
        // Environment-specific tags
        if (tags.contains("@dev-only") && !isDevEnvironment()) {
            scenario.log("⏭️ Dev-only test in non-dev environment - will skip");
        }
        
        if (tags.contains("@prod-safe") && isProdEnvironment()) {
            scenario.log("✅ Production-safe test in prod environment");
        }
    }
    
    @After
    public void reportScenarioMetrics(Scenario scenario) {
        // Create detailed scenario report
        String report = String.format(
            "Scenario Execution Report:\n" +
            "  Name: %s\n" +
            "  Status: %s\n" +
            "  File: %s (line %d)\n" +
            "  Tags: %s\n" +
            "  Duration: %d ms\n" +
            "  Steps: %d\n",
            scenario.getName(),
            scenario.getStatus(),
            scenario.getUri(),
            scenario.getLine(),
            String.join(", ", scenario.getSourceTagNames()),
            getExecutionDuration(scenario.getId()),
            getStepCount(scenario.getId())
        );
        
        scenario.attach(report, "text/plain", "Execution Report");
        scenario.log("📊 Execution report generated");
    }
}

PendingException

Exception class for marking steps as not yet implemented, commonly used during BDD development.

/**
 * Exception to mark steps as pending (not yet implemented)
 */
public final class PendingException extends RuntimeException {
    
    /**
     * Create pending exception with default message "TODO: implement me"
     */
    public PendingException();
    
    /**
     * Create pending exception with custom message
     * @param message Custom message describing what needs to be implemented
     */
    public PendingException(String message);
}

Usage Examples:

import io.cucumber.java.PendingException;
import io.cucumber.java.en.*;

public class PendingStepExamples {
    
    @Given("the user is logged in")
    public void the_user_is_logged_in() {
        // TODO: Implement user login logic
        throw new PendingException("User login not yet implemented");
    }
    
    @When("I perform a complex calculation")
    public void i_perform_complex_calculation() {
        // TODO: Implement calculation logic
        throw new PendingException("Complex calculation algorithm pending");
    }
    
    @Then("the result should be accurate")
    public void the_result_should_be_accurate() {
        // Placeholder for result validation
        throw new PendingException();
    }
    
    @Given("the external API is available")
    public void external_api_available() {
        // TODO: Check API availability
        throw new PendingException("API availability check not implemented - requires API client setup");
    }
    
    // Pattern: Implement step gradually
    @When("I submit the payment form")
    public void submit_payment_form() {
        // Step 1: Form validation (implemented)
        validatePaymentForm();
        
        // Step 2: Payment processing (pending)
        throw new PendingException("Payment processing integration pending - waiting for payment gateway setup");
        
        // Step 3: Result handling (not reached)
        // handlePaymentResult();
    }
    
    // Pattern: Feature flag for incomplete features
    @Then("the new feature should be visible")
    public void new_feature_visible() {
        if (!isFeatureFlagEnabled("NEW_FEATURE")) {
            throw new PendingException("New feature behind feature flag - implementation complete but not enabled");
        }
        
        // Feature implementation here when enabled
        validateNewFeature();
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-io-cucumber--cucumber-java

docs

data-handling.md

hooks.md

index.md

parameter-transformation.md

runtime-context.md

step-definitions.md

tile.json