test_conftest.py
Overview
This file contains a suite of tests and utility functions targeting the management, discovery, loading, and behavior of `conftest.py` files within the pytest testing framework. `conftest.py` files are special configuration files used by pytest to define fixtures, hooks, and plugins that influence test discovery and execution.
The tests ensure that `conftest.py` files:
Are correctly discovered in different directory structures, including packages, non-packages, and symlinked directories.
Are properly loaded with correct import semantics, including incremental loading and import order.
Are respected according to pytest options like
--confcutdirand--noconftest.Handle edge cases such as casing differences on case-insensitive file systems, uppercase package names, and special objects inside conftests.
Integrate correctly with pytest's plugin manager (
PytestPluginManager) and fixture resolution.Correctly expose command-line options defined in conftests.
Properly handle exceptions and special import scenarios.
The file also includes helper functions for initializing a `PytestPluginManager` with conftests and a test class to verify visibility and scope of fixtures declared in conftests.
Key Entities
Functions
ConftestWithSetinitial(path) -> PytestPluginManager
Purpose: Creates a new
PytestPluginManagerinstance and initializes it with conftest files starting at the specifiedpath.Parameters:
path(Path): The directory path to start loading conftest files from.
Returns:
PytestPluginManagerinstance initialized with conftests.Usage example:
conftest_manager = ConftestWithSetinitial(Path("/my/project/tests"))Implementation details: Uses the helper
conftest_setinitialto set initial conftests on the plugin manager.
conftest_setinitial(conftest, args, confcutdir=None) -> None
Purpose: Sets the initial conftest files on a given
PytestPluginManagerbased on directory arguments.Parameters:
conftest(PytestPluginManager): The plugin manager instance to initialize.args(Sequence[str | Path]): Sequence of directory paths or strings to initialize conftests from.confcutdir(Path | None): Optional directory to stop conftest discovery (confcutdir).
Returns:
NoneImplementation details: Calls
_set_initial_conftestson the plugin manager with predefined parameters such asimportmode="prepend"andpyargs=False.
Classes
TestConftestValueAccessGlobal
Purpose: Tests related to accessing and loading values provided by conftest files in various directory layouts.
Fixtures:
basedir(module-scoped): Creates a temporary directory structure with nestedconftest.pyfiles and optional__init__.pyto simulate package or non-package structures.
Test Methods:
test_basic_init: Verifies that conftest modules can be loaded and values accessed.test_immediate_initialization_and_incremental_are_the_same: Ensures loading conftests incrementally or immediately results in the same state.test_value_access_not_existing: Confirms that accessing a non-loaded conftest value raisesKeyError.test_value_access_by_path: Tests accessing values defined in nested conftests by directory path.test_value_access_with_confmod: Checks retrieval of both the conftest module and its values, and validates module file location.
TestConftestVisibility
Purpose: Validates the visibility and scope of fixtures declared in conftest files across package and subpackage boundaries.
Key Methods:
_setup_tree: Builds a directory structure with packages and subpackages, each containing conftest files defining fixtures.test_parsefactories_relative_node_ids: Parametrized test that runs pytest from different directories and with different test arguments to verify correct fixture resolution and test outcomes.
Use case: Tests issue #616, ensuring that fixtures in nested conftests override or inherit expectedly based on package boundaries.
Important Implementation Details and Algorithms
The file leverages pytest's internal APIs, particularly
PytestPluginManager, to simulate and test conftest discovery and loading behavior.It uses
conftest_setinitialandConftestWithSetinitialutility wrappers to initialize the plugin manager with conftest files for various test scenarios.Tests simulate real filesystem structures using
tmp_pathandpytesterfixtures to create temporary directories, files, and symlinks.Several tests focus on edge cases like:
Symlink resolution and how conftest discovery behaves with symlinked directories and files.
Case sensitivity on filesystems.
Behavior when
--confcutdiris set to limit conftest loading.Handling of doubled paths or special directory names starting with
--.
The tests also verify that pytest plugins and fixtures defined in conftests are properly registered and accessible.
Use of
pytest.mark.parametrizein tests for coverage of multiple scenarios with varying inputs.Exception handling tests ensure that errors in conftest files lead to expected pytest exit codes and error messages.
Use of monkeypatching to test import order without executing actual conftest code.
Interaction With Other Parts of the System
This file tests integration with
PytestPluginManager, a core pytest component responsible for managing plugins and conftest files.Uses
pytesterfixture extensively, which is a testing utility provided by pytest for running pytest tests in isolated environments and managing test files/directories.Interacts with pytest internals such as
_rget_with_confmod,_loadconftestmodules,_getconftestmodules, and_importconftestmethods ofPytestPluginManager.Verifies behavior of conftest files in relation to pytest command line options such as
--confcutdir,--noconftest, and--pyargs.Tests ensure conftest fixture visibility and plugin registration aligns with pytest's test collection and execution mechanisms.
Usage Examples from Tests
# Initialize a PytestPluginManager with conftests starting from a path
conftest = ConftestWithSetinitial(Path("/path/to/tests"))
# Load conftests incrementally at different subdirectories
conftest._loadconftestmodules(
Path("/path/to/tests/subdir"),
importmode="prepend",
rootpath=Path("/path/to/tests"),
consider_namespace_packages=False,
)
# Access a value 'a' from conftest files for a given path
mod, value = conftest._rget_with_confmod("a", Path("/path/to/tests/subdir"))
print(value)
Mermaid Diagram: Flowchart of Main Functions and Relationships in test_conftest.py
flowchart TD
A[ConftestWithSetinitial(path)] --> B[conftest_setinitial(conftest, args, confcutdir)]
B --> C[PytestPluginManager._set_initial_conftests]
D[TestConftestValueAccessGlobal] -->|Uses| A
D -->|Tests| PytestPluginManager._loadconftestmodules
D -->|Tests| PytestPluginManager._rget_with_confmod
E[TestConftestVisibility] -->|Sets up| _setup_tree
E -->|Runs pytest with various cwd| pytester.inline_run
F[Individual test_* functions] -->|Use| pytester, PytestPluginManager
F -->|Test| conftest discovery, import, options, symlink handling
Summary
The `test_conftest.py` file is a comprehensive pytest test suite focused on verifying the correctness and robustness of conftest file discovery, loading, and usage within pytest. It tests multiple scenarios involving directory structures, import modes, filesystem edge cases, and pytest options related to conftests. The tests ensure that conftest files behave as expected as plugins and fixture providers and that pytest's internal plugin manager correctly handles them. The file plays a crucial role in maintaining the integrity of pytest's configuration and plugin system.