### Install Tox and Run Tests Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/docs/contributing.md Install tox to run all tests within automatically set up virtual environments. This example runs linting and tests for Python 3.12. ```bash pip install tox tox -e linting,py312 ``` -------------------------------- ### Install and Install Pre-commit Hooks Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/CONTRIBUTING.rst Install pre-commit and set up the hooks to run automatically on commits. This ensures code style and checks are followed. ```bash pip install --user pre-commit pre-commit install ``` -------------------------------- ### Install Tox Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/CONTRIBUTING.rst Install tox, a tool used to automate testing in virtual environments. It is used to run all tests and ensure compatibility. ```bash pip install tox ``` -------------------------------- ### Configuration Examples for get_reruns_delay Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Illustrates how get_reruns_delay prioritizes delay settings from command-line, markers, and ini files. ```python # Command line: pytest --reruns 3 --reruns-delay 1.5 @pytest.mark.flaky(reruns=3) def test_example(): pass # get_reruns_delay returns: 1.5 ``` ```python # Marker configuration @pytest.mark.flaky(reruns=3, reruns_delay=0.5) def test_example(): pass # get_reruns_delay returns: 0.5 ``` ```python # Positional argument @pytest.mark.flaky(3, 2.0) # 3 reruns, 2.0 second delay def test_example(): pass # get_reruns_delay returns: 2.0 ``` ```python # pyproject.toml: reruns_delay = 0.25 def test_example(): pass ``` -------------------------------- ### Install pytest-rerunfailures Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/README.md Install the plugin using pip. This command makes the plugin available for use with pytest. ```bash pip install pytest-rerunfailures ``` -------------------------------- ### Simple vs. Complex Condition Syntax Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/condition-syntax.md Illustrates good and bad practices for condition strings. The 'good' example is clear and readable, while the 'bad' example shows a complex, nested logic that should be avoided or documented. ```python # Good: clear and readable @pytest.mark.flaky(reruns=3, condition="sys.platform == 'linux'") # Bad: complex nested logic @pytest.mark.flaky(reruns=3, condition="(sys.platform in ('linux', 'darwin') and sys.version_info >= (3, 11)) or (os.getenv('FORCE_RERUN') == 'true' and os.getenv('ENV') not in ('prod', 'staging'))") ``` -------------------------------- ### Checking xdist Installation Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/integration-and-advanced-usage.md Provides a command to verify if the `xdist` plugin, required for parallel execution, is installed in the current Python environment. ```bash pip list | grep xdist ``` -------------------------------- ### Command-line Usage for Reruns Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/pytest-plugin-hooks.md Examples of how to use the --reruns and related command-line options to control test reruns. ```bash pytest --reruns 3 --reruns-delay 1.5 pytest --only-rerun AssertionError --only-rerun ValueError pytest --rerun-except TimeoutError --rerun-except ConnectionError pytest --reruns-mode append pytest --fail-on-flaky pytest --rerun-show-tracebacks ``` -------------------------------- ### Configuration Priority Examples for get_reruns_count Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Demonstrates how get_reruns_count prioritizes different configuration sources, from command-line options to ini settings. ```python # Command line: pytest --force-reruns 10 @pytest.mark.flaky(reruns=5) def test_example(): pass # get_reruns_count returns: 10 ``` ```python # Command line: pytest --reruns 3 @pytest.mark.flaky(reruns=5) def test_example(): pass # get_reruns_count returns: 5 (marker priority in strict mode) ``` ```python # Command line: pytest --reruns 3 --reruns-mode append @pytest.mark.flaky(reruns=5) def test_example(): pass # get_reruns_count returns: 8 (5 + 3, additive) ``` ```python # Command line: pytest --reruns 3 def test_example(): pass # get_reruns_count returns: 3 ``` ```python # pyproject.toml: reruns = 2 def test_example(): pass # get_reruns_count returns: 2 ``` ```python # No configuration def test_example(): pass # get_reruns_count returns: None ``` -------------------------------- ### Incompatible Options Error Example Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Shows the command-line usage that triggers the UsageError for incompatible --reruns and --pdb options. ```bash pytest --reruns 3 --pdb test_file.py # Error: ERROR: --reruns incompatible with --pdb ``` -------------------------------- ### Socket Protocol Example Exchange Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/status-database.md Illustrates a typical communication exchange between a worker and the server using the defined socket protocol for setting and getting test failure counts. ```text Worker sends: "set|5a7c8f2d|f|1\n" Server stores: {test_hash: {"f": 1}} Worker sends: "get|5a7c8f2d|f|\n" Server responds: "1\n" ``` -------------------------------- ### Remove Failed Setup State Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Removes a test item from the session's setup state if it failed. This is necessary to allow the item to be re-executed during a rerun. ```python def _remove_failed_setup_state_from_session(item): ``` -------------------------------- ### Install pytest-rerunfailures Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/docs/installation.md Use pip to install the pytest-rerunfailures plugin. Ensure you have Python 3.10+ and pytest 8.1+ installed. ```bash $ pip install pytest-rerunfailures ``` -------------------------------- ### Separating Flaky from Deterministic Tests with CLI Arguments Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/integration-and-advanced-usage.md Provides command-line examples for running deterministic tests with minimal reruns and flaky tests with more aggressive rerun configurations. ```bash # Fast, deterministic tests pytest tests/unit/ --reruns 1 # Slow, potentially flaky tests pytest tests/integration/ --reruns 3 --reruns-delay 2 # Network-dependent tests pytest tests/e2e/ --reruns 5 --reruns-delay 5 ``` -------------------------------- ### Checking for pytest-xdist crash item support Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md An example of how to use the `HAS_PYTEST_HANDLECRASHITEM` constant to conditionally enable crash recovery features when pytest-xdist is installed and compatible. ```python from pytest_rerunfailures import HAS_PYTEST_HANDLECRASHITEM if HAS_PYTEST_HANDLECRASHITEM: print("Crash recovery is enabled via pytest-xdist") # Set up additional crash handling else: print("Running without pytest-xdist crash recovery") ``` -------------------------------- ### Checking xdist compatibility Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Demonstrates how to use `works_with_current_xdist` to check the compatibility of the installed pytest-xdist version and print a relevant message. ```python from pytest_rerunfailures import works_with_current_xdist result = works_with_current_xdist() if result is True: print("Using modern pytest-xdist with full rerun support") elif result is False: print("Using old pytest-xdist; rerun logging disabled for parallel tests") else: print("pytest-xdist not installed") ``` -------------------------------- ### Example Error Message for Unsupported Scheduler Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/errors.md This is an example of the error message logged when a test crashes with pytest-xdist and the scheduler does not support rescheduling. ```text Test crashed and could not be rescheduled for rerun. The scheduler 'LoadScopeScheduling' does not support rescheduling crashed tests (mark_test_pending not implemented). Remaining reruns: 2 ``` -------------------------------- ### Example of get_reruns_delay behavior Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Demonstrates the return value of get_reruns_delay based on configuration. No delay is applied if not explicitly configured. ```python # get_reruns_delay returns: 0.25 # No delay configured def test_example(): pass # get_reruns_delay returns: 0 ``` -------------------------------- ### Combine reruns and fail-on-flaky with verbose output Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/configuration.md This example combines the --reruns and --fail-on-flaky options with the -v flag for verbose output, useful for detailed CI reporting. ```bash pytest --reruns 2 --fail-on-flaky -v ``` -------------------------------- ### Initialize ServerStatusDB Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/status-database.md Initializes the master-side status database. It binds a TCP socket to localhost on an ephemeral port and starts a daemon thread to run the server loop. ```python class ServerStatusDB(SocketDB): def __init__(self): super().__init__() self.sock.bind(("127.0.0.1", 0)) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.rerunfailures_db = {} t = threading.Thread(target=self.run_server, daemon=True) t.start() ``` -------------------------------- ### Using Default Scheduler with xdist Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/errors.md Example command to use the default scheduler with pytest-xdist, which supports rescheduling crashed tests. ```bash pytest -n 4 tests/ ``` -------------------------------- ### Example Usage of check_options Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Demonstrates how to explicitly call check_options within a pytest hook to validate command-line options. ```python from pytest_rerunfailures import check_options @pytest.hookimpl def pytest_configure(config): check_options(config) # Validate configuration early ``` -------------------------------- ### Full Configuration with Condition and Other Parameters Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/condition-syntax.md This example demonstrates how `condition` works alongside other `pytest-rerunfailures` marker parameters like `reruns`, `reruns_delay`, and `only_rerun`. ```python @pytest.mark.flaky( reruns=5, reruns_delay=1.5, condition="os.getenv('FLAKY') == 'true'", only_rerun=["TimeoutError"], ) def test_full_config(): # All parameters work together: # 1. Condition must be true # 2. Only rerun on TimeoutError # 3. Rerun up to 5 times # 4. Wait 1.5 seconds between reruns pass ``` -------------------------------- ### Force tests to rerun 10 times for stress-testing Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/configuration.md This example demonstrates using --force-reruns with a higher number to stress-test flaky behavior in specific files. ```bash pytest --force-reruns 10 test_file.py ``` -------------------------------- ### Remove Failed Setup State from Session Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/test-execution-behavior.md Removes a test item from the session's setup state when it fails. This ensures the test and its function-scoped fixtures are re-setup on the next execution. ```python def _remove_failed_setup_state_from_session(item): """Clean up setup state.""" setup_state = item.session._setupstate if item in setup_state.stack: del setup_state.stack[item] ``` -------------------------------- ### Platform-Specific Rerun Configuration in conftest.py Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/configuration.md Dynamically apply different rerun configurations using markers based on the operating system. This example sets different rerun counts for Windows and other platforms. ```python # conftest.py import sys import pytest # Platform-specific markers pytestmark = [] if sys.platform == "win32": pytestmark.append(pytest.mark.flaky(reruns=3)) else: pytestmark.append(pytest.mark.flaky(reruns=1)) ``` -------------------------------- ### Using Pure Functions or Simple Expressions for Conditions Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/condition-syntax.md This example shows the 'good' practice of using a pure function or a simple expression for a condition, ensuring predictable behavior as the condition is evaluated only once. ```python # Good: pure function or simple expression @pytest.mark.flaky(reruns=3, condition="sys.platform == 'linux'") def test_pure(): pass ``` -------------------------------- ### Documenting Complex Conditions Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/condition-syntax.md This example shows how to document a complex condition using a comment. The condition reruns tests on non-Windows systems within a CI environment. ```python @pytest.mark.flaky( reruns=3, # Only rerun on non-Windows systems when in CI environment condition="not sys.platform.startswith('win') and os.getenv('CI') is not None" ) def test_complex(): pass ``` -------------------------------- ### StatusDB _hash Method Example Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/status-database.md Demonstrates how to generate a cached SHA1 hash for a test node ID using the _hash method. This is used internally for efficient storage and retrieval of test status. ```python db = StatusDB() hash_val = db._hash("test_file.py::test_name") # Returns something like: "5a7c8f2d3e" ``` -------------------------------- ### Force all tests to rerun 3 times with short traceback Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/configuration.md This example shows how to use --force-reruns in a CI/CD environment for extra validation, combined with --tb=short for concise output. ```bash pytest --force-reruns 3 --tb=short ``` -------------------------------- ### GitHub Actions Workflow for Testing with Reruns Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/integration-and-advanced-usage.md Configure a GitHub Actions workflow to install dependencies, run tests with specified rerun options, and upload rerun reports as artifacts. ```yaml name: Tests with Rerun Support on: [push, pull_request] jobs: test: runs-on: ubuntu-latest strategy: matrix: python-version: ['3.10', '3.11', '3.12'] steps: - uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | pip install -e . pip install pytest pytest-xdist - name: Run tests with reruns run: | pytest \ --reruns 2 \ --reruns-delay 1 \ --rerun-show-tracebacks \ --fail-on-flaky \ tests/ - name: Archive rerun report if: always() uses: actions/upload-artifact@v3 with: name: rerun-report-py${{ matrix.python-version }} path: .pytest_cache/rerun_report.txt ``` -------------------------------- ### Correct Forms for Reruns Delay Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/errors.md Examples of valid configurations for the reruns_delay parameter, specifying no delay or a positive delay time. ```python import pytest @pytest.mark.flaky(reruns=3, reruns_delay=0) # No delay def test_no_delay(): pass @pytest.mark.flaky(reruns=3, reruns_delay=1.5) # 1.5 seconds delay def test_positive_delay(): pass ``` -------------------------------- ### Using Environment Variables for Test Rerun Configuration Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/condition-syntax.md This example demonstrates using an environment variable ('FLAKY_TESTS') to control test reruns, offering flexibility over hardcoded conditions. ```python # Good: flexible, configurable @pytest.mark.flaky( reruns=3, condition="os.getenv('FLAKY_TESTS') == 'true'" ) def test_with_env_config(): # Rerun if FLAKY_TESTS environment variable is set to 'true' pass ``` -------------------------------- ### Example Output for Rerun Test Summary Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/pytest-plugin-hooks.md Shows the format of the summary added to the terminal by the `pytest_terminal_summary` hook, including the test name and optionally its traceback. ```text ========================= rerun test summary info ========================== RERUN test_file.py::test_fail AssertionError: assert False ``` -------------------------------- ### Use Simple Boolean or String Conditions Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/errors.md Examples of correct forms for specifying conditions in flaky markers, using simple boolean values or evaluated string expressions. ```python import pytest # Boolean value @pytest.mark.flaky(reruns=3, condition=True) def test_bool(): pass # String condition (evaluated) @pytest.mark.flaky(reruns=3, condition="os.getenv('FLAKY') == 'true'") def test_string_condition(): pass ``` -------------------------------- ### Adaptive Rerun Delay in conftest.py Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/integration-and-advanced-usage.md Implement adaptive rerun delays within conftest.py. This example increases the delay for tests involving network operations. ```python import pytest import os from pytest_rerunfailures import get_reruns_delay @pytest.hookimpl def pytest_runtest_protocol(item, nextitem): delay = get_reruns_delay(item) # Increase delay for network tests if 'network' in item.nodeid: delay *= 2 # Store for later use item._effective_delay = delay ``` -------------------------------- ### Get Global Reruns Setting Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Fetches the global `--reruns` setting, which can be configured via command-line arguments or a config file. ```python def _get_global_reruns(item): ``` -------------------------------- ### GitLab CI Configuration for Running Tests with Reruns Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/integration-and-advanced-usage.md Set up a GitLab CI job to install dependencies, execute tests with rerun flags, and define artifacts for reporting, while allowing failures for flaky tests. ```yaml test: stage: test script: - pip install pytest pytest-xdist - pytest \ --reruns 2 \ --reruns-delay 1 \ --rerun-show-tracebacks \ --fail-on-flaky \ tests/ artifacts: when: always reports: junit: report.xml allow_failure: false # Fail on flaky tests ``` -------------------------------- ### Ensuring Database Transaction Reset Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/integration-and-advanced-usage.md Provides an example `conftest.py` fixture that ensures database transactions are properly reset after each test, which is crucial for reliable testing, especially with flaky tests. ```python # conftest.py @pytest.fixture(autouse=True) def reset_db(): # Setup yield # Django handles rollback automatically ``` -------------------------------- ### Troubleshooting: Debugging Conditional Logic Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/integration-and-advanced-usage.md Provides an example of debugging conditional logic that might affect test execution or reruns by printing relevant system information. ```python # Debug condition import sys print(sys.platform.startswith("linux")) # Should be True ``` -------------------------------- ### Handle Client Connection Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/status-database.md Handles a single client connection by receiving and processing messages. It supports 'set' and 'get' operations for test failure and rerun data. Exits on connection error. ```python def run_connection(self, conn: socket.socket) -> None: pass ``` -------------------------------- ### Investigating Flakiness with Tracebacks Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/integration-and-advanced-usage.md Explains how to use the `--rerun-show-tracebacks` option to display all failure tracebacks, aiding in the understanding of flakiness patterns. ```bash # Show all failure tracebacks to understand flakiness pattern pytest --reruns 2 --rerun-show-tracebacks tests/flaky_test.py::test_something ``` -------------------------------- ### CircleCI Configuration for Running Tests with Reruns Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/integration-and-advanced-usage.md Configure a CircleCI job to check out code, install dependencies, run tests with rerun options, and store test results and artifacts. ```yaml version: 2.1 jobs: test: docker: - image: cimg/python:3.11 steps: - checkout - run: name: Install dependencies command: | pip install -e . pip install pytest - run: name: Run tests with reruns command: | pytest \ --reruns 2 \ --reruns-delay 1 \ --rerun-show-tracebacks \ --fail-on-flaky \ tests/ - store_test_results: path: test-results - store_artifacts: path: test-results ``` -------------------------------- ### Internal _get Method Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/status-database.md This internal method sends a 'get' request to the server and reads the response. It's used for retrieving test status information. ```python def _get(self, i: str, k: str) -> int: ``` -------------------------------- ### Troubleshooting: Checking Exception Filters with CLI Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/integration-and-advanced-usage.md Shows how to verify that the `--only-rerun` filter is correctly configured and matches the expected error pattern when troubleshooting. ```bash # If using --only-rerun, verify error matches pattern pytest test_file.py::test_name --only-rerun "AssertionError" -v ``` -------------------------------- ### Rerun Tests Not in Production Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/condition-syntax.md This example reruns a test 3 times if the environment is not 'production'. It uses `os.getenv` to check the environment variable 'ENV', defaulting to 'development'. ```python import os @pytest.mark.flaky( reruns=3, condition="os.getenv('ENV', 'development') != 'production'" ) def test_not_in_production(): # Rerun in dev/staging, not production pass ``` -------------------------------- ### Accessing Plugin State in Pytest Hooks Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/module-reference.md Provides examples of how to access pytest configuration and check for the presence of plugins like 'rerunfailures' and 'xdist' within a pytest hook. ```python # In pytest hook config = item.session.config # Check if plugin is active if config.pluginmanager.hasplugin("rerunfailures"): print("Plugin is loaded") # Access database db = config.failures_db print(f"Database type: {type(db).__name__}") # Check if xdist is available if config.pluginmanager.hasplugin("xdist"): print("xdist is loaded") ``` -------------------------------- ### Monitor Flakiness in CI Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/errors.md Use command-line options to track flaky tests within a Continuous Integration environment and display tracebacks for reruns. ```bash # Track flakiness in CI pytest --reruns 2 --fail-on-flaky --rerun-show-tracebacks ``` -------------------------------- ### Example: Accessing Tracked Failure Statuses in Conftest Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/pytest-plugin-hooks.md Shows how to access the `_test_failed_statuses` attribute, which is populated by the `pytest_runtest_makereport` hook, to inspect the failure status of different test phases within a `conftest.py` file. ```python # In conftest.py @pytest.hookimpl(tryfirst=True) def pytest_runtest_makereport(item, call): # Access the tracked failure statuses if hasattr(item, '_test_failed_statuses'): print(f"Failed statuses: {item._test_failed_statuses}") ``` -------------------------------- ### Platform Detection for Conditional Reruns (sys.platform) Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/condition-syntax.md Conditionally rerun tests based on the operating system using `sys.platform`. Examples include running only on Linux, Windows, macOS, or excluding Windows. ```python import pytest import sys # Linux @pytest.mark.flaky(reruns=3, condition="sys.platform.startswith('linux')") def test_linux(): pass # Windows @pytest.mark.flaky(reruns=3, condition="sys.platform.startswith('win')") def test_windows(): pass # macOS @pytest.mark.flaky(reruns=3, condition="sys.platform == 'darwin'") def test_macos(): pass # Not Windows @pytest.mark.flaky(reruns=3, condition="not sys.platform.startswith('win')") def test_not_windows(): pass ``` -------------------------------- ### Python Version Detection for Conditional Reruns (by version) Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/condition-syntax.md Conditionally rerun tests based on the Python version using `sys.version_info`. Examples include rerunning on specific minor versions or ranges of versions. ```python import pytest import sys # Python 3.11+ @pytest.mark.flaky(reruns=3, condition="sys.version_info >= (3, 11)") def test_py311(): pass # Python 3.10 or 3.11 @pytest.mark.flaky(reruns=3, condition="sys.version_info[:2] in ((3, 10), (3, 11))") def test_py310_or_py311(): pass # Not Python 3.9 @pytest.mark.flaky(reruns=3, condition="sys.version_info[:2] != (3, 9)") def test_not_py39(): pass ``` -------------------------------- ### Condition Evaluation Caching Example Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/condition-syntax.md Illustrates that the condition is evaluated only once per test and its result is cached for all rerun decisions. This example uses `random.random()` to show that the outcome is fixed after the first evaluation. ```python import random # WARNING: Condition is evaluated once, before test execution @pytest.mark.flaky(reruns=3, condition="random.random() > 0.5") def test_random_condition(): # Condition result is cached # If first evaluation says rerun is allowed, all reruns are allowed # Even if random changes pass ``` -------------------------------- ### Direct Usage in pytest Hooks Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/status-database.md Example of how to access and use the failures database within pytest hooks, such as setting initial rerun counts, adding failure records, and checking failure counts. ```python @pytest.hookimpl def pytest_runtest_protocol(item, nextitem): db = item.session.config.failures_db # Set initial rerun count db.set_test_reruns(item.nodeid, 3) # After a failure db.add_test_failure(item.nodeid) # Check failure count failures = db.get_test_failures(item.nodeid) if failures >= 3: print(f"Test {item.nodeid} has failed {failures} times") ``` -------------------------------- ### works_with_current_xdist Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Checks compatibility between pytest-rerunfailures and the installed pytest-xdist version. ```APIDOC ## works_with_current_xdist ### Description Checks compatibility between pytest-rerunfailures and the installed pytest-xdist version. ### Method `works_with_current_xdist()` ### Return Type - `bool` or `None`: `True` if xdist >= 1.20.0 is installed, `False` if older xdist is installed, `None` if xdist is not installed ### Behavior 1. Attempts to get the installed pytest-xdist distribution 2. Returns `None` if xdist is not installed 3. Parses the xdist version using `packaging.version.parse()` 4. Returns `True` if version >= 1.20.0, `False` otherwise ### Why This Matters Older versions of pytest-xdist (< 1.20.0) have a bug where the first report that is logged will finish and terminate the current node rather than allow test rerunning. The plugin skips logging of intermediate rerun results when using older xdist versions to work around this limitation. ### Example Usage ```python from pytest_rerunfailures import works_with_current_xdist result = works_with_current_xdist() if result is True: print("Using modern pytest-xdist with full rerun support") elif result is False: print("Using old pytest-xdist; rerun logging disabled for parallel tests") else: print("pytest-xdist not installed") ``` ### Internal Usage Used internally in `pytest_runtest_protocol()` to decide whether to log rerun reports: ```python if not parallel or works_with_current_xdist(): # Log intermediate rerun results item.ihook.pytest_runtest_logreport(report=report) ``` ``` -------------------------------- ### Boolean Conversion Error Example for evaluate_condition Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Demonstrates a TypeError when a condition cannot be converted to a boolean. ```python # Error converting to boolean @pytest.mark.flaky(reruns=3, condition=some_object_with_bad_bool) def test_bad_bool(): pass # Error: "Error evaluating flaky condition as a boolean" # "TypeError: ..." ``` -------------------------------- ### Run Linting and Tests with Tox Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/CONTRIBUTING.rst Execute linting and tests for Python 3.12 using tox. This command ensures code quality and test coverage. ```bash tox -e linting,py312 ``` -------------------------------- ### Dynamic Configuration via conftest.py Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/configuration.md Configure reruns and rerun delay dynamically based on environment variables within conftest.py. This allows for different settings in CI versus local development. ```python # conftest.py import pytest import os def pytest_configure(config): # Set reruns based on environment if os.getenv("CI"): config.option.reruns = 3 config.option.reruns_delay = 1 else: config.option.reruns = 1 config.option.reruns_delay = 0 # Dynamically add markers based on platform import sys pytestmark = [] if sys.platform.startswith("win"): pytestmark.append(pytest.mark.flaky(reruns=2)) ``` -------------------------------- ### HAS_PYTEST_HANDLECRASHITEM Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Module-level constant indicating whether pytest-xdist is installed and compatible with crash item handling. ```APIDOC ## HAS_PYTEST_HANDLECRASHITEM ### Description Module-level constant indicating whether pytest-xdist is installed and compatible. ### Value - `True`: pytest-xdist is installed with `pytest_handlecrashitem` hook support (xdist >= 2.4.0) - `False`: pytest-xdist is not installed or doesn't support crash handling ### Import ```python from pytest_rerunfailures import HAS_PYTEST_HANDLECRASHITEM ``` ### Behavior - Set during module import by attempting to import `pytest_handlecrashitem` from xdist.newhooks - Used internally to determine if XDistHooks should be registered - Can be used by external plugins to detect xdist compatibility ### Example Usage ```python from pytest_rerunfailures import HAS_PYTEST_HANDLECRASHITEM if HAS_PYTEST_HANDLECRASHITEM: print("Crash recovery is enabled via pytest-xdist") # Set up additional crash handling else: print("Running without pytest-xdist crash recovery") ``` ``` -------------------------------- ### Import evaluate_condition Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Shows how to import the evaluate_condition function. ```python from pytest_rerunfailures import evaluate_condition ``` -------------------------------- ### SyntaxError Example for evaluate_condition Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Illustrates a SyntaxError when an invalid condition string is provided to the flaky marker. ```python # SyntaxError in condition string @pytest.mark.flaky(reruns=3, condition="sys.platform.startswith('win") def test_bad_syntax(): pass # Error: "Error evaluating flaky condition" # " sys.platform.startswith('win" # " ^" # "SyntaxError: invalid syntax" ``` -------------------------------- ### Example Usage of is_master Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Shows how to use is_master within a pytest hook to differentiate between master and worker processes. ```python from pytest_rerunfailures import is_master @pytest.hookimpl def pytest_configure(config): if is_master(config): print("Running as master process") else: print("Running as worker process") ``` -------------------------------- ### Configure reruns and delay in setup.cfg Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/configuration.md Set global default rerun count and delay using the [tool:pytest] section in setup.cfg. ```ini [tool:pytest] reruns = 3 reruns_delay = 1.5 ``` -------------------------------- ### Runtime Error Example for evaluate_condition Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Shows a NameError when an undefined variable is used in the condition string for the flaky marker. ```python # Runtime error in condition @pytest.mark.flaky(reruns=3, condition="undefined_variable") def test_undefined(): pass # Error: "Error evaluating flaky condition" # " undefined_variable" # "NameError: name 'undefined_variable' is not defined" ``` -------------------------------- ### Development vs CI Configuration in pyproject.toml Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/configuration.md Set minimal reruns for local development in pyproject.toml and use a command-line option for aggressive rerunning in CI. ```toml [tool.pytest.ini_options] reruns = 1 # Local development: minimal reruns ``` ```bash pytest --force-reruns 5 tests/ # CI: aggressive rerun for validation ``` -------------------------------- ### Conditional Flaky Test Re-run Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/docs/mark.md Re-run a test only if the specified condition evaluates to True. This example re-runs only on Windows. ```python import pytest import sys @pytest.mark.flaky(reruns=3, condition=sys.platform.startswith("win32")) def test_example(): import random assert random.choice([True, False]) ``` -------------------------------- ### Initialize ClientStatusDB Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/status-database.md Initializes the worker-side status database client. It connects to the master ServerStatusDB using the provided socket port. ```python class ClientStatusDB(SocketDB): def __init__(self, sock_port: int): super().__init__() self.sock.connect(("127.0.0.1", sock_port)) ``` -------------------------------- ### Get Pytest Flaky Marker Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Retrieves the `@pytest.mark.flaky` marker from a test item. Returns None if the marker is not present. ```python def _get_marker(item): ``` -------------------------------- ### Example Usage of get_reruns_delay in Hook Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Use get_reruns_delay within a pytest hook to introduce a delay between test reruns if configured. ```python # Use in a custom plugin to implement custom timing logic from pytest_rerunfailures import get_reruns_delay import time @pytest.hookimpl def pytest_runtest_protocol(item, nextitem): delay = get_reruns_delay(item) if delay > 0: time.sleep(delay) ``` -------------------------------- ### Avoid Confusing Rerun Configurations Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/errors.md Be mindful of configurations that may not provide practical benefits, such as rerunning a test only once with no delay. ```bash # Avoid confusing combinations pytest --reruns 1 --reruns-delay 0 # What's the point? ``` -------------------------------- ### Basic Rerun Configuration via Command-Line Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/README.md Run tests with a specified number of reruns using the --reruns option. This is useful for transient test failures. ```bash pytest --reruns 3 tests/ ``` -------------------------------- ### Example Usage of get_reruns_count in Fixture Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Utilize get_reruns_count within a pytest fixture to log rerun information for each test node. ```python # conftest.py from pytest_rerunfailures import get_reruns_count @pytest.fixture(autouse=True) def log_reruns(request): reruns = get_reruns_count(request.node) print(f"Reruns for {request.node.name}: {reruns}") ``` -------------------------------- ### Correct Reruns Configuration in pyproject.toml Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/errors.md Example of a valid integer 'reruns' value in pyproject.toml, which will be correctly parsed and used by pytest-rerunfailures. ```toml [tool.pytest.ini_options] reruns = 3 # Correct ``` -------------------------------- ### Show tracebacks and summary for reruns Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/configuration.md Combine --rerun-show-tracebacks with -rR to display detailed tracebacks from failed reruns and a summary of test outcomes. ```bash pytest --reruns 2 --rerun-show-tracebacks -rR ``` -------------------------------- ### Get Exception Filter Regex Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Retrieves exception filter patterns (only_rerun or rerun_except) from either a marker or command-line options. ```python def _get_rerun_filter_regex(item, regex_name): ``` -------------------------------- ### Show Tracebacks for Retried Failures (Command Line) Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/README.rst Use '--rerun-show-tracebacks' to display tracebacks for all attempts of a flaky test, not just the final one. ```bash pytest --reruns 2 --rerun-show-tracebacks ``` -------------------------------- ### Checking rerun eligibility in a hook Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md An example of how to use `get_reruns_condition` within a pytest hook to determine if a test item is eligible for reruns. ```python @pytest.hookimpl def pytest_runtest_protocol(item, nextitem): if get_reruns_condition(item): print(f"Test {item.nodeid} is eligible for reruns") else: print(f"Test {item.nodeid} is NOT eligible for reruns") ``` -------------------------------- ### Example Usage of get_reruns_count Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Use get_reruns_count within a pytest hook to determine and log the number of reruns configured for a test item. ```python @pytest.hookimpl(tryfirst=True) def pytest_runtest_protocol(item, nextitem): reruns = get_reruns_count(item) if reruns is None: print(f"Test {item.nodeid} has no reruns configured") else: print(f"Test {item.nodeid} will rerun up to {reruns} times") ``` -------------------------------- ### Invalid Reruns Configuration in pyproject.toml Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/errors.md Example of an invalid 'reruns' value in pyproject.toml. This configuration will be ignored, and tests will run without reruns. ```toml [tool.pytest.ini_options] reruns = "not_a_number" # Invalid ``` -------------------------------- ### Basic Rerun Configuration Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/errors.md Configure the number of reruns and the delay between them for flaky tests. ```bash # Clear and maintainable pytest --reruns 2 --reruns-delay 1.0 ``` -------------------------------- ### Get Server Listening Port Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/status-database.md Retrieves the port number on which the server socket is listening. This is useful for clients to know which port to connect to. ```python @property def sock_port(self) -> int: pass ``` -------------------------------- ### Documenting Flaky Tests with Comments Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/integration-and-advanced-usage.md Shows how to document the reason for a test's flakiness directly within the marker, including external issue links and explanations for reruns. ```python @pytest.mark.flaky( reruns=3, only_rerun=TimeoutError, # Flaky due to: external service occasionally slow # See: https://github.com/myorg/myrepo/issues/123 ) def test_external_service(): """Test integration with external API. Known flaky due to service latency spikes. Reruns on timeout to handle temporary slowness. """ pass ``` -------------------------------- ### Conditional Reruns in CI Environments Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/integration-and-advanced-usage.md Demonstrates how to configure aggressive reruns in CI pipelines while using minimal reruns for local development, controlled by an environment variable. ```bash # Local development: minimal reruns pytest --reruns 1 # CI pipeline: aggressive reruns if [ "$CI" = "true" ]; then pytest --reruns 3 --reruns-delay 1 else pytest --reruns 1 fi ``` -------------------------------- ### Troubleshooting: Verifying Test Failure Consistency Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/integration-and-advanced-usage.md Suggests running a specific test with `-v` to confirm if it consistently fails, which is a prerequisite for reruns to be effective. ```bash pytest test_file.py::test_name -v # Does it fail consistently? ``` -------------------------------- ### Get Rerun Count Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/module-reference.md Retrieves the number of times a test is configured to rerun. Useful for logging or conditional logic within test execution. ```python from pytest_rerunfailures import get_reruns_count reruns = get_reruns_count(item) print(f"Test will rerun {reruns} times") ``` -------------------------------- ### Specific vs. General Exception Filters Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/integration-and-advanced-usage.md Illustrates the best practice of using specific exception filters like `only_rerun=TimeoutError` to avoid masking real problems by rerunning on all errors. ```python # Good: Specific about what can be rerun @pytest.mark.flaky(reruns=3, only_rerun=TimeoutError) def test_api_call(): pass # Bad: Rerun on all errors (masks real problems) @pytest.mark.flaky(reruns=3) def test_api_call(): pass ``` -------------------------------- ### Example Usage of evaluate_condition Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Demonstrates how to use evaluate_condition within a pytest hook to determine if a test should be rerun based on a flaky marker's condition. ```python from pytest_rerunfailures import evaluate_condition @pytest.hookimpl def pytest_runtest_protocol(item, nextitem): marker = item.get_closest_marker("flaky") if marker and "condition" in marker.kwargs: condition = marker.kwargs["condition"] should_rerun = evaluate_condition(item, marker, condition) if should_rerun: print(f"Condition {condition} evaluated to True") ``` -------------------------------- ### Rerun with Exception Class Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/flaky-marker.md Uses an exception class for rerunning a test, which includes matching subclasses. This example matches TimeoutError and its subclasses like CustomTimeout. ```python class CustomTimeout(TimeoutError): pass @pytest.mark.flaky(only_rerun=TimeoutError) def test_exception_class(): # Matches TimeoutError AND CustomTimeout (subclass) raise CustomTimeout() ``` -------------------------------- ### Show Rerun Summary Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/public-functions.md Formats and displays summary lines for test reruns in the terminal output. Optionally includes tracebacks. ```python def show_rerun(terminalreporter, show_tracebacks=False): ``` -------------------------------- ### Verbose Output for xdist Debugging Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/integration-and-advanced-usage.md Suggests using verbose output (`-vv`) when running with `pytest-xdist` and reruns to get more detailed information about test execution. ```bash pytest -n 4 --reruns 2 -vv # See what's happening ``` -------------------------------- ### Platform Detection for Conditional Reruns (platform module) Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/condition-syntax.md Use the `platform` module for more explicit platform detection, such as checking the system name or CPU architecture. This provides a more detailed way to control reruns based on the environment. ```python import pytest import platform @pytest.mark.flaky(reruns=3, condition="platform.system() == 'Windows'") def test_windows_system(): # More explicit than sys.platform pass @pytest.mark.flaky(reruns=3, condition="'arm' in platform.machine()") def test_arm_architecture(): # Run on ARM CPUs pass ``` -------------------------------- ### Rerun with Conditions and Delay Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/flaky-marker.md Reruns a test 5 times with a 1-second delay, but only on non-Windows systems and for timeout errors. ```python import pytest import sys @pytest.mark.flaky( reruns=5, reruns_delay=1, condition="not sys.platform.startswith('win32')", only_rerun=TimeoutError ) def test_linux_timeout_retries(): pass ``` -------------------------------- ### get_reruns_delay() Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/module-reference.md Gets the configured delay between test reruns. This is important for controlling the pacing of retries, especially in scenarios where external resources might be temporarily unavailable. ```APIDOC ## get_reruns_delay() ### Description Gets the delay between reruns. ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```python from pytest_rerunfailures import get_reruns_delay delay = get_reruns_delay(item) print(f"Delay between reruns: {delay}s") ``` ### Response #### Success Response - **delay** (float) - The delay in seconds between reruns. ``` -------------------------------- ### pytest_runtest_protocol Hook Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/module-reference.md This hook is called first in the test protocol. It prints the node ID of the test being started and retrieves the configured number of reruns for the item. ```python import pytest @pytest.hookimpl(tryfirst=True) def pytest_runtest_protocol(item, nextitem): print(f"\n>>> Starting protocol for {item.nodeid}") from pytest_rerunfailures import get_reruns_count print(f" Reruns configured: {get_reruns_count(item)}") ``` -------------------------------- ### Database Selection Logic in pytest_configure Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/status-database.md This code snippet demonstrates how the appropriate database class (ServerStatusDB, ClientStatusDB, or StatusDB) is selected based on the presence of pytest-xdist and the role of the current process (master or worker). ```python if config.pluginmanager.hasplugin("xdist") and HAS_PYTEST_HANDLECRASHITEM: config.pluginmanager.register(XDistHooks()) if is_master(config): config.failures_db = ServerStatusDB() # Master process else: config.failures_db = ClientStatusDB(config.workerinput["sock_port"]) # Worker else: config.failures_db = StatusDB() # No-op database for single-process ``` -------------------------------- ### Complex Filtering with Conditional Reruns Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/integration-and-advanced-usage.md Combine 'condition', 'only_rerun', and 'reruns' for sophisticated rerun control. This example reruns only specific errors and only when an environment variable is set. ```python import pytest import os @pytest.mark.flaky( reruns=3, condition="os.getenv('RERUN_FLAKY') == 'true'", only_rerun=["timeout", "ConnectionRefused"], ) def test_external_service(): """Only rerun timeouts/connection errors, and only if enabled via env""" # This test: # 1. Only reruns if RERUN_FLAKY=true environment variable is set # 2. Only reruns on timeout or connection refused errors # 3. Fails immediately on other errors pass ``` -------------------------------- ### Example: Accessing Execution Count in Conftest Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/pytest-plugin-hooks.md Demonstrates how to access the `execution_count` attribute added to a test item by the `pytest_runtest_protocol` hook, typically within a `conftest.py` file. ```python @pytest.hookimpl(tryfirst=True) def pytest_runtest_makereport(item, call): if hasattr(item, 'execution_count'): print(f"Execution: {item.execution_count}") ``` -------------------------------- ### Run Server Loop Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/status-database.md The main server loop that runs in a daemon thread. It continuously listens for incoming connections and spawns a new thread to handle each connection. ```python def run_server(self) -> None: pass ``` -------------------------------- ### Core and Optional Dependencies Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/module-reference.md Lists the core and optional dependencies required for pytest-rerunfailures. Pytest is the core framework, while pytest-xdist is an optional dependency for parallel execution benefits. ```markdown ### Core Dependencies | Package | Version | Purpose | |---------|---------|---------| | `pytest` | >= 8.1 | Test framework | | `packaging` | >= 17.1 | Version parsing | ### Optional Dependencies | Package | Version | Purpose | Benefit | |---------|---------|---------|---------| | `pytest-xdist` | >= 2.3.0 | Parallel execution | Crash recovery | ``` -------------------------------- ### Positional Arguments for Reruns and Delay Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/flaky-marker.md Demonstrates using positional arguments for specifying the rerun count and delay. This offers a more concise syntax for common configurations. ```python @pytest.mark.flaky(3, 2) def test_with_positional_args(): pass ``` -------------------------------- ### Checking xdist Compatibility Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/integration-and-advanced-usage.md Shows how to check for the presence of `HAS_PYTEST_HANDLECRASHITEM`, a compatibility flag related to `pytest-xdist` and `pytest-rerunfailures`. ```python from pytest_rerunfailures import HAS_PYTEST_HANDLECRASHITEM print(HAS_PYTEST_HANDLECRASHITEM) # Should be True ``` -------------------------------- ### Example Output for Rerun Test Status Source: https://github.com/pytest-dev/pytest-rerunfailures/blob/master/_autodocs/api-reference/pytest-plugin-hooks.md Illustrates how the `pytest_report_teststatus` hook can modify pytest's terminal output to indicate rerun tests with a custom character and color. ```text test_file.py RRF ```