如何使用子测试¶
9.0 版本新增。
注意
此功能尚处于实验阶段。其行为,特别是报告失败的方式,可能会在未来版本中有所演变。然而,其核心功能和用法被认为是稳定的。
pytest 允许在正常测试中分组断言,这被称为 子测试。
子测试是参数化的替代方案,特别是在收集时不知道确切的参数化值时非常有用。
# content of test_subtest.py
def test(subtests):
for i in range(5):
with subtests.test(msg="custom message", i=i):
assert i % 2 == 0
每个断言失败或错误都会被上下文管理器捕获并单独报告。
$ pytest -q test_subtest.py
uuuuuF [100%]
================================= FAILURES =================================
_______________________ test [custom message] (i=1) ________________________
subtests = <_pytest.subtests.Subtests object at 0xdeadbeef0001>
def test(subtests):
for i in range(5):
with subtests.test(msg="custom message", i=i):
> assert i % 2 == 0
E assert (1 % 2) == 0
test_subtest.py:6: AssertionError
_______________________ test [custom message] (i=3) ________________________
subtests = <_pytest.subtests.Subtests object at 0xdeadbeef0001>
def test(subtests):
for i in range(5):
with subtests.test(msg="custom message", i=i):
> assert i % 2 == 0
E assert (3 % 2) == 0
test_subtest.py:6: AssertionError
___________________________________ test ___________________________________
contains 2 failed subtests
========================= short test summary info ==========================
SUBFAILED[custom message] (i=1) test_subtest.py::test - assert (1 % 2) == 0
SUBFAILED[custom message] (i=3) test_subtest.py::test - assert (3 % 2) == 0
FAILED test_subtest.py::test - contains 2 failed subtests
3 failed, 3 subtests passed in 0.12s
在上面的输出中
子测试失败被报告为
SUBFAILED。子测试首先被报告,“顶层”测试最后单独报告。
请注意,可以在同一个测试中多次使用 subtests,甚至可以与 subtests.test 块外部的正常断言混合使用。
def test(subtests):
for i in range(5):
with subtests.test("stage 1", i=i):
assert i % 2 == 0
assert func() == 10
for i in range(10, 20):
with subtests.test("stage 2", i=i):
assert i % 2 == 0
注意
有关子测试的替代方案,请参阅 如何参数化夹具和测试函数。
详细程度¶
默认情况下,只显示 子测试失败。更高的详细程度 (-v) 也会显示 通过 的子测试的进度输出。
可以通过设置 verbosity_subtests 来控制子测试的详细程度。
类型¶
pytest.Subtests 已导出,因此可以在类型注解中使用。
def test(subtests: pytest.Subtests) -> None: ...
参数化与子测试¶
虽然 传统的 pytest 参数化 和 subtests 相似,但它们有重要的区别和用例。
参数化¶
发生在收集时。
生成单独的测试。
可以通过命令行引用参数化测试。
与处理测试执行的插件(例如
--last-failed)配合良好。非常适合决策表测试。
子测试¶
发生在测试执行期间。
在收集时未知。
可以动态生成。
无法通过命令行单独引用。
处理测试执行的插件无法针对单个子测试。
子测试内的断言失败不会中断测试,让用户可以在同一个报告中看到所有失败。