Pytest之?dāng)嘌?/h1>
VOL 147

04
2020-08
今天距2021年149天
這是ITester軟件測(cè)試小棧第147次推文

點(diǎn)擊上方藍(lán)字“ITester軟件測(cè)試小棧“關(guān)注我,每周一、三、五早上?07:30準(zhǔn)時(shí)推送。
微信公眾號(hào)后臺(tái)回復(fù)“資源”、“測(cè)試工具包”領(lǐng)取測(cè)試資源,回復(fù)“微信群”一起進(jìn)群打怪。
本文4633字,閱讀約需12分鐘
在上一篇Pytest系列文章:Pytest之收集用例及命令行參數(shù),主要介紹Pytest用例收集規(guī)則及常用的命令行參數(shù)。
在自動(dòng)化測(cè)試過(guò)程中,需要判斷預(yù)期結(jié)果和實(shí)際結(jié)果是否一致,這時(shí)需要使用到斷言。
什么是斷言呢?簡(jiǎn)單來(lái)說(shuō)就是實(shí)際結(jié)果和期望結(jié)果去對(duì)比。
一 斷言用法
在pytest中,使用assert進(jìn)行斷言,格式為:assert 表達(dá)式。
如果表達(dá)式返回結(jié)果為True,則斷言成功,否則斷言失敗。
二 常用斷言
unittest的三種斷言:
assertIn(expect,result)斷言包含(被包含的寫前面);
assertEqual(expect,result)斷言相等;
assertTure(條件)斷言是否為真。返回Ture或False;
Pytest里的斷言實(shí)際上就是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()
運(yùn)行結(jié)果如下:
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
三 異常斷言
在測(cè)試過(guò)程中,有時(shí)需要對(duì)特定異常進(jìn)行斷言,可以使用 pytest.raises 作為上下文管理器,當(dāng)拋出異常時(shí)可以獲取到對(duì)應(yīng)的異常實(shí)例。
import?pytest
def?test_zero_division():
????1?/?0
if?__name__?==?'__main__':
????pytest.main()
運(yùn)行結(jié)果:
==================================?FAILURES?===================================
_____________________________?test_zero_division?______________________________
????def?test_zero_division():
>???????1?/?0
E???????ZeroDivisionError:?division?by?zero
所以我們需要捕獲并斷言異常。
斷言場(chǎng)景:斷言拋出的異常是否符合預(yù)期。
預(yù)期結(jié)果:ZeroDivisionError: division by zero,其中ZeroDivisionError為錯(cuò)誤類型,division by zero為具體錯(cuò)誤值。
斷言方式: ?斷言異常的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()
代碼詳細(xì)說(shuō)明:
① 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作為異常信息實(shí)例,擁有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的值是元組,所以要轉(zhuǎn)成字符串。
以上
That‘s all 更多系列文章
敬請(qǐng)期待
ITester軟件測(cè)試小棧 往期內(nèi)容寵幸

想獲取更多最新干貨內(nèi)容 快來(lái)星標(biāo) 置頂 關(guān)注我 每周一、三、五 07:30見 
?后臺(tái)
?回復(fù)"資源"取干貨 回復(fù)"微信群"一起打怪升級(jí) 測(cè)試交流Q群:727998947
點(diǎn)亮一下在看,你更好看 
瀏覽
77

04
2020-08
今天距2021年149天
這是ITester軟件測(cè)試小棧第147次推文

點(diǎn)擊上方藍(lán)字“ITester軟件測(cè)試小棧“關(guān)注我,每周一、三、五早上?07:30準(zhǔn)時(shí)推送。
微信公眾號(hào)后臺(tái)回復(fù)“資源”、“測(cè)試工具包”領(lǐng)取測(cè)試資源,回復(fù)“微信群”一起進(jìn)群打怪。
本文4633字,閱讀約需12分鐘
在自動(dòng)化測(cè)試過(guò)程中,需要判斷預(yù)期結(jié)果和實(shí)際結(jié)果是否一致,這時(shí)需要使用到斷言。
什么是斷言呢?簡(jiǎn)單來(lái)說(shuō)就是實(shí)際結(jié)果和期望結(jié)果去對(duì)比。
斷言用法
在pytest中,使用assert進(jìn)行斷言,格式為:assert 表達(dá)式。
如果表達(dá)式返回結(jié)果為True,則斷言成功,否則斷言失敗。
常用斷言
unittest的三種斷言:
assertIn(expect,result)斷言包含(被包含的寫前面);
assertEqual(expect,result)斷言相等;
assertTure(條件)斷言是否為真。返回Ture或False;
Pytest里的斷言實(shí)際上就是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()
運(yùn)行結(jié)果如下:
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
異常斷言
在測(cè)試過(guò)程中,有時(shí)需要對(duì)特定異常進(jìn)行斷言,可以使用 pytest.raises 作為上下文管理器,當(dāng)拋出異常時(shí)可以獲取到對(duì)應(yīng)的異常實(shí)例。
import?pytest
def?test_zero_division():
????1?/?0
if?__name__?==?'__main__':
????pytest.main()
運(yùn)行結(jié)果:
==================================?FAILURES?===================================
_____________________________?test_zero_division?______________________________
????def?test_zero_division():
>???????1?/?0
E???????ZeroDivisionError:?division?by?zero
所以我們需要捕獲并斷言異常。
斷言場(chǎng)景:斷言拋出的異常是否符合預(yù)期。
預(yù)期結(jié)果:ZeroDivisionError: division by zero,其中ZeroDivisionError為錯(cuò)誤類型,division by zero為具體錯(cuò)誤值。
斷言方式: ?斷言異常的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()
代碼詳細(xì)說(shuō)明:
① 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作為異常信息實(shí)例,擁有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的值是元組,所以要轉(zhuǎn)成字符串。


測(cè)試交流Q群:727998947

