Pytest如何参数化循环内断言,测试不提前终止并展示全部错误结果
解决方案
以下是3种常用实现方式,可根据实际场景选择:
方案1:使用pytest原生subtests上下文(零额外依赖,改动最小)
不需要修改外层参数化逻辑,仅需把循环内的断言包裹在subtests上下文中即可,运行时所有不匹配的项都会被单独统计,不会出现第一个断言失败就终止测试的情况,失败时还会自动标记不匹配元素的索引位置。
import pytest @pytest.mark.parametrize("inp, output", zip(INPUT, OUTPUT)) def test_example_to_ask_in_stackoverflow(inp, output): result = my_test_function(inp) for idx, (res_a, exp_res) in enumerate(zip(result.a, output)): with pytest.subtest(element_index=idx): assert res_a == exp_res
该方案优势是无需提前预处理测试数据,完全保留原有测试用例结构,运行结束后会统一输出所有不匹配项的位置、实际值和预期值。
方案2:完全展开为参数化用例
如果希望每个元素的校验都作为独立测试用例展示,可以提前把测试数据展平,将输入、输入索引、元素索引、预期值作为单个参数化项:
# 提前构造展平的参数列表 flattened_params = [] for inp_idx, (inp, output) in enumerate(zip(INPUT, OUTPUT)): for elem_idx, exp_val in enumerate(output): flattened_params.append( (inp, inp_idx, elem_idx, exp_val) ) @pytest.mark.parametrize("inp, inp_idx, elem_idx, exp_val", flattened_params) def test_a_element(inp, inp_idx, elem_idx, exp_val): result = my_test_function(inp) assert result.a[elem_idx] == exp_val
注意该方案会针对每个元素单独调用一次my_test_function,如果该函数运行开销较大,不推荐使用。
方案3:使用pytest-check插件实现软断言
如果不需要拆分子用例,也可以使用pytest-check插件实现批量断言,失败后不会终止测试,会统一统计所有不匹配项:
- 先安装依赖:
pip install pytest-check - 测试代码示例:
import pytest from pytest_check import check @pytest.mark.parametrize("inp, output", zip(INPUT, OUTPUT)) def test_example_to_ask_in_stackoverflow(inp, output): result = my_test_function(inp) for res_a, exp_res in zip(result.a, output): check.equal(res_a, exp_res)
内容的提问来源于stack exchange,提问作者Andrex
相关产品推荐
相关产品推荐

