如何使用parametrize测试返回值为None或非None?
问题:如何用pytest参数化测试返回值为None或非None的场景?
我有一个方法,在某些异常场景下应返回None,其他情况则返回复杂结果。示例方法foo如下:
import typing def foo(x: int) -> typing.Optional[float]: if x == 0 or x == 10: return None else: return 1/x
我已针对正常场景编写单元测试验证复杂结果,现在想编写测试,验证异常场景返回None、正常场景返回非None。尝试使用pytest的parametrize参数化测试:
import pytest @pytest.mark.parametrize("x, target", [(0, None), (10, None), (5, not None)]) def test_foo(x, target): assert foo(x) is target
期望第三个测试用例执行assert foo(5) is not None,但not None会被解析为True,导致断言foo(x) is True失败。请问如何使用parametrize正确测试返回值为None或非None?
可行解决方案
方案1:传入断言判断函数
把target换成判断逻辑的函数,在测试中调用函数验证结果:
import pytest import typing def foo(x: int) -> typing.Optional[float]: if x == 0 or x == 10: return None else: return 1/x @pytest.mark.parametrize("x, validator", [ (0, lambda res: res is None), (10, lambda res: res is None), (5, lambda res: res is not None) ]) def test_foo(x, validator): result = foo(x) assert validator(result)
方案2:用布尔标记分支处理断言
给参数化用例传入一个布尔标记,在测试中根据标记执行对应断言:
import pytest import typing def foo(x: int) -> typing.Optional[float]: if x == 0 or x == 10: return None else: return 1/x @pytest.mark.parametrize("x, should_be_none", [ (0, True), (10, True), (5, False) ]) def test_foo(x, should_be_none): result = foo(x) if should_be_none: assert result is None else: assert result is not None
方案3:拆分场景为独立参数化测试
如果场景区分明确,拆成两个独立的参数化测试,逻辑更直观:
import pytest import typing def foo(x: int) -> typing.Optional[float]: if x == 0 or x == 10: return None else: return 1/x @pytest.mark.parametrize("x", [0, 10]) def test_foo_returns_none(x): assert foo(x) is None @pytest.mark.parametrize("x", [5, 3, 7]) def test_foo_returns_non_none(x): assert foo(x) is not None
内容的提问来源于stack exchange,提问作者Qaswed
相关产品推荐
相关产品推荐

