Python中的斷言用起來非常簡(jiǎn)單,你可以在assert后面跟上任意判斷條件蚯姆,如果斷言失敗則會(huì)拋出異常。
>>>assert1+1==2
>>>assertisinstance('Hello',str)
>>>assertisinstance('Hello',int)
Traceback(most recent calllast):
File"",line1,in
AssertionError
其實(shí)assert看上去不錯(cuò),然而用起來并不爽。就比如有人告訴你程序錯(cuò)了畸悬,但是不告訴哪里錯(cuò)了。很多時(shí)候這樣的assert還不如不寫珊佣,寫了我就想罵娘蹋宦。直接拋一個(gè)異常來得更痛快一些。
改進(jìn)方案 #1
一個(gè)稍微改進(jìn)一丟丟的方案就是把必要的信息也放到assert語句后面咒锻,比如這樣冷冗。
>>>s="nothin is impossible."
>>>key="nothing"
>>>assertkeyins,"Key: '{}' is not in Target: '{}'".format(key,s)
Traceback(most recent calllast):
File"",line1,in
AssertionError:Key:'nothing'isnotinTarget:'nothin is impossible.'
看上去還行吧,但是其實(shí)寫的很蛋疼惑艇。假如你是一名測(cè)試汪蒿辙,有成千上萬的測(cè)試案例需要做斷言做驗(yàn)證,相信你面對(duì)以上做法,心中一定有千萬只那種馬奔騰而過须板。
改進(jìn)方案 #2
不管你是你是搞測(cè)試還是開發(fā)的碰镜,想必聽過不少測(cè)試框架。你猜到我要說什么了吧习瑰?對(duì),不用測(cè)試框架里的斷言機(jī)制秽荤,你是不是灑甜奄。
py.test
py.test 是一個(gè)輕量級(jí)的測(cè)試框架,所以它壓根就沒寫自己的斷言系統(tǒng)窃款,但是它對(duì)Python自帶的斷言做了強(qiáng)化處理课兄,如果斷言失敗,那么框架本身會(huì)盡可能多地提供斷言失敗的原因晨继。那么也就意味著烟阐,用py.test實(shí)現(xiàn)測(cè)試,你一行代碼都不用改紊扬。
import pytest
def test_case():
expected="Hello"
actual="hello"
assertexpected==actual
if__name__=='__main__':
pytest.main()
"""
================================== FAILURES ===================================
__________________________________ test_case __________________________________
def test_case():
expected = "Hello"
actual = "hello"
>?????? assert expected == actual
E?????? assert 'Hello' == 'hello'
E???????? - Hello
E???????? ? ^
E???????? + hello
E???????? ? ^
assertion_in_python.py:7: AssertionError
========================== 1 failed in 0.05 seconds ===========================
""""
unittest
Python自帶的unittest單元測(cè)試框架就有了自己的斷言方法self.assertXXX()蜒茄,而且不推薦使用assert XXX語句。
importunittest
classTestStringMethods(unittest.TestCase):
deftest_upper(self):
self.assertEqual('foo'.upper(),'FoO')
if__name__=='__main__':
unittest.main()
"""
Failure
Expected :'FOO'
Actual?? :'FoO'
Traceback (most recent call last):
File "assertion_in_python.py", line 6, in test_upper
self.assertEqual('foo'.upper(), 'FoO')
AssertionError: 'FOO' != 'FoO'
"""
ptest
我非常喜歡ptest餐屎,感謝Karl大神寫了這么一個(gè)測(cè)試框架檀葛。ptest中的斷言可讀性很好,而且智能提示也很方便你通過IDE輕松完成各種斷言語句腹缩。
fromptest.decoratorimport*
fromptest.assertionimport*
@TestClass()
classTestCases:
@Test()
deftest1(self):
actual='foo'
expected='bar'
assert_that(expected).is_equal_to(actual)
"""
Start to run following 1 tests:
------------------------------
...
[demo.assertion_in_python.TestCases.test1@Test] Failed with following message:
...
AssertionError: Unexpectedly that the str is not equal to str .
"""
改進(jìn)方案 #3
不僅僅是你和我對(duì)Python中的斷言表示不滿足屿聋,所以大家都爭(zhēng)相發(fā)明自己的assert包。在這里我強(qiáng)烈推薦assertpy 這個(gè)包藏鹊,它異常強(qiáng)大而且好評(píng)如潮润讥。
pip install assertpy
看例子:
fromassertpyimportassert_that
deftest_something():
assert_that(1+2).is_equal_to(3)
assert_that('foobar')\
.is_length(6)\
.starts_with('foo')\
.ends_with('bar')
assert_that(['a','b','c'])\
.contains('a')\
.does_not_contain('x')
從它的github 主頁 文檔上你會(huì)發(fā)現(xiàn)它支持了幾乎你能想到的所有測(cè)試場(chǎng)景,包括但不限于以下列表盘寡。
Strings
Numbers
Lists
Tuples
Dicts
Sets
Booleans
Dates
Files
Objects
而且它的斷言信息簡(jiǎn)潔明了楚殿,不多不少。
Expectedto be oflength<4>,butwas<3>.
Expectedto be empty string,but wasnot.
Expected,but wasnot.
Expectedto contain onlydigits,but didnot.
Expected<123>to contain only alphabeticchars,but didnot.
Expectedto contain only uppercasechars,but didnot.
Expectedto contain only lowercasechars,but didnot.
Expectedto be equalto,but wasnot.
Expectedto benotequalto,butwas.
Expectedto becase-insensitive equalto,but wasnot.
在發(fā)現(xiàn)assertpy之前我也想寫一個(gè)類似的包宴抚,盡可能通用一些勒魔。但是現(xiàn)在,我為毛要重新去造輪子菇曲?完全沒必要冠绢!
總結(jié)
斷言在軟件系統(tǒng)中有非常重要的作用,寫的好可以讓你的系統(tǒng)更穩(wěn)定常潮,也可以讓你有更多真正面對(duì)對(duì)象的時(shí)間弟胀,而不是在調(diào)試代碼。
Python中默認(rèn)的斷言語句其實(shí)還有一個(gè)作用,如果你寫了一個(gè)類型相關(guān)的斷言孵户,IDE會(huì)把這個(gè)對(duì)象當(dāng)成這種類型萧朝,這時(shí)候智能提示就有如神助。
要不要把內(nèi)置的斷言語句換成可讀性更好功能更強(qiáng)大的第三方斷言夏哭,完全取決于實(shí)際情況检柬。比如你真的需要驗(yàn)證某個(gè)東西并且很關(guān)心驗(yàn)證結(jié)果,那么必須不能用簡(jiǎn)單的assert竖配;如果你只是擔(dān)心某個(gè)點(diǎn)可能有坑或者讓IDE認(rèn)識(shí)某個(gè)對(duì)象何址,用內(nèi)置的assert既簡(jiǎn)單又方便。
所以說进胯,項(xiàng)目經(jīng)驗(yàn)還是蠻重要的用爪。怎么樣才能學(xué)好python學(xué)好python你需要一個(gè)良好的環(huán)境,一個(gè)優(yōu)質(zhì)的開發(fā)交流群胁镐,群里都是那種相互幫助的人才是可以的偎血,我有建立一個(gè)python學(xué)習(xí)交流群,在群里我們相互幫助盯漂,相互關(guān)心颇玷,相互分享內(nèi)容,這樣出問題幫助你的人就比較多宠能,群號(hào)是301亚隙,還有056,最后是051违崇,這樣就可以找到大神聚合的群阿弃,如果你只愿意別人幫助你,不愿意分享或者幫助別人羞延,那就請(qǐng)不要加了渣淳,你把你會(huì)的告訴別人這是一種分享。