Arbeiten mit Nicht-Python-Tests¶
Ein einfaches Beispiel für die Spezifikation von Tests in Yaml-Dateien¶
Hier ist ein Beispiel für eine conftest.py (entnommen aus Ali Afshars speziellem Plugin pytest-yamlwsgi). Dieses conftest.py sammelt test*.yaml-Dateien und führt den YAML-formatierten Inhalt als benutzerdefinierte Tests aus.
# content of conftest.py
from __future__ import annotations
import pytest
def pytest_collect_file(parent, file_path):
if file_path.suffix == ".yaml" and file_path.name.startswith("test"):
return YamlFile.from_parent(parent, path=file_path)
class YamlFile(pytest.File):
def collect(self):
# We need a yaml parser, e.g. PyYAML.
import yaml
raw = yaml.safe_load(self.path.open(encoding="utf-8"))
for name, spec in sorted(raw.items()):
yield YamlItem.from_parent(self, name=name, spec=spec)
class YamlItem(pytest.Item):
def __init__(self, *, spec, **kwargs):
super().__init__(**kwargs)
self.spec = spec
def runtest(self):
for name, value in sorted(self.spec.items()):
# Some custom test execution (dumb example follows).
if name != value:
raise YamlException(self, name, value)
def repr_failure(self, excinfo):
"""Called when self.runtest() raises an exception."""
if isinstance(excinfo.value, YamlException):
return "\n".join(
[
"usecase execution failed",
" spec failed: {1!r}: {2!r}".format(*excinfo.value.args),
" no further details known at this point.",
]
)
return super().repr_failure(excinfo)
def reportinfo(self):
return self.path, 0, f"usecase: {self.name}"
class YamlException(Exception):
"""Custom exception for error reporting."""
Sie können eine einfache Beispieldatei erstellen.
# test_simple.yaml
ok:
sub1: sub1
hello:
world: world
some: other
Und wenn Sie PyYAML oder einen kompatiblen YAML-Parser installiert haben, können Sie nun die Testspezifikation ausführen.
nonpython $ pytest test_simple.yaml
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y
rootdir: /home/sweet/project/nonpython
collected 2 items
test_simple.yaml F. [100%]
================================= FAILURES =================================
______________________________ usecase: hello ______________________________
usecase execution failed
spec failed: 'some': 'other'
no further details known at this point.
========================= short test summary info ==========================
FAILED test_simple.yaml::hello - usecase execution failed
======================= 1 failed, 1 passed in 0.12s ========================
Sie erhalten einen Punkt für die erfolgreich bestandene Prüfung sub1: sub1 und einen Fehler. Offensichtlich werden Sie in der obigen conftest.py eine interessantere Interpretation der YAML-Werte implementieren wollen. Sie können auf diese Weise leicht Ihre eigene domänenspezifische Testsprache schreiben.
Hinweis
repr_failure(excinfo) wird zum Darstellen von Testfehlern aufgerufen. Wenn Sie benutzerdefinierte Sammelknoten erstellen, können Sie eine Fehlersymbolzeichenkette Ihrer Wahl zurückgeben. Sie wird als (rote) Zeichenkette gemeldet.
reportinfo() wird zum Darstellen des Testorts verwendet und wird auch bei der Berichterstattung im verbose-Modus konsultiert.
nonpython $ pytest -v
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python
cachedir: .pytest_cache
rootdir: /home/sweet/project/nonpython
collecting ... collected 2 items
test_simple.yaml::hello FAILED [ 50%]
test_simple.yaml::ok PASSED [100%]
================================= FAILURES =================================
______________________________ usecase: hello ______________________________
usecase execution failed
spec failed: 'some': 'other'
no further details known at this point.
========================= short test summary info ==========================
FAILED test_simple.yaml::hello - usecase execution failed
======================= 1 failed, 1 passed in 0.12s ========================
Während der Entwicklung Ihrer benutzerdefinierten Testsammlung und -ausführung ist es auch interessant, einfach den Sammlungbaum zu betrachten.
nonpython $ pytest --collect-only
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-9.x.y, pluggy-1.x.y
rootdir: /home/sweet/project/nonpython
collected 2 items
<Package nonpython>
<YamlFile test_simple.yaml>
<YamlItem hello>
<YamlItem ok>
======================== 2 tests collected in 0.12s ========================