作者:HelloGitHub- Prodesire
文中涉及的示例代碼,已同步更新到?HelloGitHub-Team?倉庫
一、nose
nose 是一個第三方單元測試框架,它
完全兼容
unittest
,并且號稱是一個更好用的測試框架。
那么
nose
除了具備
unittest
的所有功能外,還具有哪些優(yōu)勢呢?
1.1 用例編寫
用例的編寫方式除了編寫繼承于 unittest.TestCase 的測試類外,還可以編寫成
沒有繼承的測試類
。比如,寫成如下形式也會被
nose
視作一個測試類:
from nose.tools import raises
class TestStringMethods:
def test_upper(self):
assert 'foo'.upper() == 'FOO'
def test_isupper(self):
assert 'FOO'.isupper()
assert not 'Foo'.isupper()
@raises(TypeError)
def test_split(self):
s = 'hello world'
assert s.split() == ['hello', 'world']
# check that s.split fails when the separator is not a string
s.split(2)
當(dāng)然,測試類并沒有繼承
unittest.TestCase
,將不能使用其內(nèi)置的各類
assertXXX
方法,進而導(dǎo)致用例出錯時無法獲得更加詳細的上下文信息。
此外,
nose
也支持
定義函數(shù)
來作為測試,這給許多簡單的測試場景帶來很大的便利:
def test_upper():
assert 'foo'.upper() == 'FOO'
1.2 用例發(fā)現(xiàn)和執(zhí)行
unittest
所支持的用例發(fā)現(xiàn)和執(zhí)行能力,
nose
均支持。
nose
支持用例自動(遞歸)發(fā)現(xiàn):
-
默認(rèn)發(fā)現(xiàn)當(dāng)前目錄下所有包含
test
的測試用例,但不包括以_
開頭的用例-
使用
nosetests
命令
-
使用
-
通過
-w
參數(shù)指定要自動發(fā)現(xiàn)的目錄,-m
參數(shù)指定用例文件、目錄、函數(shù)、類的名稱模式(正則匹配)-
nosetests -w project_directory "test_.+"
-
nose
也支持執(zhí)行指定用例:
-
指定測試模塊
-
nosetests test.module
-
-
指定測試類
-
nosetests a.test:TestCase
-
-
指定測試方法
-
nosetests another.test:TestCase.test_method
-
-
指定測試文件路徑
-
nosetests /path/to/test/file.py
-
-
指定測試文件路徑+測試類或測試函數(shù)(這是
unittest
所不支持的)-
nosetests /path/to/test/file.py:TestCase
-
nosetests /path/to/test/file.py:TestCase.test_method
-
nosetests /path/to/test/file.py:test_function
-
1.3 測試夾具(Fixtures)
nose
除了支持
unittest
所支持的定義測試前置和清理方式,還支持一種更為簡單的定義方式:
def setup_func():
"set up test fixtures"
def teardown_func():
"tear down test fixtures"
@with_setup(setup_func, teardown_func)
def test():
"test ..."
只需定義兩個函數(shù)用來表示前置和清理方法,通過 nose.tools.with_setup 裝飾器裝飾測試函數(shù),
nose
便會在執(zhí)行測試用例前后分別執(zhí)行所定義的前置和清理函數(shù)。
1.4 子測試/測試生成器
nose
除了支持
unittest
中的
TestCase.subTest
,還支持一種更為強大的子測試編寫方式,也就是
測試生成器(Test generators)
,通過
yield
實現(xiàn)。
在下面的示例中,定義一個
test_evens
測試函數(shù),里面生成了 5 個子測試
check_even
:
def test_evens():
for i in range(0, 5):
yield check_even, i, i*3
def check_even(n, nn):
assert n % 2 == 0 or nn % 2 == 0
此外,相較于
unittest.TestCase.subTest
多個子測試只能執(zhí)行一次測試前置和清理,
nose
的
測試生成器
可以支持每個子測試執(zhí)行一次測試前置和清理,如:
def test_generator():
# ...
yield func, arg, arg # ...
@with_setup(setup_func, teardown_func)
def func(arg):
assert something_about(arg)
1.5 插件體系
nose
相較于
unittest
一個最大的優(yōu)勢就是插件體系,自帶了很多有用的插件,也有豐富的第三方插件。這樣就能做更多的事情。
其中,自帶插件如下:
- AllModules:在所有模塊中收集用例
- Attrib:給用例打標(biāo)簽,并可運行含指定標(biāo)簽的用例
- Capture:捕獲用例的標(biāo)準(zhǔn)輸出
- Collect:快速收集用例
- Cover:統(tǒng)計代碼覆蓋率
- Debug:用例失敗時進入 pdb 調(diào)試
- Deprecated:標(biāo)記用例為棄用
- Doctests:運行文檔用例
- Failure Detail:斷言失敗時提供上下文信息
- Isolate:保護用例避免受一些副作用的影響
- Logcapture:捕捉 logging 輸出
- Multiprocess:并行執(zhí)行用例
- Prof:使用熱點分析器進行分析
- Skip:標(biāo)記用例為跳過
- Testid:為輸出的每個用例名稱添加測試 ID
- Xunit:以 xunit 格式輸出測試結(jié)果
而第三方庫則多種多樣,如用來生成 HTML 格式測試報告的 nose-htmloutput 等,這里不再一一列出。
得益于
nose
豐富的插件生態(tài),當(dāng)
nose
本身不能夠完全滿足我們的測試需求時,可以通過安裝插件,并在
nosetests
命令行指定該插件所提供的特定參數(shù)即可非常容易的使用插件。
相較于
unittest
,就能省去很多自己開發(fā)額外測試邏輯的精力。
二、nose2
nose2 是 nose 的繼任者。
它們的理念都是讓編寫和運行測試用例變得更容易。
它們有很多相同點,比如都兼容
unittest
,支持使用函數(shù)作為測試用例,支持子測試,擁有插件體系。但也有很多不同點,下面列出一些主要的不同點:
-
發(fā)現(xiàn)和載入測試
-
nose
自行實現(xiàn)了模塊加載功能,使用惰性方式加載測試模塊,加載一個執(zhí)行一個。 -
nose2
則借助內(nèi)建的 import () 導(dǎo)入模塊,并且是先全部載入,再執(zhí)行用例 -
nose2
并不支持nose
所支持的所有測試用例項目結(jié)構(gòu),比如如下用例文件的結(jié)構(gòu)在nose2
中就不受支持:
-
.
`-- tests
|-- more_tests
| `-- test.py
`-- test.py
-
測試前置和清理函數(shù)級別
-
nose
支持方法、類、模塊和包級別的測試前置和清理函數(shù) -
nose2
則不支持包級別的測試前置和清理函數(shù)
-
-
子測試
-
nose2
除了支持使用測試生成器來實現(xiàn)子測試外,還支持使用參數(shù)化測試(Parameterized tests)來實現(xiàn)子測試 -
nose2
除了像nose
一樣支持在測試函數(shù)和測試類(不繼承于unittest.TestCase
)中支持參數(shù)化測試和測試生成器外,還支持在繼承于unittest.TestCase
的測試類中使用
-
-
配置化
-
nose
期望所有插件的配置通過命令行參數(shù)進行配置 -
nose2
則通過配置文件進行控制,以最小化命令行參數(shù)讓人讀得更舒服
-
更多對比詳見 官方文檔。
三、小結(jié)
nose
和
nose2
在做到兼容
unittest
上就足以看出它們的目標(biāo),那便是要吸引原來那些使用
unittest
的用戶來使用它們。它們確實做到了!
nose
和
nose2
在用例編寫、測試夾具、子測試上做出改進,已經(jīng)能讓日常用例編寫工作變得更加容易和靈活。同時又引入插件體系,進一步將單元測試框架的能力提升了一個大大的臺階,這讓很多在基礎(chǔ)測試功能之上的高階功能的實現(xiàn)和共享成為了可能。也難怪有眾多開發(fā)者對它們情有獨鐘。
『講解開源項目系列』 ——讓對開源項目感興趣的人不再畏懼、讓開源項目的發(fā)起者不再孤單。跟著我們的文章,你會發(fā)現(xiàn)編程的樂趣、使用和發(fā)現(xiàn)參與開源項目如此簡單。歡迎留言聯(lián)系我們、加入我們,讓更多人愛上開源、貢獻開源~
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
