Was ist in pytest die Verwendung von conftest.py-Dateien?

216

Ich habe vor kurzem entdeckt pytest. Es scheint großartig. Ich bin jedoch der Meinung, dass die Dokumentation besser sein könnte.

Ich versuche zu verstehen, wofür conftest.pyDateien verwendet werden sollen.

In meiner (derzeit kleinen) Testsuite habe ich eine conftest.pyDatei im Projektstamm. Ich benutze es, um die Fixtures zu definieren, die ich in meine Tests injiziere.

Ich habe zwei Fragen:

  1. Ist das die richtige Verwendung von conftest.py? Hat es andere Verwendungszwecke?
  2. Kann ich mehr als eine conftest.pyDatei haben? Wann würde ich das machen wollen? Beispiele werden geschätzt.

Wie würden Sie allgemein den Zweck und die korrekte Verwendung von conftest.pyDateien in einer py.test-Testsuite definieren?

Aviv Cohn
quelle
8
Sie hatten mich beiIt seems great. However, I feel the documentation could be better.
user9074332
6
Ja, die Dokumentation könnte so viel besser sein. Ich habe die gesamte pytest-Dokumentation durchsucht, conftest.pyund obwohl es viele Verweise darauf gibt, dieses oder jenes Ding mit einer Conftest-Datei zu machen, gibt es nirgends in der Dokumentation jemals einen Hinweis darauf, dass beim Testen von pytest alle conftest.py-Dateien gefunden wurden (innerhalb der Die Verzeichnisstruktur, über die die Testerkennung durchgeführt wird, wird während der Testsammlungsphase ausgeführt (bevor Tests ausgeführt werden). Musste das selbst durch Experimentieren herausfinden.
Daniel Goldfarb

Antworten:

287

Ist dies die richtige Verwendung von conftest.py?

Ja, so ist es. Vorrichtungen sind eine mögliche und übliche Verwendung von conftest.py. Die von Ihnen definierten Geräte werden von allen Tests in Ihrer Testsuite gemeinsam genutzt. Das Definieren von Fixtures in der Wurzel conftest.pykann jedoch nutzlos sein und das Testen verlangsamen, wenn solche Fixtures nicht von allen Tests verwendet werden.

Hat es andere Verwendungszwecke?

Ja tut es.

  • Befestigungen : Definieren Vorrichtungen für statische Daten von Tests verwendet. Auf diese Daten können alle Tests in der Suite zugreifen, sofern nicht anders angegeben. Dies können sowohl Daten als auch Helfer von Modulen sein, die an alle Tests übergeben werden.

  • Externes Laden von Plugins : conftest.pyDient zum Importieren externer Plugins oder Module. Durch Definieren der folgenden globalen Variablen lädt pytest das Modul und stellt es für seinen Test zur Verfügung. Plugins sind im Allgemeinen Dateien, die in Ihrem Projekt oder anderen Modulen definiert sind und möglicherweise in Ihren Tests benötigt werden. Sie können auch eine Reihe vordefinierter Plugins laden, wie hier erläutert .

    pytest_plugins = "someapp.someplugin"

  • Hooks : Sie können Hooks wie Setup- und Teardown-Methoden und vieles mehr angeben, um Ihre Tests zu verbessern. Eine Reihe verfügbarer Haken finden Sie hier . Beispiel:

    def pytest_runtest_setup(item):
         """ called before ``pytest_runtest_call(item). """
         #do some stuff`
    
  • Root-Pfad testen : Dies ist eine versteckte Funktion. Wenn Sie conftest.pyin Ihrem Stammpfad definieren , pytesterkennen Sie Ihre Anwendungsmodule ohne Angabe PYTHONPATH. Im Hintergrund ändert py.test Ihre, sys.pathindem alle Submodule eingeschlossen werden , die im Stammpfad gefunden werden.

Kann ich mehr als eine conftest.py-Datei haben?

Ja, das können Sie und es wird dringend empfohlen, wenn Ihre Teststruktur etwas komplex ist. conftest.pyDateien haben Verzeichnisbereich. Daher ist es eine gute Praxis, gezielte Geräte und Helfer zu erstellen.

Wann würde ich das machen wollen? Beispiele werden geschätzt.

Mehrere Fälle könnten passen:

Erstellen einer Reihe von Tools oder Hooks für eine bestimmte Gruppe von Tests.

root / mod / conftest.py

def pytest_runtest_setup(item):
    print("I am mod")
    #do some stuff


test root/mod2/test.py will NOT produce "I am mod"

Laden einer Reihe von Vorrichtungen für einige Tests, für andere jedoch nicht.

root / mod / conftest.py

@pytest.fixture()
def fixture():
    return "some stuff"

root / mod2 / conftest.py

@pytest.fixture()
def fixture():
    return "some other stuff"

root / mod2 / test.py.

def test(fixture):
    print(fixture)

Druckt "einige andere Sachen".

Überschreiben von Hooks, die von der Wurzel geerbt wurden conftest.py.

root / mod / conftest.py

def pytest_runtest_setup(item):
    print("I am mod")
    #do some stuff

root / conftest.py

def pytest_runtest_setup(item):
    print("I am root")
    #do some stuff

Wenn Sie einen Test ausführen root/mod, wird nur "I am mod" gedruckt.

Sie können mehr über lesen conftest.py hier .

BEARBEITEN:

Was ist, wenn ich einfache Hilfsfunktionen benötige, die aus einer Reihe von Tests in verschiedenen Modulen aufgerufen werden können? Werden sie mir zur Verfügung stehen, wenn ich sie in eine conftest.py stelle? Oder sollte ich sie einfach in ein helpers.py-Modul einfügen und in meine Testmodule importieren und verwenden?

Sie können verwenden conftest.py, um Ihre Helfer zu definieren. Sie sollten jedoch die gängige Praxis befolgen. Helfer können zumindest in als Vorrichtungen verwendet werden pytest. Zum Beispiel habe ich in meinen Tests einen nachgebildeten Redis-Helfer, den ich auf diese Weise in meine Tests einspritze.

root / helper / redis / redis.py

@pytest.fixture
def mock_redis():
    return MockRedis()

root / tests / stuff / conftest.py

pytest_plugin="helper.redis.redis"

root / tests / stuff / test.py.

def test(mock_redis):
    print(mock_redis.get('stuff'))

Dies ist ein Testmodul, das Sie frei in Ihre Tests importieren können. HINWEIS, dass Sie möglicherweise so benennen könnten, redis.pyals conftest.pyob Ihr Modul redismehr Tests enthält. Von dieser Praxis wird jedoch aufgrund von Mehrdeutigkeiten abgeraten.

Wenn Sie verwenden möchten conftest.py, können Sie diesen Helfer einfach in Ihre Wurzel conftest.pyeinfügen und ihn bei Bedarf injizieren.

root / tests / conftest.py

@pytest.fixture
def mock_redis():
    return MockRedis()

root / tests / stuff / test.py.

def test(mock_redis):
    print(mock_redis.get(stuff))

Sie können auch ein installierbares Plugin schreiben. In diesem Fall kann Ihr Helfer überall geschrieben werden, er muss jedoch einen Einstiegspunkt definieren, der in Ihrem und anderen potenziellen Testframeworks installiert werden soll. Sehen Sie das .

Wenn Sie keine Fixtures verwenden möchten, können Sie natürlich einen einfachen Helfer definieren und einfach den alten Import verwenden, wo immer er benötigt wird.

root / tests / helper / redis.py

class MockRedis():
    # stuff

root / tests / stuff / test.py.

from helper.redis import MockRedis

def test():
    print(MockRedis().get(stuff))

Hier können jedoch Probleme mit dem Pfad auftreten, da sich das Modul nicht in einem untergeordneten Ordner des Tests befindet. Sie sollten in der Lage sein, dies zu überwinden (nicht getestet), indem Sie __init__.pyIhrem Helfer ein hinzufügen

root / tests / helper / __ init__.py

from .redis import MockRedis

Oder fügen Sie einfach das Hilfsmodul zu Ihrem hinzu PYTHONPATH.

Simone Zandara
quelle
Ich stoße auf eine Situation, in der mein erstes Unit-Test-Modul test_aaaaa.pytatsächlich versucht, ausgeführt zu werden, bevor das Setup des Geräts abgeschlossen ist conftest.py. Irgendwelche Gedanken darüber, warum dies auftreten kann?
user9074332
Ohne conftest.py wird Ihr Teststammpfad nicht zum sys.path hinzugefügt, und es werden Fehler wie "ModuleNotFoundError: Kein Modul mit dem Namen 'foobar'" angezeigt.
Cale Sweeney
10

Im weitesten Sinne ist conftest.py ein lokales Plugin pro Verzeichnis. Hier definieren Sie verzeichnisspezifische Hooks und Fixtures. In meinem Fall haben Sie ein Stammverzeichnis mit projektspezifischen Testverzeichnissen. Einige gängige Magie ist in 'root' conftest.py stationiert. Projektspezifisch - in ihren eigenen. Ich kann beim Speichern von Fixtures in conftest.py nichts Schlechtes sehen, es sei denn, sie werden nicht häufig verwendet (in diesem Fall definiere ich sie lieber direkt in Testdateien).

Wütende Ente
quelle
10

Ich verwende die conftest.pyDatei, um die Fixtures zu definieren, die ich in meine Tests einspeise. Ist dies die richtige Verwendung von conftest.py?

Ja , ein Gerät wird normalerweise verwendet, um Daten für mehrere Tests vorzubereiten.

Hat es andere Verwendungszwecke?

Ja , ein Gerät ist eine Funktion, die pytestvor und manchmal nach den eigentlichen Testfunktionen ausgeführt wird. Der Code im Gerät kann alles tun, was Sie wollen. Beispielsweise kann ein Gerät verwendet werden, um einen Datensatz für die zu bearbeitenden Tests abzurufen, oder ein Gerät kann auch verwendet werden, um ein System in einen bekannten Zustand zu versetzen, bevor ein Test ausgeführt wird.

Kann ich mehr als eine conftest.pyDatei haben? Wann würde ich das machen wollen?

Erstens ist es möglich, Geräte in einzelne Testdateien zu legen. Um Geräte jedoch für mehrere Testdateien freizugeben, müssen Sie conftest.pyfür alle Tests eine Datei verwenden, die sich an einem zentralen Ort befindet. Geräte können von jedem Test gemeinsam genutzt werden. Sie können in einzelne Testdateien eingefügt werden, wenn das Gerät nur von Tests in dieser Datei verwendet werden soll.

Zweitens, ja , können Sie andere haben conftest.pyDateien in Unterverzeichnissen des Top-Tests Verzeichnisses. In conftest.pydiesem Fall stehen in diesen untergeordneten Dateien definierte Fixtures für Tests in diesem Verzeichnis und in diesen Unterverzeichnissen zur Verfügung.

Wenn Sie Fixtures in die conftest.pyDatei am Teststamm einfügen, werden sie in allen Testdateien verfügbar.

lmiguelvargasf
quelle