python - 使用 pytest 的参数化,如果一个测试用例失败,我如何跳过剩余的测试?
问题描述
我pytest.mark.parametrize
用来将越来越长的输入输入到一个相当慢的测试函数中,如下所示:
@pytest.mark.parametrize('data', [
b'ab',
b'xyz'*1000,
b'12345'*1024**2,
... # etc
])
def test_compression(data):
... # compress the data
... # decompress the data
assert decompressed_data == data
因为压缩大量数据需要很长时间,所以我想在一个失败后跳过所有剩余的测试。例如,如果输入b'ab'
(第一个)测试失败,b'xyz'*1000
并且b'12345'*1024**2
应该跳过所有其他参数化(或 xfail 不被执行)。
我知道可以将标记附加到单个参数化,如下所示:
@pytest.mark.parametrize("test_input,expected", [
("3+5", 8),
("2+4", 6),
pytest.param("6*9", 42, marks=pytest.mark.xfail),
])
但我不知道如何根据前一个测试用例的状态有条件地应用这些标记。有没有办法做到这一点?
解决方案
skipif
标记是在执行测试之前评估的,因此无法通过依赖于其他测试结果的某种声明性标记(如)。不过,您可以在挂钩中应用自定义测试跳过逻辑。修改增量测试 -pytest
文档中的测试步骤配方:
# conftest.py
import pytest
def pytest_sessionstart(session):
session.failednames = set()
def pytest_runtest_makereport(item, call):
if call.excinfo is not None:
item.session.failednames.add(item.originalname)
def pytest_runtest_setup(item):
if item.originalname in item.session.failednames:
pytest.skip("previous test failed (%s)" % item.name) # or use pytest.xfail like in the other answer
示例测试
@pytest.mark.parametrize('i', range(10))
def test_spam(i):
assert i != 3
产量:
=================================== test session starts ===================================
collected 10 items
test_spam.py::test_spam[0] PASSED
test_spam.py::test_spam[1] PASSED
test_spam.py::test_spam[2] PASSED
test_spam.py::test_spam[3] FAILED
test_spam.py::test_spam[4] SKIPPED
test_spam.py::test_spam[5] SKIPPED
test_spam.py::test_spam[6] SKIPPED
test_spam.py::test_spam[7] SKIPPED
test_spam.py::test_spam[8] SKIPPED
test_spam.py::test_spam[9] SKIPPED
========================================= FAILURES ========================================
_______________________________________ test_spam[3] ______________________________________
i = 3
@pytest.mark.parametrize('i', range(10))
def test_spam(i):
> assert i != 3
E assert 3 != 3
test_spam.py:5: AssertionError
====================== 1 failed, 3 passed, 6 skipped in 0.06 seconds ======================
编辑:使用自定义标记
def pytest_runtest_makereport(item, call):
markers = {marker.name for marker in item.iter_markers()}
if call.excinfo is not None and 'skiprest' in markers:
item.session.failednames.add(item.originalname)
def pytest_runtest_setup(item):
markers = {marker.name for marker in item.iter_markers()}
if item.originalname in item.session.failednames and 'skiprest' in markers:
pytest.skip(item.name)
用法:
@pytest.mark.skiprest
@pytest.mark.parametrize('somearg', ['a', 'b', 'c'])
def test_marked(somearg):
...
推荐阅读
- css - 如何使用 CSS 水平对齐表格中的垂直文本?
- flutter - WebSocketChannelException:SocketException:操作系统错误:操作超时,errno = 60,地址 = echo.websocket.org,端口 = 52365
- python - 如何返回类参数列表?
- json - 如何将 ArrayList 项传递给 Flutter 中的 http 请求(post)正文?
- rust - 为什么我们必须借用类型而不是变量的名称
- javascript - 如何制作下拉菜单
- asp.net-mvc - 值不能为空。ASP 中的参数名称 DropdownList。网络核心
- azure - 从 azure apim 导出 OAS 中的安全性和策略
- python - 仅当间隙小于 N nans 时才填充 pandas df 中的 nan 间隙
- typescript - 在 TypeScript 中从参数推断通用类型的回调