Custom Directory Collection
Purpose
This subtopic addresses the need for **fine-grained control over how pytest collects test files within specific directories**. While pytest’s default directory collection behavior automatically discovers tests by scanning files and subdirectories (using `pytest.Dir` or [pytest.Package](/projects/286/67337) collectors), there are cases where users want to **restrict or customize which files get collected** based on explicit manifests or rules defined per directory.
Custom Directory Collection solves the problem of controlling test discovery on a per-directory basis by allowing users to define a manifest file (e.g., `manifest.json`) that lists exactly which test files should be considered. This approach provides deterministic, reproducible, and manageable test discovery, especially valuable in large or complex projects where not all files in a directory should be tested or where discovery rules need to be declaratively specified.
Functionality
At the core, this subtopic introduces a **custom directory collector** class and a hook implementation that:
Detects the presence of a manifest file (e.g.,
manifest.json) inside a directory during test collection.When a manifest is found, uses the manifest to determine exactly which files to collect as test modules, ignoring all others.
Uses pytest’s existing file collection mechanism (
pytest_collect_file) to collect test modules listed in the manifest.Falls back to the standard directory collection behavior if no manifest is present.
Key Workflow
Directory Collection Hook (
pytest_collect_directory):
When pytest begins collecting a directory, this hook checks for the presence of a manifest file inside the directory.Custom Collector Instantiation:
If the manifest file exists, pytest uses a custom collector subclass (ManifestDirectory) instead of the default directory collector.Manifest Parsing and File Collection (
ManifestDirectory.collect):
This collector reads the manifest JSON file to extract the list of test files to collect. It then iterates over this list and delegates the collection of each file to pytest’s internal file collection hook.Test Item Generation:
Collected test files are further processed by pytest as usual, producing test items for execution.
Illustrative Code Snippet
class ManifestDirectory(pytest.Directory):
def collect(self):
manifest_path = self.path / "manifest.json"
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
ihook = self.ihook
for file in manifest["files"]:
yield from ihook.pytest_collect_file(
file_path=self.path / file, parent=self
)
@pytest.hookimpl
def pytest_collect_directory(path, parent):
if path.joinpath("manifest.json").is_file():
return ManifestDirectory.from_parent(parent=parent, path=path)
return None
Here, `ManifestDirectory` overrides `collect` to load the manifest and selectively yield collected file nodes. The hook function `pytest_collect_directory` tells pytest to use this collector for directories containing a manifest.
Relationship to Test Discovery and Collection
Custom Directory Collection is a **specialized extension of the broader Test Discovery and Collection system**. While the parent topic covers the default mechanisms for discovering tests (based on file patterns, naming conventions, and directory structure), this subtopic gives users **explicit control to override that behavior on a directory basis**.
It complements the Python Test Collectors subtopic by providing a user-driven way to:
Filter which files within a directory are collected.
Implement custom directory collection rules without modifying global test discovery configurations.
Integrate seamlessly with pytest’s existing file and test item collection machinery via hooks.
Because it leverages the `pytest_collect_directory` hook, this subtopic fits naturally into pytest’s plugin and extension framework, showcasing how pytest’s modular architecture supports custom collection strategies.
Diagram
flowchart TD
A[Start Directory Collection]
B{Manifest File Present?}
C[Use ManifestDirectory Collector]
D[Read manifest.json and parse file list]
E[For each file in manifest]
F[Call pytest_collect_file to collect file]
G[Yield collected test modules]
H[Use Default Directory Collector]
I[Continue with standard collection]
A --> B
B -- Yes --> C
C --> D
D --> E
E --> F
F --> G
G --> I
B -- No --> H
H --> I
This flowchart visualizes how pytest decides between default directory collection and a custom manifest-driven collector, and how the custom collector processes the manifest to selectively collect test files.
By enabling directories to define their own test file manifests, Custom Directory Collection empowers users to tailor test discovery precisely, improving test suite management and execution predictability.