historical-notes.rst

Overview

This file serves as a comprehensive historical record of changes and deprecated features in **pytest**, a popular Python testing framework. It documents how specific functionalities, especially related to markers, fixtures, configuration, and plugins, have evolved across different pytest versions. The purpose of this document is to assist users and developers in understanding legacy behaviors, facilitate migration from older pytest versions, and provide context for certain design decisions.

The file is written in reStructuredText format (`.rst`) and is intended to be included in the pytest documentation to aid users who encounter or maintain older codebases.


Detailed Explanations

Marker revamp and iteration

**Section Reference:** `marker-revamp`

**Purpose:** Describes the major redesign of pytest's marker system introduced in pytest 3.6.

**Key Concepts:**

**Implications:** Users should move away from deprecated methods like [Node.get_marker()](/projects/286/67332) and adopt `iter_markers()` and `get_closest_marker()` for reliable marker access.

**Usage Example:**

for skipif_marker in item.iter_markers("skipif"):
    condition = skipif_marker.args[0]
    # Evaluate condition here

Updating code

**Section Reference:** `update marker code`

**Purpose:** Guidance on migrating old marker access patterns to the new API.

**Two scenarios for marker handling:**

  1. Overwriting marks: Only the closest mark matters (e.g., log level).

    marker = item.get_closest_marker("log_level")
    if marker:
        level = marker.args[0]
    
  2. Additive marks: All marks apply (e.g., multiple skipif conditions).

    for skipif in item.iter_markers("skipif"):
        condition = skipif.args[0]
        # process condition
    

Related issues

Lists important bugs and feature requests resolved by the marker revamp, with issue numbers for reference. Examples include:

cache plugin integrated into the core

Explains that the formerly third-party `pytest-cache` plugin has been integrated into pytest core, with some limitations (only JSON serializable data can be cached).

funcargs and pytest_funcarg__

Describes the legacy fixture declaration method using the `pytest_funcarg__NAME` naming convention before the introduction of `@pytest.fixture` in version 2.3. This method is still supported but deprecated.

@pytest.yield_fixture decorator

Before pytest 2.10, `yield_fixture` was required to write fixtures using yield for teardown. Post-2.10, normal fixtures support `yield` natively, and `yield_fixture` is deprecated.

[pytest] header in setup.cfg

Previously the configuration section header was `[pytest]`. Due to conflicts with distutils commands, `[tool:pytest]` is now recommended for `setup.cfg`. For `pytest.ini` and `tox.ini`, `[pytest]` remains the section name.

Applying marks to @pytest.mark.parametrize parameters

Prior to version 3.1, marking individual parameters in `parametrize` used a hacky syntax that was incomplete and buggy. This old syntax is planned for removal in pytest 4.0.

@pytest.mark.parametrize argument names as tuple

Before 2.4, argument names in parametrize had to be specified as a tuple. Now a simpler comma-separated string syntax is preferred.

setup: is now an "autouse fixture"

The old `pytest.setup` hook was replaced by autouse fixtures starting before pytest 2.3.

Conditions as strings instead of booleans

Before pytest 2.4, skipif/xfail conditions were expressed as strings evaluated via `eval()`. Since then, boolean expressions are preferred for better importability and encapsulation. String conditions remain supported.

**Evaluation namespace:** includes `sys`, `os`, `pytest.config`, and module globals.

**Example:**

@pytest.mark.skipif("sys.version_info >= (3,3)")
def test_func():
    ...

is better written as:

@pytest.mark.skipif(sys.version_info >= (3,3), reason="Python version too low")
def test_func():
    ...

pytest.set_trace()

Deprecated since version 2.4. Use standard Python debugger calls (`import pdb; pdb.set_trace()`) instead.

"compat" properties

Access to types such as `Module`, `Function`, `Class`, etc. through `Node` objects is deprecated since pytest 3.9. Users should import these directly from the `pytest` module.


Important Implementation Details


Interactions With Other Parts of the System


Visual Diagram: Marker API Evolution Class Diagram

classDiagram
    class Node {
        +get_marker(name): MarkerInfo (deprecated)
        +get_closest_marker(name): Mark
        +iter_markers(name=None): iterator~Mark~
    }
    class MarkerInfo {
        +name: str
        +args: tuple
        +kwargs: dict
    }
    class Mark {
        +name: str
        +args: tuple
        +kwargs: dict
    }
    Node --> MarkerInfo : old marker API
    Node --> Mark : new marker API

Summary

The [historical-notes.rst](/projects/286/67223) file is a vital resource documenting the evolution of key pytest features. It helps users migrate older tests to newer pytest versions and understand the rationale behind deprecated practices and new recommended patterns. The focus on markers, fixtures, configuration, and plugins highlights pytest's continuous improvement and commitment to usability and robustness.