透析Python 項目測試全過程
對于一般新入手的開發(fā)人員,如果只想在Python 項目測試或添加新特性之前檢查包是否能夠在他自己的平臺上進(jìn)行工作,那么 test_suite 入口點是非常方便的,這也避免程序員多走的彎路。
本文討論先進(jìn)的測試框架如何提供健壯的應(yīng)用程序測試自動發(fā)現(xiàn),以及這如何替代過去維護(hù)的集中式測試列表。Python 編程社區(qū)非常重視單元測試和功能性測試。這種風(fēng)氣不但有助于確保組件和應(yīng)用程序最初的質(zhì)量,還促使程序員不斷調(diào)整和改進(jìn)代碼。
本文是討論現(xiàn)代 Python 測試框架的 三篇系列文章 的第二篇。本系列中的 ***篇文章 介紹了 zope.testing、py.test 和 nose,介紹它們?nèi)绾斡绊?Python 項目編寫和維護(hù)測試的方式。
本文介紹如何調(diào)用這三種框架、它們?nèi)绾卧陧椖恐邪l(fā)現(xiàn)測試以及如何選擇并運行測試。***一篇文章將討論如何通過各種報告特性讓測試支持更強大的技術(shù)。Python 測試的黑暗時代Python 項目測試曾經(jīng)是非常特殊化、個人化的活動。開發(fā)人員可能先在單獨的 Python 腳本中編寫每組測試。
然后,編寫一個名為 test_all.py 或 tests.py 的腳本,這個腳本導(dǎo)入并運行他的所有測試。但是,無論這個過程的自動化做得多么好,這種方式仍然是特殊化的:參與項目的每個開發(fā)人員都必須知道測試腳本放在哪里以及如何調(diào)用它們。
如果某個 Python 開發(fā)人員從事十幾個項目,他就必須記住十幾個測試命令。test_all.py(或項目采用的其他名稱)還可能手工導(dǎo)入所有其他測試,這可能導(dǎo)致風(fēng)險。如果這個集中的測試列表過時了(常常是由于開發(fā)人員添加了新的測試套件。
手工運行它,但是忘了把它添加到中心腳本中),那么在 Python 包投入生產(chǎn)之前的***一次測試就會遺漏許多測試。這種無政府狀態(tài)的另一個缺點是,它要求每個測試文件包含樣板代碼,從而能夠作為單獨的命令運行。如果查看 Python 項目測試或當(dāng)今的一些 Python 項目,會看到許多這樣的測試示例:
- # test_old.py - The old way of doing things
- import unittest
- class TruthTest(unittest.TestCase):
- def testTrue(self):
- assert True == 1
- def testFalse(self):
- assert False == 0
- if __name__ == '__main__':
- unittest.main()
本系列的 ***篇文章 已經(jīng)討論過基于 TestCase 類的測試在現(xiàn)代環(huán)境中為什么常常是不必要的。但是,現(xiàn)在注意***兩行:它們起什么作用?答案是,它們檢測什么時候從命令行單獨運行這個 test_old.py 腳本。
在這種情況下,它們運行一個 unittest 簡便函數(shù),這個函數(shù)在模塊中搜索測試并運行它們。它們使這個測試文件可以獨立于項目范圍的測試腳本單獨運行。顯然,在數(shù)十甚至數(shù)百個測試模塊中復(fù)制相同的代碼非常麻煩。
另一個不太明顯的缺點是這種做法不利于標(biāo)準(zhǔn)化。如果 test_main() 函數(shù)不夠完善,無法檢測出某個模塊的測試,那么這個模塊的行為可能與其他測試套件不匹配。因此,每個模塊在測試類的名稱、操作方式和運行方式方面稍有差異。
由于主流 Python 測試框架的出現(xiàn),上述的所有問題已經(jīng)解決了,而且每種框架解決這些問題的方式大致相同。首先,這三種測試框架都提供了從操作系統(tǒng)命令行運行測試的標(biāo)準(zhǔn)方法。這樣,每個 Python 項目測試就不再需要在代碼基中維護(hù)全局測試腳本。
zope.testing 包運行測試的機制是最特殊化的:因為 Zope 開發(fā)人員常常使用 buildout 設(shè)置他們的項目,常常通過 buildout.cfg 文件中的 zc.recipe.testrunner recipe 安裝測試腳本。但是,結(jié)果在不同的項目上相當(dāng)一致:在我遇到的每個 Zope 項目中,開發(fā) buildout 都會創(chuàng)建一個 ./bin/test 腳本,可以通過它調(diào)用項目的測試。
py.test 和 nose 項目的做法更意思。它們都提供一個命令行工具,所以每個項目完全不需要有自己的測試命令:
- # Run "py.test" on the project
- # in the current directory...
- $ py.test
- # Run "nose" on the project
- # in the current directory...
- $ nosetests
py.test 和 nosetests 工具甚至有幾個相同的命令行選項,比如 -v 選項在執(zhí)行測試時輸出測試的名稱??赡苓^不了多久,只要程序員熟悉這兩種工具,就能夠運行大多數(shù)公共 Python 包的測試
【編輯推薦】