上一章学习了pytest的基本用法,今天学习一下断言。
1、assert 基本用法
unitest单元测试框架中提供了丰富的断言方法,如assertEqual()、assertIn()、assertTrue()、assertIs()等,但是pytest没有。直接使用Python的assert进行断言
# MyPytest.pyimport pytestdef inc(x):return x+1# 判断结果不等于5def test_inc_01():assert inc(3) != 5# 判断结果等于4def test_inc_02():assert inc(3) == 4# 判断结果小于等于5def test_inc_03():assert inc(3) <= 5# 判断结果包含在列表内def test_inc_04():assert inc(3) in [1,2,3,4]# 判断结果不为Truedef test_inc_06():a = 1assert a == Trueassert a is not Trueif __name__ =="__main__":pytest.main(['MyPytest.py'])
执行结果:
collected 5 itemsMyPytest.py ..... [100%]============================== 5 passed in 0.08s ==============================***Repl Closed***
2、assert断言失败提示
当我们为了脚本报错后更容易的定位到原因时候,可以在断言的地方输出断言失败提示信息,比如:
# MyPytest.pyimport pytestdef division(x):return 100/xdef test_division_01():res = division(3)assert res == 50 , f"判断 res 为50 ,当前 res 的值为{res}"if __name__ =="__main__":pytest.main(['MyPytest.py'])
执行结果:
collected 1 itemMyPytest.py F [100%]================================== FAILURES ===================================______________________________ test_division_01 _______________________________def test_division_01():res = division(3)> assert res == 50 , f"判断 res 为50 ,当前 res 的值为{res}"E AssertionError: 判断 res 为50 ,当前 res 的值为33.333333333333336E assert 33.333333333333336 == 50MyPytest.py:10: AssertionError=========================== short test summary info ===========================FAILED MyPytest.py::test_division_01 - AssertionError: 判断 res 为50 ,当前 r...============================== 1 failed in 0.21s ==============================***Repl Closed***
3、预期内异常报错断言
有时候一些场景我们明知道它会报错,也知道这种报错,是正常的预期,比如:
# MyPytest.pyimport pytestdef division(x):return 100/xdef test_division_01():res = division(0)if __name__ =="__main__":pytest.main(['MyPytest.py'])
执行结果:
collected 1 itemMyPytest.py F [100%]================================== FAILURES ===================================______________________________ test_division_01 _______________________________def test_division_01():> res = division(0)MyPytest.py:9:_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _x = 0def division(x):> return 100/xE ZeroDivisionError: division by zeroMyPytest.py:5: ZeroDivisionError=========================== short test summary info ===========================FAILED MyPytest.py::test_division_01 - ZeroDivisionError: division by zero============================== 1 failed in 0.21s ==============================***Repl Closed***
100 \ 0的时候报错ZeroDivisionError: division by zero。为了对这种异常场景进行断言,我们需要使用pytest.raises,用法如下:
# MyPytest.pyimport pytestdef division(x):return 100/xdef test_division_01():with pytest.raises(ZeroDivisionError) as e:division(0)assert e.type == ZeroDivisionErrorassert "division by zero" in str(e.value)if __name__ =="__main__":pytest.main(['MyPytest.py'])
注意:断言 type 的时候,异常类型是不需要加引号的,断言 value 值的时候需转 str
4、非预期内异常
如果我们不知道预期异常的是什么,我们可以使用match和raise进行自定义异常
# MyPytest.pyimport pytestdef division(x):if x == 0:raise ValueError('value not 0 or None')if isinstance(x,str):raise TypeError('value not String')return 100/xdef test_division_01():with pytest.raises(ValueError,match = 'value not 0 or None') as e:division(0)assert e.type == ValueErrorassert "value not 0 or None" in str(e.value)def test_division_02():with pytest.raises(TypeError,match = 'value not String') as e:division("String")assert e.type == TypeErrorassert "value not String" in str(e.value)if __name__ =="__main__":pytest.main(['MyPytest.py'])
5、pytest-assume插件
pytest-assume是一个可以允许pytest测试用例中执行多个失败的断言的插件。
安装
pip install pytest-assume
对比assert :
import pytestdef inc(x):return x+1# assert断言def test_inc_01():assert inc(3) == 5assert inc(3) == 4assert inc(3) == 3# pytest.assume断言def test_inc_02():pytest.assume(inc(3) == 5)pytest.assume(inc(3) == 4)pytest.assume(inc(3) == 3)if __name__ =="__main__":pytest.main(['MyPytest.py'])
结果:
collected 2 itemsMyPytest.py FF [100%]================================== FAILURES ===================================_________________________________ test_inc_01 _________________________________def test_inc_01():> assert inc(3) == 5E assert 4 == 5E + where 4 = inc(3)MyPytest.py:8: AssertionError_________________________________ test_inc_02 _________________________________tp = <class 'pytest_assume.plugin.FailedAssumption'>, value = None, tb = Nonedef reraise(tp, value, tb=None):try:if value is None:value = tp()if value.__traceback__ is not tb:> raise value.with_traceback(tb)E pytest_assume.plugin.FailedAssumption:E 2 Failed Assumptions:EE MyPytest.py:15: AssumptionFailureE >> pytest.assume(inc(3) == 5)E AssertionError: assert FalseEE MyPytest.py:17: AssumptionFailureE >> pytest.assume(inc(3) == 3)E AssertionError: assert FalseD:\software\python\lib\site-packages\six.py:718: FailedAssumption=========================== short test summary info ===========================FAILED MyPytest.py::test_inc_01 - assert 4 == 5FAILED MyPytest.py::test_inc_02 - pytest_assume.plugin.FailedAssumption:============================== 2 failed in 0.26s ==============================***Repl Closed***
对比发现,pytest.assume在第一个断言失败的情况下继续执行后续的断言,不会终止~
