Test Rerun and Stepwise Execution

This module provides features that enhance the test execution workflow by enabling reruns of failed tests first and supporting stepwise test execution. These capabilities improve developer efficiency by focusing testing on problematic tests and allowing a controlled, incremental test run that stops on failures and resumes from the last failure.


Core Concepts and Purpose

These features address problems such as long test suite runtimes when many tests pass, difficulty in isolating failing tests quickly, and inefficient reruns during test-driven development.


How the Module Works

1. Caching Test Results for Rerun and Stepwise

The system uses the pytest cache directory to store data about failed tests and stepwise execution state. The cache is accessed via a `Cache` object (defined in `src/_pytest/cacheprovider.py`) which provides a persistent JSON-backed storage.

The `Cache` class abstracts reading and writing these JSON-serializable values, automatically managing cache directories and files.

2. Plugins Implementing Rerun and Stepwise Behavior

The rerun and stepwise features are implemented as pytest plugins registered during configuration (`pytest_configure` hook):

LFPlugin: Last-Failed and Failed-First

NFPlugin: New-First

StepwisePlugin: Stepwise Execution


Key Functional Workflows

Test Collection Modification

  1. Last-Failed Plugin reorders or filters test items based on cached failures.

  2. New-First Plugin reorders tests prioritizing new files.

  3. Stepwise Plugin skips tests prior to the last failure if applicable.

def pytest_collection_modifyitems(self, config: Config, items: list[nodes.Item]) -> None:
    # StepwisePlugin example snippet:
    if self.cached_info.last_failed:
        # Find index of last failed test
        failed_index = next(
            (i for i, item in enumerate(items) if item.nodeid == self.cached_info.last_failed),
            None,
        )
        if failed_index is not None:
            # Skip tests before the last failure
            deselected = items[:failed_index]
            del items[:failed_index]
            config.hook.pytest_deselected(items=deselected)

Test Execution and Failure Handling

def pytest_runtest_logreport(self, report: TestReport) -> None:
    if report.failed:
        if self.skip:
            if report.nodeid == self.cached_info.last_failed:
                self.cached_info.last_failed = None
            self.skip = False
        else:
            self.cached_info.last_failed = report.nodeid
            self.session.shouldstop = "Test failed, continuing from this test next run."

Cache Update

At session finish, the plugins write updated failure or stepwise information back to the cache for use in subsequent runs.


Interactions with Other System Components


Important Concepts and Design Patterns


Mermaid Diagram: Sequence of Stepwise Test Execution

sequenceDiagram
    participant User
    participant Pytest CLI
    participant StepwisePlugin
    participant Cache
    participant TestCollection
    participant TestRunner

    User->>Pytest CLI: Runs pytest with --stepwise
    Pytest CLI->>StepwisePlugin: Register plugin and read options
    StepwisePlugin->>Cache: Load last failed test info
    StepwisePlugin->>TestCollection: Modify collected tests
    TestCollection-->>StepwisePlugin: Return filtered/skipped tests
    StepwisePlugin->>TestRunner: Run tests starting from last failure
    TestRunner->>StepwisePlugin: Report test results
    StepwisePlugin->>Cache: Update last failed test info if failure occurs
    StepwisePlugin->>TestRunner: Request stop on failure
    TestRunner-->>User: Test run stops on failure
    User->>Pytest CLI: Runs pytest again with --stepwise
    StepwisePlugin->>Cache: Load last failed test info
    StepwisePlugin->>TestCollection: Skip tests before last failure
    TestRunner->>StepwisePlugin: Run remaining tests
    StepwisePlugin->>Cache: Clear last failed info if tests pass

This documentation explains the rationale, mechanisms, and system integration for pytest’s test rerun and stepwise execution features, illuminating how these capabilities optimize test workflows by leveraging caching, selective test execution, and session control.