Python中的斷言用起來(lái)非常簡(jiǎn)單,你可以在assert后面跟上任意判斷條件,如果斷言失敗則會(huì)拋出異常。
>>>assert1+1==2
>>>assertisinstance('Hello',str)
>>>assertisinstance('Hello',int)
Traceback(most recent calllast):
File"",line1,in
AssertionError
其實(shí)assert看上去不錯(cuò),然而用起來(lái)并不爽。就比如有人告訴你程序錯(cuò)了,但是不告訴哪里錯(cuò)了。很多時(shí)候這樣的assert還不如不寫,寫了我就想罵娘。直接拋一個(gè)異常來(lái)得更痛快一些。
改進(jìn)方案 #1
一個(gè)稍微改進(jìn)一丟丟的方案就是把必要的信息也放到assert語(yǔ)句后面,比如這樣。
>>>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è)試汪,有成千上萬(wàn)的測(cè)試案例需要做斷言做驗(yàn)證,相信你面對(duì)以上做法,心中一定有千萬(wàn)只那種馬奔騰而過(guò)。
改進(jìn)方案 #2
不管你是你是搞測(cè)試還是開(kāi)發(fā)的,想必聽(tīng)過(guò)不少測(cè)試框架。你猜到我要說(shuō)什么了吧?對(duì),不用測(cè)試框架里的斷言機(jī)制,你是不是灑。
py.test
py.test 是一個(gè)輕量級(jí)的測(cè)試框架,所以它壓根就沒(méi)寫自己的斷言系統(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語(yǔ)句。
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中的斷言可讀性很好,而且智能提示也很方便你通過(guò)IDE輕松完成各種斷言語(yǔ)句。
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 主頁(yè) 文檔上你會(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)在,我為毛要重新去造輪子?完全沒(méi)必要!
總結(jié)
斷言在軟件系統(tǒng)中有非常重要的作用,寫的好可以讓你的系統(tǒng)更穩(wěn)定,也可以讓你有更多真正面對(duì)對(duì)象的時(shí)間,而不是在調(diào)試代碼。
Python中默認(rèn)的斷言語(yǔ)句其實(shí)還有一個(gè)作用,如果你寫了一個(gè)類型相關(guān)的斷言,IDE會(huì)把這個(gè)對(duì)象當(dāng)成這種類型,這時(shí)候智能提示就有如神助。
要不要把內(nèi)置的斷言語(yǔ)句換成可讀性更好功能更強(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)單又方便。
所以說(shuō),項(xiàng)目經(jīng)驗(yàn)還是蠻重要的。怎么樣才能學(xué)好python學(xué)好python你需要一個(gè)良好的環(huán)境,一個(gè)優(yōu)質(zhì)的開(kāi)發(fā)交流群,群里都是那種相互幫助的人才是可以的,我有建立一個(gè)python學(xué)習(xí)交流群,在群里我們相互幫助,相互關(guān)心,相互分享內(nèi)容,這樣出問(wèn)題幫助你的人就比較多,群號(hào)是301,還有056,最后是051,這樣就可以找到大神聚合的群,如果你只愿意別人幫助你,不愿意分享或者幫助別人,那就請(qǐng)不要加了,你把你會(huì)的告訴別人這是一種分享。