輕輕松松實(shí)現(xiàn)進(jìn)行Python 測(cè)試模塊
為了更容易實(shí)現(xiàn)這種Python 測(cè)試模塊,避免多次復(fù)制并粘貼測(cè)試函數(shù)以及設(shè)置惟一的名稱(chēng),py.test 和 nose 都支持衍生測(cè)試,它實(shí)際上是一個(gè)迭代器,然后使用它的 yield 語(yǔ)句并提供調(diào)用參數(shù)。
但是,之后它們都會(huì)遇到相同的情況:它們必須檢查模塊列表,尋找開(kāi)發(fā)人員希望作為測(cè)試運(yùn)行的函數(shù)和類(lèi)。正如在前一篇文章中看到的,py.test 往往選擇單一標(biāo)準(zhǔn),期望使用它的所有項(xiàng)目都遵守這一標(biāo)準(zhǔn);而 nose 允許更豐富的定制,但是這會(huì)犧牲行為的可預(yù)測(cè)性。
對(duì)于測(cè)試發(fā)現(xiàn),也是如此:py.test 按照固定、不可變且可預(yù)測(cè)的規(guī)則檢測(cè)測(cè)試模塊中的測(cè)試,而 nose 采用靈活的可定制的規(guī)則。如果項(xiàng)目使用 nose 執(zhí)行測(cè)試,就先必須閱讀項(xiàng)目的 Python 測(cè)試模塊,了解 nose 是采用通常的測(cè)試檢測(cè)規(guī)則,還是采用這個(gè)項(xiàng)目特有的規(guī)則。
下面是 py.test 使用的過(guò)程:
- class Category(models.Model):
- id = models.AutoField('id', primary_key=True)
- name = models.CharField(maxlength=50)
- code = models.CharField(maxlength=50)
- parentCategory = models.ForeignKey('self', 'id', null=True)
- enable = models.BooleanField()
- def __str__(self):
- return self.name
- class Admin:
- list_display = ('id', 'name', 'code', 'parentCategory')
當(dāng) py.test 檢查 Python 測(cè)試模塊的內(nèi)部時(shí),它收集名稱(chēng)以 test_ 開(kāi)頭的每個(gè)函數(shù)和名稱(chēng)以 Test 開(kāi)頭的每個(gè)類(lèi)。無(wú)論類(lèi)是否繼承自 unittest.TestCase,它都會(huì)收集它們。測(cè)試函數(shù)直接運(yùn)行,但是對(duì)于測(cè)試類(lèi),還必須搜索方法。類(lèi)實(shí)例化之后,作為測(cè)試運(yùn)行名稱(chēng)以 test_ 開(kāi)頭的所有方法。
如果測(cè)試類(lèi)繼承自標(biāo)準(zhǔn)的 Python unittest.TestCase 類(lèi),py.test 框架會(huì)表現(xiàn)出一種古怪的行為:如果類(lèi)不包含 runTest() 方法,那么即使它包含幾個(gè) test_ 方法,py.test 也會(huì)拋出異常并失敗。但是,如果存在 runTest() 方法,py.test 會(huì)忽略它;這個(gè)方法必須存在,py.test 才能接受這個(gè)類(lèi),但是不會(huì)運(yùn)行這個(gè)方法,因?yàn)樗拿Q(chēng)不是以 test_ 開(kāi)頭的。
為了糾正這種行為,可以在項(xiàng)目的 conttest.py 文件中或使用 -p 命令行選項(xiàng)激活框架的 unittest 插件:這會(huì)讓 py.test 對(duì)其行為做三個(gè)更改。首先,不再只檢測(cè)名稱(chēng)以 Test 開(kāi)頭的類(lèi),還會(huì)檢測(cè)繼承自 unittest.TestCase 的其他類(lèi)。
第二,對(duì)于沒(méi)有提供 runTest() 方法的 TestCase 子類(lèi),py.test 不再報(bào)告異常。第三,在類(lèi)包含的測(cè)試之前和之后,以標(biāo)準(zhǔn)方式正確地運(yùn)行 TestCase 子類(lèi)中的所有 setUp() 和 tearDown() 方法。
盡管 nose 提供更強(qiáng)的定制能力,但是比較簡(jiǎn)單的測(cè)試發(fā)現(xiàn)過(guò)程如下:當(dāng) nose 檢查 Python 測(cè)試模塊的內(nèi)部時(shí),它采用在選擇測(cè)試模塊時(shí)使用的正則表達(dá)式。收集與這個(gè)正則表達(dá)式匹配的函數(shù)和類(lèi)。(在默認(rèn)情況下,尋找包含單詞 Test 或 test 的名稱(chēng),但是可以通過(guò)命令行或配置文件提供不同的正則表達(dá)式)。
當(dāng) nose 檢查測(cè)試類(lèi)的內(nèi)部時(shí),它運(yùn)行與同一正則表達(dá)式匹配的方法。無(wú)須特別指定,nose 總會(huì)檢測(cè) unittest.TestCase 的子類(lèi)并作為測(cè)試使用它們。但是,它會(huì)根據(jù)自己的正則表達(dá)式?jīng)Q定哪些方法是測(cè)試,而不使用標(biāo)準(zhǔn)的 unittest 模式 ^test。
【編輯推薦】