在YAML文件中指定测试的基本示例
这里提供了一个conftest.py
文件的示例(该示例源自Ali Afshar的特定用途pytest插件pytest-yamlwsgi 的提取)。这个conftest.py
文件将收集以test
开头的.yaml
文件,并将YAML格式的内容作为自定义测试来执行。
# content of conftest.py
# conftest.py 的内容
from __future__ import annotations
import pytest
def pytest_collect_file(parent, file_path):
# 如果文件是.yaml格式且文件名以test开头,则通过YamlFile类来收集这个测试文件
if file_path.suffix == ".yaml" and file_path.name.startswith("test"):
return YamlFile.from_parent(parent, path=file_path)
# 定义一个继承自pytest.File的类,用于表示YAML文件类型的测试项
class YamlFile(pytest.File):
def collect(self):
# 我们需要一个YAML解析器,比如PyYAML
import yaml
# 加载YAML文件内容
raw = yaml.safe_load(self.path.open(encoding="utf-8"))
# 遍历YAML文件中的每个测试项(这里假设YAML文件的内容是一个字典,键是测试名,值是测试规范)
for name, spec in sorted(raw.items()):
yield YamlItem.from_parent(self, name=name, spec=spec)
# 定义一个继承自pytest.Item的类,用于表示YAML文件中的每个测试项
class YamlItem(pytest.Item):
def __init__(self, *, spec, **kwargs):
super().__init__(**kwargs)
self.spec = spec # 存储测试规范
def runtest(self):
# 这里是一个简单的测试执行示例,实际上你应该根据spec的内容来执行相应的测试逻辑
for name, value in sorted(self.spec.items()):
# 假设如果键和值不相等,则测试失败(这只是一个示例)
if name != value:
raise YamlException(self, name, value)
def repr_failure(self, excinfo):
# 当runtest方法抛出异常时,这个方法会被调用以生成错误报告
if isinstance(excinfo.value, YamlException):
return "\n".join(
[
"usecase execution failed",
f" spec failed: {excinfo.value.args[1]!r}: {excinfo.value.args[2]!r}",
" 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):
pass
你可以创建一个简单的示例文件:
# test_simple.yaml
ok:
sub1: sub1
hello:
world: world
some: other
如果你已经安装了PyYAML或兼容的YAML解析器,那么你现在可以执行这个测试规范:
nonpython $ pytest test_simple.yaml
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-8.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
======================= 1 failed, 1 passed in 0.12s ========================
你得到了一个点来表示通过的子项检查(sub1: sub1),以及一个失败项。显然,在上面的conftest.py
中,你会想要实现一个对YAML值更有趣的解释。通过这种方式,你可以很容易地编写自己的领域特定测试语言。
注意
repr_failure(excinfo)
是在表示测试失败时被调用的。如果你创建了自定义的集合节点,你可以返回一个你选择的错误表示字符串。这个字符串将以(红色)字符串的形式被报告出来。
reportinfo()
用于表示测试的位置,并且在以详细模式报告时也会被调用:
nonpython $ pytest -v
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-8.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
======================= 1 failed, 1 passed in 0.12s ========================
在开发你的自定义测试收集和执行时,仅仅查看集合树也是很有趣的
nonpython $ pytest --collect-only
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-8.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 ========================