如何在pytest参数化测试的元组中使用pytest.param标记xfail?
pytest参数化:多预期值与部分断言xfail的解决方案
正常运行的单参数xfail示例
以下代码可正常运行,pytest.param用于包装单个参数并标记xfail:
import pytest @pytest.mark.parametrize( "expected", [ pytest.param(42, marks=pytest.mark.xfail(reason="some bug")), ],) def test_func(expected): assert 123 == expected
输出结果:
test_xfail_demo_1.py::test_func[42] XFAIL (some bug) ========== 1 xfailed in 0.07s ==========
错误的多参数尝试
直接在元组中嵌套pytest.param会导致参数解析错误,代码如下:
import pytest def someFunc(): return 1 def someOtherFunc(): return 123 @pytest.mark.parametrize( "expected", [ (1, pytest.param(42, marks=pytest.mark.xfail(reason="some bug"))), ],) def test_func(expected): assert someFunc() == expected[0] assert someOtherFunc() == expected[1]
错误信息:
> assert someOtherFunc() == expected[1] E AssertionError: assert 123 == ParameterSet(values=(42,), marks=(MarkDecorator(mark=Mark(name='xfail', args=(), kwargs={'reason': 'some bug'})),), id=None) path/to/test_xfail_demo_2.py:10: AssertionError ==================== short test summary info =============== FAILED path/to/test_xfail_demo_2.py::test_func[expected0] - AssertionError: assert 123 == ParameterSet(values=(42,), marks=(MarkDecorator(mark=Mark(name='xfail', args=(), kwargs={'reason': 'some bug'})),), id=None) ============== 1 failed in 0.09s =====
错误原因:pytest.param是用来包装整个参数化条目的工具,不是普通值。将它放在元组中时,它不会被解析为参数标记,而是作为普通对象传入测试函数,导致断言时123和ParameterSet对象比较,触发错误。
正确的实现方式
方式1:用pytest.param包装整个元组,标记整个用例xfail
如果整个测试用例的失败符合预期(第二个断言必然失败),可以直接用pytest.param包装包含所有预期值的元组,标记整个用例为xfail:
import pytest def someFunc(): return 1 def someOtherFunc(): return 123 @pytest.mark.parametrize("expected", [ pytest.param((1, 42), marks=pytest.mark.xfail(reason="some bug")), ],) def test_func(expected): assert someFunc() == expected[0] assert someOtherFunc() == expected[1]
运行后输出:
test_xfail_demo_2.py::test_func[(1, 42)] XFAIL (some bug) ========== 1 xfailed in 0.08s ==========
方式2:在测试函数内部单独处理需要xfail的断言
如果希望仅特定断言被标记为xfail(而非整个用例),可以在测试函数中捕获该断言的错误,手动触发xfail:
import pytest def someFunc(): return 1 def someOtherFunc(): return 123 @pytest.mark.parametrize("expected", [ (1, 42), ],) def test_func(expected): # 第一个断言正常验证 assert someFunc() == expected[0] # 第二个断言预期失败,捕获错误后标记xfail try: assert someOtherFunc() == expected[1] except AssertionError: pytest.xfail("some bug")
运行后同样会显示测试用例被标记为XFAIL,且第一个断言的验证结果不会被影响。
内容的提问来源于stack exchange,提问作者Shuman
相关产品推荐
相关产品推荐

