在上一篇Pytest系列文章:Pytest之收集用例及命令行参数,主要介绍Pytest用例收集规则及常用的命令行参数。
在自动化测试过程中,需要判断预期结果和实际结果是否一致,这时需要使用到断言。
什么是断言呢?简单来说就是实际结果和期望结果去对比。
一、断言用法
在pytest中,使用assert进行断言,格式为:assert 表达式。
如果表达式返回结果为True,则断言成功,否则断言失败。
二、常用断言
unittest 的三种断言:
assertIn(expect,result)断言包含(被包含的写前面);
assertEqual(expect,result)断言相等;
assertTure(条件)断言是否为真。返回Ture或False;
Pytest 里的断言实际上就是Python中的assert断言方法,常用断言方法如下:
-
assert xx :判断 xx 为真; -
assert not xx :判断 xx 不为真; -
assert a in b :判断 b 包含 a; -
assert a == b :判断 a 等于 b; -
assert a != b :判断 a 不等于 b;
import?pytest
def?test_demo1():
????a?=?1
????assert?a
def?test_demo2():
????a?=?0
????assert?not?a
def?test_demo3():
????s?=?'hello'
????assert?'h'?in?s
def?test_demo4():
????a?=?3
????assert?a?==?3
def?test_demo5():
????a?=?4
????assert?a?!=?3
if?__name__?==?'__main__':
????pytest.main()
运行结果如下:
Testing?started?at?18:22?...
C:\Users\96984\Desktop\code\pytest\venv\Scripts\python.exe?"C:\ruanjian\pycharm2019.3\PyCharm?2019.3.1\plugins\python\helpers\pycharm\_jb_pytest_runner.py"?--path?C:/Users/96984/Desktop/code/pytest/demo/demo_pytest.py
Launching?pytest?with?arguments?C:/Users/96984/Desktop/code/learn_pytest/demo/demo_pytest.py?in?C:\Users\96984\Desktop\code\learn_pytest\demo
=============================?test?session?starts?=============================
platform?win32?--?Python?3.6.8,?pytest-5.4.3,?py-1.9.0,?pluggy-0.13.1?--?C:\Users\96984\Desktop\code\learn_pytest\venv\Scripts\python.exe
cachedir:?.pytest_cache
metadata:?{'Python':?'3.6.8',?'Platform':?'Windows-10-10.0.18362-SP0',?'Packages':?{'pytest':?'5.4.3',?'py':?'1.9.0',?'pluggy':?'0.13.1'},?'Plugins':?{'html':?'2.1.1',?'metadata':?'1.10.0'},?'JAVA_HOME':?'C:\\Program?Files\\Java\\jdk1.8.0_77'}
rootdir:?C:\Users\96984\Desktop\code\learn_pytest\demo
plugins:?html-2.1.1,?metadata-1.10.0
collecting?...?collected?5?items
demo_pytest.py::test_demo1?PASSED????????????????????????????????????????[?20%]
demo_pytest.py::test_demo2?PASSED????????????????????????????????????????[?40%]
demo_pytest.py::test_demo3?PASSED????????????????????????????????????????[?60%]
demo_pytest.py::test_demo4?PASSED????????????????????????????????????????[?80%]
demo_pytest.py::test_demo5?PASSED????????????????????????????????????????[100%]
==============================?5?passed?in?0.06s?==============================
Process?finished?with?exit?code?0
三、异常断言
在测试过程中,有时需要对特定异常进行断言,可以使用 pytest.raises 作为上下文管理器,当抛出异常时可以获取到对应的异常实例。
import?pytest
def?test_zero_division():
????1?/?0
if?__name__?==?'__main__':
????pytest.main()
运行结果:
==================================?FAILURES?===================================
_____________________________?test_zero_division?______________________________
????def?test_zero_division():
>???????1?/?0
E???????ZeroDivisionError:?division?by?zero
所以我们需要捕获并断言异常。
断言场景:断言抛出的异常是否符合预期。
预期结果:ZeroDivisionError: division by zero,其中ZeroDivisionError为错误类型,division by zero为具体错误值。
断言方式: ?断言异常的type和value值。
断言代码如下:
import?pytest
def?test_zero_division_long():
????with?pytest.raises(ZeroDivisionError)?as?excinfo:
????????1?/?0
????#?断言异常类型?type
????assert?excinfo.type?==?ZeroDivisionError
????#?断言异常?value?值
????assert?"division?by?zero"?in?str(excinfo.value)
if?__name__?==?'__main__':
????pytest.main()
代码详细说明:
① pytest.raises 捕获异常,源码如下:
def?raises(??#?noqa:?F811
????expected_exception:?Union["Type[_E]",?Tuple["Type[_E]",?...]],
????*args:?Any,
????**kwargs:?Any
)?->?Union["RaisesContext[_E]",?_pytest._code.ExceptionInfo[_E]]:
????__tracebackhide__?=?True
????for?exc?in?filterfalse(
????????inspect.isclass,?always_iterable(expected_exception,?BASE_TYPE)??#?type:?ignore[arg-type]??#?noqa:?F821
????):
????????msg?=?"exceptions?must?be?derived?from?BaseException,?not?%s"
????????raise?TypeError(msg?%?type(exc))
????message?=?"DID?NOT?RAISE?{}".format(expected_exception)
????if?not?args:
????????match?=?kwargs.pop("match",?None)
????????if?kwargs:
????????????msg?=?"Unexpected?keyword?arguments?passed?to?pytest.raises:?"
????????????msg?+=?",?".join(sorted(kwargs))
????????????msg?+=?"\nUse?context-manager?form?instead?"
????????????raise?TypeError(msg)
????????return?RaisesContext(expected_exception,?message,?match)
????else:
????????func?=?args[0]
????????if?not?callable(func):
????????????raise?TypeError(
????????????????"{!r}?object?(type:?{})?must?be?callable".format(func,?type(func))
????????????)
????????try:
????????????func(*args[1:],?**kwargs)
????????except?expected_exception?as?e:
????????????#?We?just?caught?the?exception?-?there?is?a?traceback.
????????????assert?e.__traceback__?is?not?None
????????????return?_pytest._code.ExceptionInfo.from_exc_info(
????????????????(type(e),?e,?e.__traceback__)
????????????)
????fail(message)
raises.Exception?=?fail.Exception??#?type:?ignore
② excinfo作为异常信息实例,拥有type 、value等属性,源码如下:
@property
def?type(self)?->?"Type[_E]":
????"""the?exception?class"""
????assert?(
????????self._excinfo?is?not?None
????),?".type?can?only?be?used?after?the?context?manager?exits"
????return?self._excinfo[0]
@property
def?value(self)?->?_E:
????"""the?exception?value"""
????assert?(
????????self._excinfo?is?not?None
????),?".value?can?only?be?used?after?the?context?manager?exits"
????return?self._excinfo[1]
③ excinfo.value的值是元组,所以要转成字符串。
感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:
① 2000多本软件测试电子书(主流和经典的书籍应该都有了)
② 软件测试/自动化测试标准库资料(最全中文版)
③ 项目源码(四五十个有趣且经典的练手项目及源码)
④ Python编程语言、API接口自动化测试、web自动化测试、App自动化测试(适合小白学习)
??⑤ Python学习路线图(告别不入流的学习)
在我的QQ技术交流群里(技术交流和资源共享,广告进来腿给你打断)
可以自助拿走,群号953306497(备注“csdn111”)群里的免费资料都是笔者十多年测试生涯的精华。还有同行大神一起交流技术哦。
|