Abkündigungen und Entfernungen¶
Diese Seite listet alle pytest-Funktionen auf, die derzeit abgekündigt sind oder in früheren Hauptversionen entfernt wurden. Ziel ist es, den Benutzern eine klare Begründung dafür zu geben, warum eine bestimmte Funktion entfernt wurde und welche Alternativen stattdessen verwendet werden sollten.
Abgekündigte Funktionen¶
Nachfolgend finden Sie eine vollständige Liste aller pytest-Funktionen, die als abgekündigt gelten. Die Verwendung dieser Funktionen löst eine PytestWarning oder Unterklassen aus, die mit Standard-Warnungsfiltern gefiltert werden können.
monkeypatch.syspath_prepend mit Legacy-Namespace-Paketen¶
Seit Version 9.0 abgekündigt.
Wenn monkeypatch.syspath_prepend() verwendet wird, ruft pytest automatisch pkg_resources.fixup_namespace_packages() auf, wenn pkg_resources importiert wird. Dies ist nur für Legacy-Namespace-Pakete erforderlich, die pkg_resources.declare_namespace() verwenden.
Legacy-Namespace-Pakete werden zugunsten nativer Namespace-Pakete (PEP 420) abgekündigt. Wenn Sie pkg_resources.declare_namespace() in Ihren __init__.py-Dateien verwenden, sollten Sie zu nativen Namespace-Paketen migrieren, indem Sie die __init__.py-Dateien aus Ihren Namespace-Paketen entfernen.
Diese Abkündigungswarnung wird nur ausgegeben, wenn
pkg_resourcesimportiert wird, undDer spezifische Pfad, der vorangestellt wird, enthält ein deklariertes Namespace-Paket (über
pkg_resources.declare_namespace())
Um diese Warnung zu beheben, konvertieren Sie Ihre Legacy-Namespace-Pakete in native Namespace-Pakete
Legacy-Namespace-Paket (abgekündigt)
# mypkg/__init__.py
__import__("pkg_resources").declare_namespace(__name__)
Natives Namespace-Paket (empfohlen)
Entfernen Sie einfach die __init__.py-Datei vollständig. Python 3.3+ unterstützt native Namespace-Pakete ohne __init__.py.
Synchrone Tests, die von asynchronen Fixtures abhängen¶
Seit Version 8.4 abgekündigt.
Pytest hat lange Zeit einen Fehler ausgegeben, wenn eine asynchrone Testfunktion angetroffen wurde, und den Benutzer aufgefordert, ein Plugin zu installieren, das damit umgehen kann. Es wurden keine Fehler ausgegeben, wenn eine asynchrone Fixture von einem synchronen Test abhängte. Wenn die Fixture eine asynchrone Funktion war, wurde eine Warnung "unawaitede coroutine" ausgegeben, aber für asynchrone Yield-Fixtures gab es nicht einmal das. Dies ist ein Problem, selbst wenn ein Plugin zur Handhabung asynchroner Tests installiert ist, da diese möglicherweise spezielle Dekoratoren für asynchrone Fixtures benötigen, um behandelt zu werden, und einige möglicherweise nicht robust damit umgehen können, wenn ein Benutzer versehentlich eine asynchrone Fixture von seinen synchronen Tests anfordert. Die Zwischenspeicherung von Fixture-Werten kann dies noch unintuitiver machen, wo alles "funktionieren" wird, wenn die Fixture zuerst von einem asynchronen Test angefordert und dann von einem synchronen Test angefordert wird.
Leider gibt es keine 100% zuverlässige Methode, um zu identifizieren, wann ein Benutzer einen Fehler gemacht hat, im Gegensatz zu Situationen, in denen er ein nicht erwartetes Objekt von seiner Fixture erwartet, mit dem er selbst umgehen wird. Um diese Warnung zu unterdrücken, wenn Sie sie tatsächlich beabsichtigen, können Sie Ihre asynchrone Fixture in eine synchrone Fixture einpacken
import asyncio
import pytest
@pytest.fixture
async def unawaited_fixture():
return 1
def test_foo(unawaited_fixture):
assert 1 == asyncio.run(unawaited_fixture)
sollte geändert werden in
import asyncio
import pytest
@pytest.fixture
def unawaited_fixture():
async def inner_fixture():
return 1
return inner_fixture()
def test_foo(unawaited_fixture):
assert 1 == asyncio.run(unawaited_fixture)
Sie können auch pytest_fixture_setup verwenden, um die Coroutine/den Async-Generator zu handhaben, bevor pytest sie sieht - dies ist der Weg, den aktuelle asynchrone pytest-Plugins einschlagen.
Wenn ein Benutzer eine asynchrone Fixture mit autouse=True in seiner conftest.py hat oder in einer Datei, die sowohl synchrone Tests als auch die Fixture enthält, erhält er diese Warnung. Sofern Sie kein Plugin verwenden, das asynchrone Fixtures mit synchronen Tests speziell behandelt, raten wir dringend von dieser Praxis ab. Sie kann zu unvorhersehbarem Verhalten führen (bei größeren Geltungsbereichen scheint es "zu funktionieren", wenn ein asynchroner Test die Fixture zuerst anfordert, aufgrund von Wert-Caching) und generiert Laufzeitwarnungen für nicht erwartete Coroutinen (aber nur für Nicht-Yield-Fixtures). Darüber hinaus schafft sie Mehrdeutigkeit für andere Entwickler darüber, ob die Fixture dazu bestimmt ist, Setup für synchrone Tests durchzuführen.
Das anyio pytest plugin unterstützt synchrone Tests mit asynchronen Fixtures, unterliegt jedoch bestimmten Einschränkungen.
pytest.importorskip Standardverhalten bezüglich ImportError¶
Seit Version 8.2 abgekündigt.
Traditionell erfasst pytest.importorskip() ImportError, mit der ursprünglichen Absicht, Tests zu überspringen, bei denen ein abhängiges Modul nicht installiert ist, z. B. Tests mit unterschiedlichen Abhängigkeiten.
Einige Pakete können jedoch im System installiert sein, aber aufgrund eines anderen Problems nicht importiert werden, z. B. ein Kompilierungsfehler oder eine fehlerhafte Installation. In diesen Fällen würde pytest.importorskip() den Test weiterhin stillschweigend überspringen, aber meistens möchten Benutzer den unerwarteten Fehler sehen, damit das zugrunde liegende Problem behoben werden kann.
In 8.2 wurde der Parameter exc_type hinzugefügt, der Benutzern die Möglichkeit gibt, ModuleNotFoundError zu übergeben, um Tests nur zu überspringen, wenn das Modul wirklich nicht gefunden werden kann und nicht aufgrund eines anderen Fehlers.
Das Standardverhalten, nur ModuleNotFoundError zu erfassen (und andere Fehler weiterzugeben), wäre die beste Lösung. Aus Gründen der Abwärtskompatibilität behält pytest jedoch das bestehende Verhalten bei, gibt jedoch eine Warnung aus, wenn
Die erfasste Ausnahme ist vom Typ
ImportError, undDer Benutzer übergibt
exc_typenicht explizit.
Wenn der Importversuch ModuleNotFoundError (der übliche Fall) auslöst, wird das Modul übersprungen und es wird keine Warnung ausgegeben.
Auf diese Weise funktionieren die üblichen Fälle weiterhin wie bisher, während unerwartete Fehler nun eine Warnung ausgeben. Benutzer können die Warnung unterdrücken, indem sie explizit exc_type=ImportError übergeben.
In 9.0 wird die Warnung zu einem Fehler, und in 9.1 erfasst pytest.importorskip() standardmäßig nur noch ModuleNotFoundError und es werden keine Warnungen mehr ausgegeben. Benutzer können ImportError jedoch weiterhin erfassen, indem sie es an exc_type übergeben.
Das Argument fspath für Node-Konstruktoren wurde durch pathlib.Path ersetzt¶
Seit Version 7.0 abgekündigt.
Um die Umstellung von py.path.local auf pathlib zu unterstützen, ist das Argument fspath für Node-Konstruktoren wie pytest.Function.from_parent() und pytest.Class.from_parent() nun abgekündigt.
Plugins, die Nodes konstruieren, sollten stattdessen das Argument path vom Typ pathlib.Path übergeben.
Plugins, die benutzerdefinierte Items und Sammler implementieren, werden ermutigt, fspath-Parameter (py.path.local) durch path-Parameter (pathlib.Path) zu ersetzen und jegliche andere Verwendung der py-Bibliothek, wenn möglich, fallen zu lassen.
Wenn möglich, sollten Plugins mit benutzerdefinierten Items kooperative Konstruktoren verwenden, um Argumente nicht hart zu kodieren, die sie nur an die Superklasse weitergeben.
Hinweis
Der Name der Node-Argumente und -Attribute (das neue Attribut ist path) ist **das Gegenteil** der Situation für Hooks, wie unten beschrieben (das alte Argument ist path).
Dies ist ein unglückliches Artefakt aus historischen Gründen, das in zukünftigen Versionen behoben werden sollte, da wir die Abhängigkeit von py langsam abschaffen (siehe #9283 für eine längere Diskussion).
Aufgrund der laufenden Migration von Methoden wie reportinfo(), die immer noch ein py.path.local-Objekt zurückgeben soll, haben Nodes immer noch sowohl fspath (py.path.local) als auch path (pathlib.Path) Attribute, unabhängig davon, welches Argument im Konstruktor verwendet wurde. Wir erwarten, dass das Attribut fspath in einer zukünftigen Version abgekündigt wird.
Konfiguration von Hook-Specs/Impls mit Markern¶
Bevor pluggy, die Plugin-Bibliothek von pytest, ein eigenes Paket mit einer klaren API war, verwendete pytest einfach pytest.mark zur Konfiguration von Hooks.
Die Dekoratoren pytest.hookimpl() und pytest.hookspec() sind seit Jahren verfügbar und sollten stattdessen verwendet werden.
@pytest.mark.tryfirst
def pytest_runtest_call(): ...
# or
def pytest_runtest_call(): ...
pytest_runtest_call.tryfirst = True
sollte geändert werden in
@pytest.hookimpl(tryfirst=True)
def pytest_runtest_call(): ...
Geänderte hookimpl-Attribute
tryfirsttrylastoptionalhookhookwrapper
Geänderte hookwrapper-Attribute
firstresulthistoric
Argumente für Hooks py.path.local wurden durch pathlib.Path ersetzt¶
Seit Version 7.0 abgekündigt.
Um die Umstellung von py.path.local auf pathlib zu unterstützen, erhalten die folgenden Hooks nun zusätzliche Argumente
pytest_ignore_collect(collection_path: pathlib.Path)als Äquivalent zupathpytest_collect_file(file_path: pathlib.Path)als Äquivalent zupathpytest_pycollect_makemodule(module_path: pathlib.Path)als Äquivalent zupathpytest_report_header(start_path: pathlib.Path)als Äquivalent zustartdirpytest_report_collectionfinish(start_path: pathlib.Path)als Äquivalent zustartdir
Die begleitenden py.path.local-basierten Pfade sind abgekündigt: Plugins, die diese Hooks manuell aufrufen, sollten nur die neuen pathlib.Path-Argumente übergeben, und Benutzer sollten ihre Hook-Implementierungen ändern, um die neuen pathlib.Path-Argumente zu verwenden.
Hinweis
Der Name der Node-Argumente und -Attribute, wie oben beschrieben (das neue Attribut ist path), ist **das Gegenteil** der Situation für Hooks (das alte Argument ist path).
Dies ist ein unglückliches Artefakt aus historischen Gründen, das in zukünftigen Versionen behoben werden sollte, da wir die Abhängigkeit von py langsam abschaffen (siehe #9283 für eine längere Diskussion).
Direktes Konstruieren interner Klassen¶
Seit Version 7.0 abgekündigt.
Das direkte Konstruieren der folgenden Klassen ist nun abgekündigt
_pytest.mark.structures.Mark_pytest.mark.structures.MarkDecorator_pytest.mark.structures.MarkGenerator_pytest.python.Metafunc_pytest.runner.CallInfo_pytest._code.ExceptionInfo_pytest.config.argparsing.Parser_pytest.config.argparsing.OptionGroup_pytest.pytester.HookRecorder
Diese Konstruktoren galten schon immer als privat, aber nun wird eine Abkündigungswarnung ausgegeben, die in pytest 8 zu einem harten Fehler werden könnte.
Diamant-Vererbung zwischen pytest.Collector und pytest.Item¶
Seit Version 7.0 abgekündigt.
Das Definieren eines benutzerdefinierten pytest-Knotentyps, der sowohl ein Item als auch ein Collector ist (z.B. File), gibt nun eine Warnung aus. Es wurde nie sinnvoll unterstützt und führt zu schwer zu debuggenden Fehlern.
Einige Plugins, die Linting/Code-Analyse bereitstellen, haben dies als Hack genutzt. Stattdessen sollte ein separater Collector-Knoten verwendet werden, der das Item sammelt. Siehe Arbeiten mit Nicht-Python-Tests für ein Beispiel, sowie ein Beispiel-PR zur Behebung der Vererbung.
Konstruktoren benutzerdefinierter Node-Unterklassen sollten **kwargs übernehmen¶
Seit Version 7.0 abgekündigt.
Wenn benutzerdefinierte Unterklassen von Nodes wie pytest.Item die __init__-Methode überschreiben, sollten sie **kwargs übernehmen. Somit,
class CustomItem(pytest.Item):
def __init__(self, name, parent, additional_arg):
super().__init__(name, parent)
self.additional_arg = additional_arg
sollte geändert werden in
class CustomItem(pytest.Item):
def __init__(self, *, additional_arg, **kwargs):
super().__init__(**kwargs)
self.additional_arg = additional_arg
um das Hartkodieren von Argumenten zu vermeiden, die pytest an die Superklasse übergeben kann. Siehe Arbeiten mit Nicht-Python-Tests für ein vollständiges Beispiel.
In Fällen ohne Konflikte wird keine Abkündigungswarnung ausgegeben. In Fällen mit Konflikten (wie z. B. dass pytest.File nun path anstelle von fspath annimmt, wie oben beschrieben) wird nun eine Abkündigungswarnung ausgegeben.
Anwenden eines Markers auf eine Fixture-Funktion¶
Seit Version 7.4 abgekündigt.
Das Anwenden eines Markers auf eine Fixture-Funktion hatte nie eine Wirkung, ist aber ein häufiger Benutzerfehler.
@pytest.mark.usefixtures("clean_database")
@pytest.fixture
def user() -> User: ...
Benutzer erwarteten in diesem Fall, dass der usefixtures-Marker seine beabsichtigte Wirkung hätte, die clean_database-Fixture zu verwenden, wenn user aufgerufen wurde, tatsächlich hat er aber keinerlei Wirkung.
Nun wird pytest eine Warnung ausgeben, wenn es dieses Problem erkennt, und in zukünftigen Versionen einen Fehler auslösen.
Die Funktion/der Dekorator yield_fixture¶
Seit Version 6.2 abgekündigt.
pytest.yield_fixture ist ein abgekündigter Alias für pytest.fixture().
Dies ist schon sehr lange der Fall, so dass eine einfache Suche/Ersetzung sicher ist.
Entfernte Funktionen und Breaking Changes¶
Wie in unserer Richtlinie zur Abwärtskompatibilität dargelegt, werden abgekündigte Funktionen nur in Hauptversionen nach Ablauf einer angemessenen Abkündigungsfrist entfernt.
Einige Breaking Changes, die nicht abgekündigt werden konnten, sind ebenfalls aufgeführt.
yield-Tests¶
Entfernt in Version 4.0: yield-Tests xfail.
Entfernt in Version 8.4: yield-Tests lösen einen Sammlungsfehler aus.
Pytest unterstützt keine yield-Style-Tests mehr, bei denen eine Testfunktion tatsächlich Funktionen und Werte yieldet, die dann zu richtigen Testmethoden werden. Beispiel
def check(x, y):
assert x**x == y
def test_squared():
yield check, 2, 4
yield check, 3, 9
Dies würde zwei tatsächliche Testfunktionen erzeugen.
Diese Form der Testfunktion unterstützt Fixtures nicht richtig, und Benutzer sollten auf pytest.mark.parametrize umsteigen.
@pytest.mark.parametrize("x, y", [(2, 4), (3, 9)])
def test_squared(x, y):
assert x**x == y
Unterstützung für für nose geschriebene Tests¶
Seit Version 7.2 abgekündigt.
Entfernt in Version 8.0.
Die Unterstützung für das Ausführen von für nose geschriebenen Tests ist nun abgekündigt.
nose ist seit Jahren nur noch im Wartungsmodus, und die Pflege des Plugins ist nicht trivial, da es auf die Codebasis übergreift (siehe #9886 für weitere Details).
Setup/Teardown¶
Eine Sache, die Benutzer überraschen könnte, ist, dass einfache setup- und teardown-Methoden keine nativen pytest-Methoden sind, sie sind tatsächlich Teil der nose-Unterstützung.
class Test:
def setup(self):
self.resource = make_resource()
def teardown(self):
self.resource.close()
def test_foo(self): ...
def test_bar(self): ...
Native pytest-Unterstützung verwendet setup_method und teardown_method (siehe Methoden- und Funktions-Setup/Teardown), daher sollte das obige wie folgt geändert werden
class Test:
def setup_method(self):
self.resource = make_resource()
def teardown_method(self):
self.resource.close()
def test_foo(self): ...
def test_bar(self): ...
Dies ist in einer gesamten Codebasis durch eine einfache Suche und Ersetzung leicht zu bewerkstelligen.
@with_setup¶
Code, der @with_setup wie folgt verwendet
from nose.tools import with_setup
def setup_some_resource(): ...
def teardown_some_resource(): ...
@with_setup(setup_some_resource, teardown_some_resource)
def test_foo(): ...
wird ebenfalls in einen unterstützten pytest-Stil portiert werden müssen. Eine Möglichkeit, dies zu tun, ist die Verwendung einer Fixture
import pytest
def setup_some_resource(): ...
def teardown_some_resource(): ...
@pytest.fixture
def some_resource():
setup_some_resource()
yield
teardown_some_resource()
def test_foo(some_resource): ...
Das Attribut compat_co_firstlineno¶
Nose inspiziert dieses Attribut auf Funktions-Objekten, um die Überschreibung der abgeleiteten Zeilennummer der Funktion zu ermöglichen. Pytest respektiert dieses Attribut nicht mehr.
Übergabe von msg= an pytest.skip, pytest.fail oder pytest.exit¶
Seit Version 7.0 abgekündigt.
Entfernt in Version 8.0.
Die Übergabe des Schlüsselwortarguments msg an pytest.skip(), pytest.fail() oder pytest.exit() ist nun abgekündigt und stattdessen sollte reason verwendet werden. Diese Änderung dient der Konsistenz mit den Markern @pytest.mark.skip und @pytest.mark.xfail, die bereits ein reason-Argument akzeptieren.
def test_fail_example():
# old
pytest.fail(msg="foo")
# new
pytest.fail(reason="bar")
def test_skip_example():
# old
pytest.skip(msg="foo")
# new
pytest.skip(reason="bar")
def test_exit_example():
# old
pytest.exit(msg="foo")
# new
pytest.exit(reason="bar")
Der pytest.Instance Sammler¶
Entfernt in Version 7.0.
Der pytest.Instance Sammlertyp wurde entfernt.
Zuvor wurden Python-Testmethoden als Class -> Instance -> Function gesammelt. Nun sammelt Class die Testmethoden direkt.
Die meisten Plugins, die auf Instance verweisen, tun dies, um es zu ignorieren oder zu überspringen, und verwenden eine Prüfung wie if isinstance(node, Instance): return. Solche Plugins sollten einfach die Berücksichtigung von Instance ab pytest >= 7 entfernen. Um solche Verwendungen jedoch weiterhin zu ermöglichen, wurde ein Dummy-Typ in pytest.Instance und _pytest.python.Instance instanziiert, und dessen Import löst eine Abkündigungswarnung aus. Dies wurde in pytest 8 entfernt.
Verwendung von pytest.warns(None)¶
Seit Version 7.0 abgekündigt.
Entfernt in Version 8.0.
pytest.warns(None) ist nun abgekündigt, da es häufig missbraucht wurde. Seine korrekte Verwendung war die Prüfung, ob der Code mindestens eine Warnung eines beliebigen Typs ausgibt - wie pytest.warns() oder pytest.warns(Warning).
Siehe Zusätzliche Anwendungsfälle für Warnungen in Tests für Beispiele.
Rückwärtskompatibilitäten in Parser.addoption¶
Seit Version 2.4 abgekündigt.
Entfernt in Version 8.0.
Mehrere Verhaltensweisen von Parser.addoption werden in pytest 8 entfernt (abgekündigt seit pytest 2.4.0)
parser.addoption(..., help=".. %default ..")- verwenden Sie stattdessen%(default)s.parser.addoption(..., type="int/string/float/complex")- verwenden Sie stattdessentype=intusw.
Die Befehlszeilenoption --strict (wieder eingeführt)¶
Seit Version 6.2 abgekündigt.
Geändert in Version 9.0.
Die Befehlszeilenoption --strict wurde zugunsten von --strict-markers abgekündigt, die besser vermittelt, was die Option tut.
In Version 8.1 haben wir --strict versehentlich wieder eingeführt.
In Version 9.0 haben wir --strict so geändert, dass es die neue Konfigurationsoption strict setzt. Es aktiviert nun alle strengen Optionen (einschließlich strict_markers).
Implementierung des Hooks pytest_cmdline_preparse¶
Seit Version 7.0 abgekündigt.
Entfernt in Version 8.0.
Die Implementierung des Hooks pytest_cmdline_preparse wurde offiziell abgekündigt. Implementieren Sie stattdessen den Hook pytest_load_initial_conftests.
def pytest_cmdline_preparse(config: Config, args: List[str]) -> None: ...
# becomes:
def pytest_load_initial_conftests(
early_config: Config, parser: Parser, args: List[str]
) -> None: ...
Sammlungsänderungen in pytest 8¶
Ein neuer Basis-Sammlungsknoten pytest.Directory wurde hinzugefügt, von dem alle Sammlerknoten für Dateisystemverzeichnisse abstammen sollen. Dies ist analog zum bestehenden pytest.File für Dateiknoten.
Änderte pytest.Package in eine Unterklasse von pytest.Directory. Ein Package repräsentiert ein Dateisystemverzeichnis, das ein Python-Paket ist, d.h. eine __init__.py-Datei enthält.
pytest.Package sammelt nun nur noch Dateien in seinem eigenen Verzeichnis; zuvor sammelte es rekursiv. Unterverzeichnisse werden als untergeordnete Sammlerknoten gesammelt, wodurch ein Sammlungsbaum entsteht, der die Hierarchie des Dateisystems widerspiegelt.
session.name ist nun ""; zuvor war es der Verzeichnisname des Root-Verzeichnisses. Dies entspricht session.nodeid, welches schon immer "" war.
Hinzugefügt wurde ein neuer konkreter Sammlerknoten pytest.Dir, eine Unterklasse von pytest.Directory. Dieser Knoten repräsentiert ein Dateisystemverzeichnis, das kein pytest.Package ist, d.h. keine __init__.py-Datei enthält. Ähnlich wie bei Package sammelt er nur die Dateien in seinem eigenen Verzeichnis und sammelt Unterverzeichnisse als untergeordnete Sammlerknoten.
Dateien und Verzeichnisse werden nun gemeinsam in alphabetischer Reihenfolge gesammelt, es sei denn, dies wird durch ein Plugin geändert. Zuvor wurden Dateien vor Verzeichnissen gesammelt.
Der Sammlungsbaum enthält nun Verzeichnisse/Pakete bis zum Root-Verzeichnis, für anfängliche Argumente, die sich innerhalb des Root-Verzeichnisses befinden. Für Dateien außerhalb des Root-Verzeichnisses wird nur das unmittelbare Verzeichnis/Paket gesammelt – beachten Sie jedoch, dass das Sammeln von außerhalb des Root-Verzeichnisses nicht empfohlen wird.
Als Beispiel, gegeben die folgende Dateisystemstruktur
myroot/
pytest.ini
top/
├── aaa
│ └── test_aaa.py
├── test_a.py
├── test_b
│ ├── __init__.py
│ └── test_b.py
├── test_c.py
└── zzz
├── __init__.py
└── test_zzz.py
ist der Sammlungsbaum, wie er von pytest --collect-only top/ angezeigt wird, aber mit dem ansonsten ausgeblendeten Session-Knoten zur Klarheit hinzugefügt, nun der folgende
<Session>
<Dir myroot>
<Dir top>
<Dir aaa>
<Module test_aaa.py>
<Function test_it>
<Module test_a.py>
<Function test_it>
<Package test_b>
<Module test_b.py>
<Function test_it>
<Module test_c.py>
<Function test_it>
<Package zzz>
<Module test_zzz.py>
<Function test_it>
Zuvor war es
<Session>
<Module top/test_a.py>
<Function test_it>
<Module top/test_c.py>
<Function test_it>
<Module top/aaa/test_aaa.py>
<Function test_it>
<Package test_b>
<Module test_b.py>
<Function test_it>
<Package zzz>
<Module test_zzz.py>
<Function test_it>
Code/Plugins, die von einer bestimmten Struktur des Sammlungsbaums abhängen, müssen möglicherweise aktualisiert werden.
pytest.Package ist keine pytest.Module oder pytest.File mehr¶
Geändert in Version 8.0.
Der Sammlerknoten Package bezeichnet ein Python-Paket, d.h. ein Verzeichnis mit einer __init__.py-Datei. Zuvor war Package eine Unterklasse von pytest.Module (das ein einzelnes Python-Modul repräsentiert), wobei das Modul die __init__.py-Datei war. Dies wurde als Designfehler angesehen (siehe #11137 und #7777 für Details).
Die path-Eigenschaft von Package-Knoten zeigt nun auf das Paketverzeichnis anstelle der __init__.py-Datei.
Beachten Sie, dass ein Module-Knoten für __init__.py (das kein Package ist) weiterhin existieren kann, wenn es während der Sammlung erfasst wird (z. B. wenn Sie python_files so konfiguriert haben, dass __init__.py-Dateien eingeschlossen werden).
Das Sammeln von __init__.py-Dateien sammelt nun keine Pakete mehr¶
Entfernt in Version 8.0.
Das Ausführen von pytest pkg/__init__.py sammelt nun nur die Datei (Modul) pkg/__init__.py. Zuvor sammelte es das gesamte pkg-Paket, einschließlich anderer Testdateien im Verzeichnis, aber ohne Tests in der __init__.py-Datei selbst (es sei denn, python_files wurde geändert, um __init__.py-Dateien zuzulassen).
Um das gesamte Paket zu sammeln, geben Sie nur das Verzeichnis an: pytest pkg.
Das Modul pytest.collect¶
Seit Version 6.0 veraltet.
Entfernt in Version 7.0.
Das Modul pytest.collect ist kein Teil der öffentlichen API mehr, alle seine Namen sollten nun direkt aus pytest importiert werden.
Der Hook pytest_warning_captured¶
Seit Version 6.0 veraltet.
Entfernt in Version 7.0.
Dieser Hook hat einen Parameter item, der von pytest-xdist nicht serialisiert werden kann.
Verwenden Sie stattdessen den Hook pytest_warning_recorded, der den Parameter item durch einen Parameter nodeid ersetzt.
Die Funktion pytest._fillfuncargs¶
Seit Version 6.0 veraltet.
Entfernt in Version 7.0.
Diese Funktion wurde zur Abwärtskompatibilität mit einem älteren Plugin beibehalten.
Ihre Funktionalität ist nicht zur direkten Verwendung gedacht, aber wenn Sie sie ersetzen müssen, verwenden Sie stattdessen function._request._fillfixtures(), beachten Sie jedoch, dass dies keine öffentliche API ist und sich in Zukunft ändern kann.
Kommandozeilenoption --no-print-logs¶
Seit Version 5.4 veraltet.
Entfernt in Version 6.0.
Die Option --no-print-logs und die Ini-Einstellung log_print werden entfernt. Wenn Sie sie verwendet haben, verwenden Sie stattdessen --show-capture.
Eine Kommandozeilenoption --show-capture wurde in pytest 3.5.0 hinzugefügt, die angibt, wie die erfasste Ausgabe bei fehlgeschlagenen Tests angezeigt werden soll: no, stdout, stderr, log oder all (Standard).
Ergebnisprotokoll (--result-log)¶
Seit Version 4.0 veraltet.
Entfernt in Version 6.0.
Die Option --result-log erzeugt einen Strom von Testberichten, der zur Laufzeit analysiert werden kann, verwendet jedoch ein benutzerdefiniertes Format, das von den Benutzern die Implementierung eines eigenen Parsers erfordert.
Das Plugin pytest-reportlog bietet eine Option --report-log, eine standardmäßigere und erweiterbare Alternative, die ein JSON-Objekt pro Zeile erzeugt und die gleichen Anwendungsfälle abdecken sollte. Bitte probieren Sie es aus und geben Sie Feedback.
Das Plugin pytest-reportlog wird möglicherweise irgendwann in den Kern integriert, abhängig von den Plänen für die Plugins und der Anzahl der Benutzer, die es verwenden.
Hook pytest_collect_directory¶
Entfernt in Version 6.0.
Der Hook pytest_collect_directory funktioniert seit Jahren nicht mehr richtig (er wurde aufgerufen, aber die Ergebnisse wurden ignoriert). Benutzer können stattdessen pytest_collection_modifyitems verwenden.
TerminalReporter.writer¶
Entfernt in Version 6.0.
Das Attribut TerminalReporter.writer wurde als veraltet markiert und sollte nicht mehr verwendet werden. Dies wurde versehentlich als Teil der öffentlichen API dieses Plugins offengelegt und bindet es zu stark an py.io.TerminalWriter.
Plugins, die TerminalReporter.writer direkt verwendet haben, sollten stattdessen Methoden von TerminalReporter verwenden, die die gleiche Funktionalität bieten.
Änderung des Standardwerts für junit_family zu „xunit2“¶
Geändert in Version 6.0.
Der Standardwert der Option junit_family ändert sich in pytest 6.0 zu xunit2, was eine Aktualisierung des alten xunit1-Formats ist und von modernen Tools, die diese Art von Datei manipulieren (z. B. Jenkins, Azure Pipelines usw.), standardmäßig unterstützt wird.
Benutzer werden empfohlen, das neue xunit2-Format auszuprobieren und zu sehen, ob ihr Tooling, das die JUnit XML-Datei verarbeitet, es unterstützt.
Um das neue Format zu verwenden, aktualisieren Sie Ihre Konfigurationsdatei
[pytest]
junit_family = "xunit2"
[pytest]
junit_family = xunit2
Wenn Sie feststellen, dass Ihr Tooling das neue Format nicht unterstützt und Sie die Legacy-Version weiterhin verwenden möchten, setzen Sie die Option stattdessen auf legacy
[pytest]
junit_family = "legacy"
[pytest]
junit_family = legacy
Durch die Verwendung von legacy verwenden Sie beim Upgrade auf pytest 6.0 weiterhin das Legacy-/xunit1-Format, wobei das Standardformat xunit2 sein wird.
Um Benutzer über den Übergang zu informieren, gibt pytest eine Warnung aus, falls die Option --junit-xml auf der Kommandozeile angegeben wird, junit_family aber nicht explizit in pytest.ini konfiguriert ist.
Dienste, die bekanntermaßen das xunit2-Format unterstützen
Knotenkonstruktion geändert zu Node.from_parent¶
Geändert in Version 6.0.
Die Konstruktion von Knoten sollte nun den benannten Konstruktor from_parent verwenden. Diese Einschränkung der API-Oberfläche soll eine bessere/einfachere Refaktorierung des Sammlungsbaums ermöglichen.
Das bedeutet, dass anstelle von MyItem(name="foo", parent=collector, obj=42) nun MyItem.from_parent(collector, name="foo") aufgerufen werden muss.
Plugins, die ältere Versionen von pytest unterstützen und die Warnung unterdrücken möchten, können hasattr verwenden, um zu prüfen, ob from_parent in dieser Version vorhanden ist.
def pytest_pycollect_makeitem(collector, name, obj):
if hasattr(MyItem, "from_parent"):
item = MyItem.from_parent(collector, name="foo")
item.obj = 42
return item
else:
return MyItem(name="foo", parent=collector, obj=42)
Beachten Sie, dass from_parent nur mit Schlüsselwortargumenten für die Parameter aufgerufen werden sollte.
pytest.fixture-Argumente sind nur als Schlüsselwort zulässig¶
Entfernt in Version 6.0.
Das Übergeben von Argumenten an pytest.fixture() als Positionsargumente wurde entfernt – übergeben Sie sie stattdessen als Schlüsselwort.
Alias funcargnames für fixturenames¶
Entfernt in Version 6.0.
Die Klassen FixtureRequest, Metafunc und Function verfolgen die Namen ihrer zugehörigen Fixtures mit dem treffend benannten Attribut fixturenames.
Vor pytest 2.3 hieß dieses Attribut funcargnames, und wir haben es seitdem als Alias beibehalten. Es ist endlich zur Entfernung fällig, da es oft dort verwirrend ist, wo wir oder Plugin-Autoren zwischen Fixture-Namen und Namen unterscheiden müssen, die von Nicht-Fixture-Dingen wie pytest.mark.parametrize geliefert werden.
Globales pytest.config¶
Entfernt in Version 5.0.
Das globale Objekt pytest.config ist veraltet. Verwenden Sie stattdessen request.config (über das Fixture request) oder, wenn Sie ein Plugin-Autor sind, den Hook pytest_configure(config). Beachten Sie, dass viele Hooks auch indirekt auf das config-Objekt zugreifen können, zum Beispiel über session.config oder item.config.
Parameter "message" von pytest.raises¶
Entfernt in Version 5.0.
Es ist ein häufiger Fehler zu glauben, dass dieser Parameter die Fehlermeldung abgleicht, während er tatsächlich nur dazu dient, eine benutzerdefinierte Nachricht bereitzustellen, falls die pytest.raises-Prüfung fehlschlägt. Um zu verhindern, dass Benutzer diesen Fehler machen, und weil er vermutlich wenig genutzt wird, macht pytest ihn veraltet, ohne vorerst eine Alternative anzubieten.
Wenn Sie einen gültigen Anwendungsfall für diesen Parameter haben, bedenken Sie, dass Sie, um die gleichen Ergebnisse zu erzielen, einfach pytest.fail am Ende der with-Anweisung manuell aufrufen können.
Zum Beispiel
with pytest.raises(TimeoutError, message="Client got unexpected message"):
wait_for(websocket.recv(), 0.5)
Wird zu
with pytest.raises(TimeoutError):
wait_for(websocket.recv(), 0.5)
pytest.fail("Client got unexpected message")
Wenn Sie weiterhin Bedenken bezüglich dieser Veraltung und zukünftigen Entfernung haben, kommentieren Sie bitte unter #3974.
raises / warns mit einem String als zweitem Argument¶
Entfernt in Version 5.0.
Verwenden Sie stattdessen die Kontextmanager-Form davon. Wenn nötig, rufen Sie exec direkt auf.
Beispiel
pytest.raises(ZeroDivisionError, "1 / 0")
pytest.raises(SyntaxError, "a $ b")
pytest.warns(DeprecationWarning, "my_function()")
pytest.warns(SyntaxWarning, "assert(1, 2)")
Wird zu
with pytest.raises(ZeroDivisionError):
1 / 0
with pytest.raises(SyntaxError):
exec("a $ b") # exec is required for invalid syntax
with pytest.warns(DeprecationWarning):
my_function()
with pytest.warns(SyntaxWarning):
exec("assert(1, 2)") # exec is used to avoid a top-level warning
Verwendung von Class in benutzerdefinierten Sammlern¶
Entfernt in Version 4.0.
Die Verwendung von Objekten namens "Class" als Möglichkeit, den Typ der in Collector-Unterklassen gesammelten Knoten anzupassen, wurde als veraltet markiert. Benutzer sollten stattdessen pytest_pycollect_makeitem verwenden, um Knotentypen während der Sammlung anzupassen.
Dieses Problem sollte nur fortgeschrittene Plugins betreffen, die neue Sammlungsarten erstellen. Wenn Sie diese Warnmeldung sehen, wenden Sie sich bitte an die Autoren, damit sie den Code ändern können.
Markierungen in pytest.mark.parametrize¶
Entfernt in Version 4.0.
Das Anwenden von Markierungen auf Werte eines Aufrufs von pytest.mark.parametrize ist nun veraltet. Zum Beispiel
@pytest.mark.parametrize(
"a, b",
[
(3, 9),
pytest.mark.xfail(reason="flaky")(6, 36),
(10, 100),
(20, 200),
(40, 400),
(50, 500),
],
)
def test_foo(a, b): ...
Dieser Code wendet die Markierung pytest.mark.xfail(reason="flaky") auf den Wert (6, 36) des obigen Parametrisierungsaufrufs an.
Dies wurde als schwer lesbar und verständlich angesehen, und seine Implementierung bereitete dem Code auch Probleme, die weitere interne Verbesserungen an der Markierungsarchitektur verhinderten.
Um den Code zu aktualisieren, verwenden Sie pytest.param
@pytest.mark.parametrize(
"a, b",
[
(3, 9),
pytest.param(6, 36, marks=pytest.mark.xfail(reason="flaky")),
(10, 100),
(20, 200),
(40, 400),
(50, 500),
],
)
def test_foo(a, b): ...
Präfix pytest_funcarg__¶
Entfernt in Version 4.0.
In sehr frühen pytest-Versionen konnten Fixtures mit dem Präfix pytest_funcarg__ definiert werden.
def pytest_funcarg__data():
return SomeData()
Wechseln Sie zum Dekorator @pytest.fixture
@pytest.fixture
def data():
return SomeData()
[pytest]-Abschnitt in setup.cfg-Dateien¶
Entfernt in Version 4.0.
[pytest]-Abschnitte in setup.cfg-Dateien sollten nun [tool:pytest] heißen, um Konflikte mit anderen distutils-Befehlen zu vermeiden.
Metafunc.addcall¶
Entfernt in Version 4.0.
Metafunc.addcall war ein Vorläufer des aktuellen parametrisierten Mechanismus. Benutzer sollten stattdessen pytest.Metafunc.parametrize() verwenden.
Beispiel
def pytest_generate_tests(metafunc):
metafunc.addcall({"i": 1}, id="1")
metafunc.addcall({"i": 2}, id="2")
Wird zu
def pytest_generate_tests(metafunc):
metafunc.parametrize("i", [1, 2], ids=["1", "2"])
cached_setup¶
Entfernt in Version 4.0.
request.cached_setup war der Vorläufer des Setup/Teardown-Mechanismus, der für Fixtures verfügbar ist.
Beispiel
@pytest.fixture
def db_session():
return request.cached_setup(
setup=Session.create, teardown=lambda session: session.close(), scope="module"
)
Dies sollte aktualisiert werden, um den Standard-Fixture-Mechanismen zu nutzen.
@pytest.fixture(scope="module")
def db_session():
session = Session.create()
yield session
session.close()
Sie können den Abschnitt „Vergleich von Funcargs“ in der Dokumentation für weitere Informationen konsultieren.
pytest_plugins in conftest-Dateien, die nicht auf der obersten Ebene liegen¶
Entfernt in Version 4.0.
Das Definieren von pytest_plugins ist nun in Nicht-Top-Level-conftest.py-Dateien veraltet, da sie referenzierte Plugins *global* aktivieren, was überraschend ist, da für alle anderen pytest-Funktionen conftest.py-Dateien nur für Tests auf oder unterhalb ihrer Ebene *aktiv* sind.
Config.warn und Node.warn¶
Entfernt in Version 4.0.
Diese Methoden waren Teil des internen pytest-Warnsystems, aber seit 3.8 verwendet pytest das eingebaute Warnsystem für seine eigenen Warnungen, sodass diese beiden Funktionen nun veraltet sind.
Config.warn sollte durch Aufrufe des Standard warnings.warn ersetzt werden, Beispiel
config.warn("C1", "some warning")
Wird zu
warnings.warn(pytest.PytestWarning("some warning"))
Node.warn unterstützt nun zwei Signaturen
node.warn(PytestWarning("some message")): ist nun der **empfohlene** Weg, diese Funktion aufzurufen. Die Warnungsinstanz muss eine PytestWarning oder eine Unterklasse sein.node.warn("CI", "some message"): dieses Code/Nachrichten-Format wurde **entfernt** und sollte in das obige Warnungsinstanz-Format umgewandelt werden.
record_xml_property¶
Entfernt in Version 4.0.
Das Fixture record_xml_property ist nun veraltet zugunsten des allgemeineren record_property, das von anderen Konsumenten (z.B. pytest-html) verwendet werden kann, um benutzerdefinierte Informationen über den Testlauf zu erhalten.
Dies ist nur eine Umbenennung des Fixtures, da die API dieselbe ist.
def test_foo(record_xml_property): ...
Ändern zu
def test_foo(record_property): ...
Übergabe eines Kommandozeilenstrings an pytest.main()¶
Entfernt in Version 4.0.
Das Übergeben eines Kommandozeilenstrings an pytest.main() ist veraltet.
pytest.main("-v -s")
Übergeben Sie stattdessen eine Liste.
pytest.main(["-v", "-s"])
Durch die Übergabe eines Strings erwarten die Benutzer, dass pytest diese Kommandozeile nach den Shell-Regeln interpretiert, mit denen sie arbeiten (z. B. bash oder Powershell), aber dies ist auf portable Weise sehr schwierig/unmöglich zu tun.
Direktes Aufrufen von Fixtures¶
Entfernt in Version 4.0.
Das direkte Aufrufen einer Fixture-Funktion, im Gegensatz zur Anforderung in einer Testfunktion, ist veraltet.
Zum Beispiel
@pytest.fixture
def cell():
return ...
@pytest.fixture
def full_cell():
cell = cell()
cell.make_full()
return cell
Dies ist eine große Quelle der Verwirrung für neue Benutzer, die oft Fixture-Funktionen aufrufen und sie austauschbar von Testfunktionen anfordern, was das Fixture-Auflösungsmodell bricht.
Fordern Sie in diesen Fällen die Funktion einfach direkt im abhängigen Fixture an.
@pytest.fixture
def cell():
return ...
@pytest.fixture
def full_cell(cell):
cell.make_full()
return cell
Alternativ, wenn die Fixture-Funktion mehrmals innerhalb eines Tests aufgerufen wird (was es schwierig macht, das obige Muster anzuwenden) oder wenn Sie minimale Änderungen am Code vornehmen möchten, können Sie ein Fixture erstellen, das die ursprüngliche Funktion zusammen mit dem Parameter name aufruft.
def cell():
return ...
@pytest.fixture(name="cell")
def cell_fixture():
return cell()
Interne Klassen, auf die über Node zugegriffen wird¶
Entfernt in Version 4.0.
Der Zugriff auf Module, Function, Class, Instance, File und Item über Node-Instanzen gibt nun diese Warnung aus.
usage of Function.Module is deprecated, please use pytest.Module instead
Benutzer sollten einfach import pytest und auf diese Objekte über das pytest-Modul zugreifen.
Dies wurde jahrelang als veraltet dokumentiert, aber erst jetzt geben wir tatsächlich Veraltungswarnungen aus.
Node.get_marker¶
Entfernt in Version 4.0.
Als Teil einer großen Überarbeitung und Iteration der Markierungen wird _pytest.nodes.Node.get_marker entfernt. Siehe die Dokumentation für Tipps zur Aktualisierung Ihres Codes.
somefunction.markname¶
Entfernt in Version 4.0.
Als Teil einer großen Überarbeitung und Iteration der Markierungen wurde die Verwendung von MarkInfo bereits als veraltet markiert. Der einzig korrekte Weg, Markierungen eines Elements abzurufen, ist über node.iter_markers(name).
pytest_namespace¶
Entfernt in Version 4.0.
Dieser Hook ist veraltet, da er die internen Abläufe von pytest bezüglich Konfiguration und Initialisierung stark verkompliziert und einige Fehlerbehebungen und Refaktorisierungen unmöglich macht.
Beispiel für die Verwendung
class MySymbol: ...
def pytest_namespace():
return {"my_symbol": MySymbol()}
Plugin-Autoren, die auf diesen Hook angewiesen sind, sollten stattdessen verlangen, dass Benutzer nun die Plugin-Module direkt importieren (mit einer entsprechenden öffentlichen API).
Als Übergangsmaßnahme können Plugin-Autoren weiterhin ihre Namen in den pytest-Namespace einfügen, normalerweise während pytest_configure.
import pytest
def pytest_configure():
pytest.my_symbol = MySymbol()