simple.rst

Overview

This file provides a comprehensive set of **basic patterns and examples** for using and extending the `pytest` testing framework. It serves as a tutorial and reference guide demonstrating common and advanced pytest usage scenarios, including command line option customization, test parametrization based on CLI input, test skipping control, incremental testing, fixture usage, test reporting customization, profiling, and integration with packaging tools.

The content is primarily intended for pytest users and plugin authors who want to understand practical ways to extend and control pytest behavior in projects, or manage test execution more effectively.

The file is organized into multiple example-driven sections, each focusing on a specific pytest feature or pattern, illustrated with code samples and usage explanations.

Detailed Explanations of Key Concepts and Code Examples

1. Changing Command Line Options Defaults

By default, pytest accepts command line options at runtime. To avoid repetitive typing of common options, you can specify defaults in a configuration file `pytest.ini` or via the environment variable `PYTEST_ADDOPTS`.


2. Passing Different Values to Tests Based on Command Line Options

You can define custom command line options and make them available to test functions via fixtures.


3. Dynamically Adding Command Line Options

Plugins or external modules can dynamically modify pytest command line arguments before pytest processes them.

This example automatically adds parallel execution options if the `pytest-xdist` plugin is available.


4. Controlling Skipping of Tests Based on Command Line Options

You can add a CLI option to control whether tests marked with a custom marker (`slow`) are run or skipped.


5. Writing Well Integrated Assertion Helpers

You can write helper functions that fail tests with clear messages and hide themselves from tracebacks unless `--full-trace` is used.


6. Detecting if Running Inside a Pytest Run

Application code can detect if it is running under pytest by checking the environment variable `PYTEST_VERSION`.

import os

if os.environ.get("PYTEST_VERSION") is not None:
    # Running under pytest
    ...
else:
    # Normal execution
    ...

7. Adding Information to Test Report Header

Customize pytest's test session header by implementing the `pytest_report_header` hook.


8. Profiling Test Duration

Use `--durations=N` option to report the slowest N tests.


9. Incremental Testing / Test Steps

Implement an `incremental` marker on test classes to skip tests after a failure in the same class.


10. Package/Directory-level Fixtures (Setups)

Define fixtures scoped to a directory or package by placing them in `conftest.py` inside that directory.


11. Post-process Test Reports / Failures

You can hook into `pytest_runtest_makereport` to post-process test results, e.g., logging all failures to a file.


12. Making Test Result Information Available in Fixtures

Fixtures can access detailed test results after test execution using stash keys and the `pytest_runtest_makereport` hook.


13. PYTEST_CURRENT_TEST Environment Variable

During test execution, pytest sets the environment variable `PYTEST_CURRENT_TEST` containing the current test node id and phase (`setup`, `call`, or `teardown`). This aids in diagnosing stuck tests via external monitoring tools.

Example usage with `psutil`:

import psutil

for pid in psutil.pids():
    environ = psutil.Process(pid).environ()
    if "PYTEST_CURRENT_TEST" in environ:
        print(f'pytest process {pid} running: {environ["PYTEST_CURRENT_TEST"]}')

14. Freezing Pytest (Packaging)

When freezing applications with tools like PyInstaller, you can package pytest inside your executable to allow running tests on end-user machines.

Usage:

./app_main --pytest --verbose --tb=long --junit=xml=results.xml test-suite/

Important Implementation Details

Interactions with Other Parts of the System

Visual Diagram (Class Diagram of Key Hook Implementations and Fixtures)

classDiagram
    class Conftest {
        +pytest_addoption(parser)
        +pytest_configure(config)
        +pytest_collection_modifyitems(config, items)
        +pytest_runtest_makereport(item, call)
        +pytest_runtest_setup(item)
        +pytest_report_header(config)
        +cmdopt(request)
        +db()
        +something(request)
    }

    class IncrementalState {
        -_test_failed_incremental: Dict[str, Dict[Tuple[int, ...], str]]
    }
    Conftest ..> IncrementalState : uses

    class DB {
    }

    Conftest ..> DB : fixture provides

    class pytest {
        <<framework>>
        +fail(message)
        +mark.skip(reason)
        +xfail(reason)
    }

    Conftest ..> pytest : uses hooks and markers

    class Request {
        +config
        +getoption(name)
        +node
        +funcargs
        +stash
    }

    Conftest ..> Request : fixture parameter

This diagram shows the main entities and their relationships in the examples: the `conftest.py` file implements multiple pytest hook functions and fixtures, uses internal state (`_test_failed_incremental`) for incremental tests, and interacts with pytest's core API.


Summary

The [simple.rst](/projects/286/67458) file is an extensive tutorial and pattern collection for customizing and extending pytest. It covers practical techniques for:

The file uses a mixture of concise code examples, shell command snippets, and detailed explanations, making it an invaluable resource for pytest users aiming to implement advanced test workflows and integrations.

This documentation should enable users to understand and apply the demonstrated pytest customization patterns to their own testing projects effectively.