Verwendung eines benutzerdefinierten Verzeichnissammlers

Standardmäßig sammelt pytest Verzeichnisse mit pytest.Package für Verzeichnisse mit __init__.py Dateien und pytest.Dir für andere Verzeichnisse. Wenn Sie anpassen möchten, wie ein Verzeichnis gesammelt wird, können Sie Ihren eigenen pytest.Directory Collector schreiben und pytest_collect_directory verwenden, um ihn zu verknüpfen.

Ein einfaches Beispiel für eine Verzeichnis-Manifestdatei

Angenommen, Sie möchten anpassen, wie die Sammlung pro Verzeichnis durchgeführt wird. Hier ist ein Beispiel für ein conftest.py Plugin, das es Verzeichnissen ermöglicht, eine manifest.json Datei zu enthalten, die definiert, wie die Sammlung für das Verzeichnis durchgeführt werden soll. In diesem Beispiel wird nur eine einfache Liste von Dateien unterstützt, Sie können sich jedoch vorstellen, andere Schlüssel wie Ausschlüsse und Globs hinzuzufügen.

# content of conftest.py
from __future__ import annotations

import json

import pytest


class ManifestDirectory(pytest.Directory):
    def collect(self):
        # The standard pytest behavior is to loop over all `test_*.py` files and
        # call `pytest_collect_file` on each file. This collector instead reads
        # the `manifest.json` file and only calls `pytest_collect_file` for the
        # files defined there.
        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):
    # Use our custom collector for directories containing a `manifest.json` file.
    if path.joinpath("manifest.json").is_file():
        return ManifestDirectory.from_parent(parent=parent, path=path)
    # Otherwise fallback to the standard behavior.
    return None

Sie können eine manifest.json Datei und einige Testdateien erstellen

{
    "files": [
        "test_first.py",
        "test_second.py"
    ]
}
# content of test_first.py
from __future__ import annotations


def test_1():
    pass
# content of test_second.py
from __future__ import annotations


def test_2():
    pass
# content of test_third.py
from __future__ import annotations


def test_3():
    pass

Und Sie können nun die Testspezifikation ausführen

customdirectory $ pytest
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y
rootdir: /home/sweet/project/customdirectory
configfile: pytest.ini
collected 2 items

tests/test_first.py .                                                [ 50%]
tests/test_second.py .                                               [100%]

============================ 2 passed in 0.12s =============================

Beachten Sie, dass test_three.py nicht ausgeführt wurde, da es nicht im Manifest aufgeführt ist.

Sie können überprüfen, ob Ihr benutzerdefinierter Collector im Sammlungsprotokoll angezeigt wird

customdirectory $ pytest --collect-only
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y
rootdir: /home/sweet/project/customdirectory
configfile: pytest.ini
collected 2 items

<Dir customdirectory>
  <ManifestDirectory tests>
    <Module test_first.py>
      <Function test_1>
    <Module test_second.py>
      <Function test_2>

======================== 2 tests collected in 0.12s ========================