Running Tests

Execute your SpecFlow test suite with various options for filtering, parallelisation, and output formats.

Basic Test Execution

Run All Tests

dotnet test ./Tests.E2E/Tests.E2E.csproj

This executes all scenarios in your Tests.E2E/Features/ directory using the NUnit test runner.

Run Specific Features

Filter by feature file name:

dotnet test ./Tests.E2E/Tests.E2E.csproj --filter "FullyQualifiedName~Login"

Filter by feature tag:

# Run scenarios tagged with @smoke dotnet test ./Tests.E2E/Tests.E2E.csproj --filter "FullyQualifiedName~@smoke" # Run scenarios tagged with @regression dotnet test ./Tests.E2E/Tests.E2E.csproj --filter "FullyQualifiedName~@regression"

Run Specific Scenarios

# By scenario name dotnet test ./Tests.E2E/Tests.E2E.csproj --filter "FullyQualifiedName~Successful login"

Parallel Execution

Run tests in parallel to reduce execution time:

# Use 4 parallel workers (adjust to your CPU cores) dotnet test ./Tests.E2E/Tests.E2E.csproj -m:4 # Use all available cores dotnet test ./Tests.E2E/Tests.E2E.csproj -m

Best practices:

  • Start with 2-4 workers and increase based on system resources
  • Monitor CPU and memory usage
  • Some tests may require sequential execution (use @sequential tag)

Sequential Execution

For tests that must run in order:

@sequential
Feature: Multi-step Workflow
    Scenario: Complete checkout process
        Given I add items to cart
        When I proceed to checkout
        Then I should see order confirmation

Run sequential tests:

dotnet test ./Tests.E2E/Tests.E2E.csproj --filter "FullyQualifiedName~@sequential"

Environment Configuration

Using Environment Variables

Override configuration at runtime:

# Set timeout PW_TIMEOUT_MS=3000 dotnet test ./Tests.E2E/Tests.E2E.csproj # Set environment ENVIRONMENT=qa dotnet test ./Tests.E2E/Tests.E2E.csproj # Multiple variables PW_TIMEOUT_MS=5000 ENVIRONMENT=staging dotnet test ./Tests.E2E/Tests.E2E.csproj

Environment-Specific Settings

The framework automatically loads environment-specific configuration:

  1. appsettings.json (base)
  2. appsettings.{ENVIRONMENT}.json (overrides)

Example:

# Uses appsettings.qa.json ENVIRONMENT=qa dotnet test ./Tests.E2E/Tests.E2E.csproj # Uses appsettings.staging.json ENVIRONMENT=staging dotnet test ./Tests.E2E/Tests.E2E.csproj

Test Output Formats

Console Output (Default)

Standard NUnit console output:

dotnet test ./Tests.E2E/Tests.E2E.csproj

HTML Report

Generate an HTML report:

dotnet test ./Tests.E2E/Tests.E2E.csproj --logger "html;LogFileName=report.html"

Output location: Tests.E2E/TestResults/report.html

JUnit XML (for Allure)

Generate JUnit XML for Allure reporting:

dotnet test ./Tests.E2E/Tests.E2E.csproj \ --logger:"junit;LogFileName=junit.xml" \ --results-directory ./allure-results

See Reporting for Allure setup.

Verbose Output

Get detailed test execution information:

dotnet test ./Tests.E2E/Tests.E2E.csproj --verbosity detailed

Test Filtering Strategies

By Tag

# Single tag dotnet test --filter "FullyQualifiedName~@smoke" # Multiple tags (AND) dotnet test --filter "FullyQualifiedName~@smoke&FullyQualifiedName~@login" # Exclude tags dotnet test --filter "FullyQualifiedName!~@skip"

By Feature

# Feature name contains "Login" dotnet test --filter "FullyQualifiedName~Login"

By Scenario

# Scenario name contains "checkout" dotnet test --filter "FullyQualifiedName~checkout"

Timeout Configuration

Global Timeout

Set via environment variable:

PW_TIMEOUT_MS=3000 dotnet test ./Tests.E2E/Tests.E2E.csproj

Per-Test Timeout

Override in LifecycleHooks.cs:

[BeforeScenario]
public async Task SetTimeout()
{
    var timeoutMs = Environment.GetEnvironmentVariable("PW_TIMEOUT_MS");
    if (!string.IsNullOrEmpty(timeoutMs))
    {
        Page.SetDefaultTimeout(int.Parse(timeoutMs));
    }
}

Browser Configuration

Headless Mode

Configure in appsettings.json:

{
  "Headless": true
}

Or override at runtime:

HEADLESS=true dotnet test ./Tests.E2E/Tests.E2E.csproj

Browser Selection

The framework uses Chromium by default. To change:

  1. Update LifecycleHooks.cs:
[BeforeScenario]
public async Task SetupBrowser()
{
    var browserType = Environment.GetEnvironmentVariable("BROWSER") ?? "chromium";
    // Initialise browser based on type
}
  1. Run with browser selection:
BROWSER=firefox dotnet test ./Tests.E2E/Tests.E2E.csproj BROWSER=webkit dotnet test ./Tests.E2E/Tests.E2E.csproj

Debugging Tests

Attach Debugger

Run tests with debugger attached:

dotnet test ./Tests.E2E/Tests.E2E.csproj --logger "console;verbosity=detailed"

Set breakpoints in your step definitions or Page Objects, then attach your IDE debugger.

Screenshots on Failure

Screenshots are automatically captured on test failure. Location: artifacts/screenshots/

Video Recording

Enable video recording for failed tests in LifecycleHooks.cs:

[AfterScenario]
public async Task CaptureVideoOnFailure()
{
    if (ScenarioContext.ScenarioExecutionStatus == ScenarioExecutionStatus.TestError)
    {
        await Page.Video.SaveAsAsync($"artifacts/videos/{ScenarioContext.ScenarioInfo.Title}.webm");
    }
}

Performance Optimisation

Reduce Timeouts for Faster Runs

PW_TIMEOUT_MS=2000 dotnet test ./Tests.E2E/Tests.E2E.csproj -m:4

Skip Non-Critical Tests

Tag non-critical tests and exclude them:

@non-critical
Scenario: Advanced feature test
dotnet test --filter "FullyQualifiedName!~@non-critical"

Use Test Retries

Configure retries in nunit.runsettings:

<NUnit>
  <TestSettings>
    <RetryCount>2</RetryCount>
  </TestSettings>
</NUnit>

Common Commands Reference

# Full suite, parallel dotnet test ./Tests.E2E/Tests.E2E.csproj -m:4 # Smoke tests only dotnet test ./Tests.E2E/Tests.E2E.csproj --filter "FullyQualifiedName~@smoke" # Fast run with reduced timeout PW_TIMEOUT_MS=2000 dotnet test ./Tests.E2E/Tests.E2E.csproj -m:4 # QA environment ENVIRONMENT=qa dotnet test ./Tests.E2E/Tests.E2E.csproj # With HTML report dotnet test ./Tests.E2E/Tests.E2E.csproj --logger "html;LogFileName=report.html" # Verbose output dotnet test ./Tests.E2E/Tests.E2E.csproj --verbosity detailed