unittest --- 單元測試框架
源代碼:https://github.com/python/cpython/tree/3.9/Lib/unittest/_init_.py
unittest 單元測試框架是受到Junit的啟發(fā),與其他語言中的主流單元測試框架有著相似的風(fēng)格困肩。其支持測試自動化,配置共享和關(guān)機代碼測試崩溪。支持將測試樣例聚合到測試集中捶索,并將測試與報告框架獨立陈症。
為了實現(xiàn)這些逛薇,unittest通過面向?qū)ο蟮姆绞街С至艘恍┲匾母拍睢?/p>
test fixture
test fixture表示為了開展一項或多項測試所需要進行的準備工作狼犯,以及所有相關(guān)的清理操作。舉個例子窃植,這可能包含創(chuàng)建臨時或代理的數(shù)據(jù)庫帝蒿,目錄,再或者啟動一個服務(wù)器進程巷怜。test case
一個test case是一個獨立的測試單元葛超。它檢查輸入特定的數(shù)據(jù)時的響應(yīng)。 unittest提供一個基類:TestCase ,用于新建測試用例延塑。test suite
test suite是一系列的測試用例绣张,或測試套件,或兩者皆有关带。它用于歸檔需要一起執(zhí)行的測試侥涵。test runner
test runner 是一個用于執(zhí)行和輸出測試結(jié)果的組件。這個云運行可能使用圖形接口宋雏,文本接口芜飘,或返回一個特定的值表示運行測試的結(jié)果。
基本實例
unittest模塊提供了一系列創(chuàng)建和運行測試的工具磨总。這一段演示了這些工具的一小部分嗦明,但也足以滿足大部分用戶的需求。
這是一段剪短的代碼舍败,來測試三種字符串方法:
import unittest
class TestStringMethods(unittest.TestCase):
def test_upper(self):
self.assertEqual('foo'.upper(), 'FOO')
def test_isupper(self):
self.assertTrue('FOO'.isupper())
self.assertFalse('Foo'.isupper())
def test_split(self):
s = 'hello world'
self.assertRqual(s.split(), ['Hello', 'world'])
# check that s.split fails when the separator is not a string
with self.ssertRaises(TypeError):
s.split(2)
if __name__ == '__main__':
unittest.main()
集成unittest.TestCase 就創(chuàng)建了一個測試用例招狸。上述三個獨立的測試時三個類方法,這些方法的命名都以test
開頭邻薯。 這個命名約定告訴test runner類的哪些方法表示測試。
每個測試的用例是:調(diào)用assertEqual()
來檢查預(yù)期的輸出乘凸; 調(diào)用assertTrue()
或assertFalse()
來驗證一個條件厕诡;調(diào)用assertRaises()
來驗證跑出了一個特定的異常。使用這些方法而不是assert
語句是為了讓test runner 能聚合所有的測試結(jié)果并產(chǎn)生結(jié)果報告营勤。
通過setUp()
和tearDown()
方法灵嫌,可以設(shè)置測試開始前與完成后需要執(zhí)行的指令。
最后的代碼中演示了運行測試的一個簡單的方法葛作。unittest.main()
提供了一個測試腳本的命令行接口寿羞。當在命令行運行該測試腳本,上文的腳本生成如以下格式的輸出:
# python script.py
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK
在調(diào)用測試腳本時添加-v
參數(shù)使unittest.main()
顯示更為詳細的信息赂蠢,生成如以下形式的輸入:
# python script.py -v
# python -m unittest -v script.py
test_isupper (__main__.TestStringMethods) ... ok
test_split (__main__.TestStringMethods) ... ok
test_upper (__main__.TestStringMethods) ... ok
----------------------------------------------------------------------
Ran 3 tests in 0.001s
OK
命令行界面
unitetst模塊可以通過命令行運行模塊绪穆,類和獨立測試方法的測試:
python -m unitest test_module1 test_module2
python -m unitest test_module.TestClass
python -m unitest testmodule.TestClass.test_method
你可以傳入模塊名,類或方法名或他們的任意組合。
同樣的玖院,測試模塊可以通過文件路徑指定:
python -m unittest tests/test_something.py
這樣就可以使用shell的文件名補全指定測試模塊菠红。所指定的文件仍需要可以被作為模塊導(dǎo)入。路徑通過去除'.py'难菌、把分隔符轉(zhuǎn)換為'.'轉(zhuǎn)換為模塊名试溯。若你需要執(zhí)行不能被作為模塊導(dǎo)入的測試文件,你需要直接執(zhí)行該測試文件郊酒。
在運行測試時遇绞,你可以通過添加-v
參數(shù)獲取更詳細(更多的冗余)的信息。
python -m unitest -v test module
當運行時不包含參數(shù)燎窘,開始測試發(fā)現(xiàn)
:
python -m unittest # 等價于 python -m unittest discover
用于獲取命令行選項列表:
python -m unittest -h
在3.2版本中更改:在早期版本中试读,只支持運行獨立的測試方法,而不支持模塊和類荠耽。
命令行選項
uniitest支持以下命令行選項:
-b, --buffer
在測試運行時钩骇,標準輸出流與標準錯誤流會被放入緩沖區(qū)。成功的測試的運行時輸出會被丟棄铝量;測試不通過時倘屹,測試運行中的輸出會正常顯示,錯誤會被加入到測試失敗信息慢叨。-c, --catch
當測試正在運行時纽匙, Control-C(即Ctrl+C)會等待當前測試完成,并在完成后報告已執(zhí)行的測試的結(jié)果拍谐。當再次按下Control-C時烛缔,引發(fā)平常的KeyboardInterrupt
異常。-f, --failfast
當出現(xiàn)第一個錯誤或者失敗時轩拨,停止運行測試践瓷。-k
只運行匹配模式或子串的測試方法和類⊥鋈兀可以多次使用這個選項晕翠,以便包含匹配子串的所有測試用例。
包含通配符(*)的模式使用fnmatch.fnmatchcase()
對測試名稱進行匹配砍濒。另外淋肾,該匹配是大小寫敏感的。
模式對testloader
導(dǎo)入的測試方法全名進行匹配爸邢。
例如樊卓,-k foo
可以匹配到foo_tests.SomeTest.test_something
和bar_tests.SomeTest.test_foo
,但是不能匹配到bar_tests.FooTest.test_something
杠河。--locals
在回溯中顯示局部變量碌尔。
3.2新版本功能:添加命令行選項 -b
,-c
和-f
浇辜。
3.5新版本功能:添加命令行選項 --locals
。
3.7新版本功能:添加命令行選項 -k
七扰。
測試
3.2新版本功能
unittest 支持簡單的測試發(fā)現(xiàn)奢赂。為了與測試發(fā)現(xiàn)兼容,所有測試文件必須是可從項目鼎城目錄導(dǎo)入的模塊
或者包
(包括名稱空間包
)(這意味著他們的文件名必須是有效的標識符)颈走。
Test discovery已經(jīng)在TestLoader.discover()
中實現(xiàn)膳灶, 但也可以從命令行中使用×⒂桑基本的命令行用法是:
cd project_directory
python -m unittest discover
筆記:方便起見轧钓,python -m unittest 等效于 python -m unittest discover . 如果你需要向test discover 傳入?yún)?shù),必須顯式地使用discover 子命令 |
---|
discover 有一下選項:
-v, --verbose
更詳細地輸出結(jié)果锐膜。-s, --start-directory directory
開始進行搜索的目錄(默認值為當前目錄.
)-p, --pattern pattern
用于匹配測試文件的模式(默認為test*.py
)-t, --top-level-directory directory
指定項目的最上層目錄(通常為開始時坐在目錄)
-s
毕箍,-p
和-t
選項可以按順序作為位置參數(shù)傳入。以下兩條命令是等價的
python -m unittest discover -s project_directory -p "*_test.py"
python -m unittest discover project_directory "*_test.py"
正如可以傳入路徑那樣道盏,傳入一個包名作為起始目錄也是可行的而柑,如myproject.subprockage.test
。你提供的包名會被導(dǎo)入荷逞,它在文件系統(tǒng)中的位置會被作為起始目錄媒咳。
警告: 測試發(fā)現(xiàn)通過導(dǎo)入測試對測試進行加載。在找到所有你指定的開始目錄下的所有測試文件后种远,它把路徑轉(zhuǎn)換為包名并進行導(dǎo)入涩澡。如foo/bar/baz.py
會被導(dǎo)入為foo.bar.baz
。
如果你有一個全局安裝的包坠敷,并嘗試對這個包的副本進行測試發(fā)現(xiàn)妙同。可能會從錯誤的地方開始導(dǎo)入膝迎。如果出現(xiàn)這種情況粥帚,測試會輸出警告并退出。
如果你使用包名而不是路徑作為開始目錄弄抬,搜索時假定它導(dǎo)入的是你想要的目錄茎辐,所以你不會收到警告。
在3.4版本更改:Test discovery support namespace packages
for start directory. Note that you need to the top level directory too.(e.g. python -m unittest discover -s root/namespace -t root
).