Verwendung temporärer Verzeichnisse und Dateien in Tests

Das tmp_path Fixture

Sie können das tmp_path Fixture verwenden, das ein für jede Testfunktion eindeutiges temporäres Verzeichnis bereitstellt.

tmp_path ist ein pathlib.Path Objekt. Hier ist ein Beispiel für die Testnutzung

# content of test_tmp_path.py
CONTENT = "content"


def test_create_file(tmp_path):
    d = tmp_path / "sub"
    d.mkdir()
    p = d / "hello.txt"
    p.write_text(CONTENT, encoding="utf-8")
    assert p.read_text(encoding="utf-8") == CONTENT
    assert len(list(tmp_path.iterdir())) == 1
    assert 0

Wenn Sie dies ausführen, würde der Test erfolgreich sein, mit Ausnahme der letzten Zeile assert 0, die wir verwenden, um Werte zu betrachten

$ pytest test_tmp_path.py
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y
rootdir: /home/sweet/project
collected 1 item

test_tmp_path.py F                                                   [100%]

================================= FAILURES =================================
_____________________________ test_create_file _____________________________

tmp_path = PosixPath('PYTEST_TMPDIR/test_create_file0')

    def test_create_file(tmp_path):
        d = tmp_path / "sub"
        d.mkdir()
        p = d / "hello.txt"
        p.write_text(CONTENT, encoding="utf-8")
        assert p.read_text(encoding="utf-8") == CONTENT
        assert len(list(tmp_path.iterdir())) == 1
>       assert 0
E       assert 0

test_tmp_path.py:11: AssertionError
========================= short test summary info ==========================
FAILED test_tmp_path.py::test_create_file - assert 0
============================ 1 failed in 0.12s =============================

Standardmäßig behält pytest das temporäre Verzeichnis für die letzten 3 pytest Aufrufe bei. Gleichzeitige Aufrufe derselben Testfunktion werden durch Konfiguration des Basis-Temporärverzeichnisses, das für jeden gleichzeitigen Lauf eindeutig ist, unterstützt. Weitere Informationen finden Sie unter Temporäres Verzeichnisstandort und -aufbewahrung.

Das tmp_path_factory Fixture

Das tmp_path_factory ist ein Session-Scope Fixture, das verwendet werden kann, um beliebige temporäre Verzeichnisse aus jedem anderen Fixture oder Test zu erstellen.

Angenommen, Ihre Testsuite benötigt ein großes Bild auf der Festplatte, das prozedural generiert wird. Anstatt dasselbe Bild für jeden Test, der es verwendet, in sein eigenes tmp_path berechnet wird, können Sie es einmal pro Sitzung generieren, um Zeit zu sparen.

# contents of conftest.py
import pytest


@pytest.fixture(scope="session")
def image_file(tmp_path_factory):
    img = compute_expensive_image()
    fn = tmp_path_factory.mktemp("data") / "img.png"
    img.save(fn)
    return fn


# contents of test_image.py
def test_histogram(image_file):
    img = load_image(image_file)
    # compute and test histogram

Weitere Informationen finden Sie in der tmp_path_factory API.

Die tmpdir und tmpdir_factory Fixtures

Die tmpdir und tmpdir_factory Fixtures sind ähnlich wie tmp_path und tmp_path_factory, verwenden jedoch/geben Legacy py.path.local Objekte anstelle von Standard pathlib.Path Objekten zurück.

Hinweis

Heutzutage ist es vorzuziehen, tmp_path und tmp_path_factory zu verwenden.

Um alte Codebasen zu modernisieren, kann man pytest mit deaktiviertem legacypath-Plugin ausführen.

pytest -p no:legacypath

Dadurch werden Fehler bei Tests mit Legacy-Pfaden ausgelöst. Dies kann auch dauerhaft als Teil des addopts Parameters in der Konfigurationsdatei festgelegt werden.

Weitere Informationen finden Sie in der tmpdir tmpdir_factory API.

Temporäres Verzeichnisstandort und -aufbewahrung

Die temporären Verzeichnisse, wie sie von den tmp_path und (jetzt veralteten) tmpdir Fixtures zurückgegeben werden, werden automatisch unter einem Basis-Temporärverzeichnis erstellt, in einer Struktur, die von der Option --basetemp abhängt.

  • Standardmäßig (wenn die Option --basetemp nicht gesetzt ist) folgen die temporären Verzeichnisse dieser Vorlage.

    {temproot}/pytest-of-{user}/pytest-{num}/{testname}/
    

    wobei

    • {temproot} das System-Temporärverzeichnis ist, wie von tempfile.gettempdir() bestimmt. Es kann durch die Umgebungsvariable PYTEST_DEBUG_TEMPROOT überschrieben werden.

    • {user} der Benutzername ist, der die Tests ausführt,

    • {num} eine Zahl ist, die mit jedem Testlauf inkrementiert wird.

    • {testname} eine bereinigte Version des Namens des aktuellen Tests ist.

    Der automatisch inkrementierende Platzhalter {num} bietet eine grundlegende Aufbewahrungsfunktion und vermeidet, dass bestehende Ergebnisse früherer Testläufe blind entfernt werden. Standardmäßig werden die letzten 3 temporären Verzeichnisse aufbewahrt, dieses Verhalten kann jedoch mit tmp_path_retention_count und tmp_path_retention_policy konfiguriert werden.

  • Wenn die Option --basetemp verwendet wird (z. B. pytest --basetemp=mydir), wird diese direkt als Basis-Temporärverzeichnis verwendet.

    {basetemp}/{testname}/
    

    Beachten Sie, dass in diesem Fall keine Aufbewahrungsfunktion vorhanden ist: Es werden nur die Ergebnisse des letzten Laufs beibehalten.

    Warnung

    Das an --basetemp übergebene Verzeichnis wird vor jedem Testlauf blind geleert. Stellen Sie daher sicher, dass Sie ein Verzeichnis nur für diesen Zweck verwenden.

Wenn Tests auf der lokalen Maschine mit pytest-xdist verteilt werden, wird darauf geachtet, automatisch ein basetemp Verzeichnis für die Unterprozesse zu konfigurieren, so dass alle temporären Daten unter einem einzigen temporären Verzeichnis pro Testlauf liegen.