透析Python 項目測試全過程
對于一般新入手的開發人員,如果只想在Python 項目測試或添加新特性之前檢查包是否能夠在他自己的平臺上進行工作,那么 test_suite 入口點是非常方便的,這也避免程序員多走的彎路。
本文討論先進的測試框架如何提供健壯的應用程序測試自動發現,以及這如何替代過去維護的集中式測試列表。Python 編程社區非常重視單元測試和功能性測試。這種風氣不但有助于確保組件和應用程序最初的質量,還促使程序員不斷調整和改進代碼。
本文是討論現代 Python 測試框架的 三篇系列文章 的第二篇。本系列中的 ***篇文章 介紹了 zope.testing、py.test 和 nose,介紹它們如何影響 Python 項目編寫和維護測試的方式。
本文介紹如何調用這三種框架、它們如何在項目中發現測試以及如何選擇并運行測試。***一篇文章將討論如何通過各種報告特性讓測試支持更強大的技術。Python 測試的黑暗時代Python 項目測試曾經是非常特殊化、個人化的活動。開發人員可能先在單獨的 Python 腳本中編寫每組測試。
然后,編寫一個名為 test_all.py 或 tests.py 的腳本,這個腳本導入并運行他的所有測試。但是,無論這個過程的自動化做得多么好,這種方式仍然是特殊化的:參與項目的每個開發人員都必須知道測試腳本放在哪里以及如何調用它們。
如果某個 Python 開發人員從事十幾個項目,他就必須記住十幾個測試命令。test_all.py(或項目采用的其他名稱)還可能手工導入所有其他測試,這可能導致風險。如果這個集中的測試列表過時了(常常是由于開發人員添加了新的測試套件。
手工運行它,但是忘了把它添加到中心腳本中),那么在 Python 包投入生產之前的***一次測試就會遺漏許多測試。這種無政府狀態的另一個缺點是,它要求每個測試文件包含樣板代碼,從而能夠作為單獨的命令運行。如果查看 Python 項目測試或當今的一些 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()
本系列的 ***篇文章 已經討論過基于 TestCase 類的測試在現代環境中為什么常常是不必要的。但是,現在注意***兩行:它們起什么作用?答案是,它們檢測什么時候從命令行單獨運行這個 test_old.py 腳本。
在這種情況下,它們運行一個 unittest 簡便函數,這個函數在模塊中搜索測試并運行它們。它們使這個測試文件可以獨立于項目范圍的測試腳本單獨運行。顯然,在數十甚至數百個測試模塊中復制相同的代碼非常麻煩。
另一個不太明顯的缺點是這種做法不利于標準化。如果 test_main() 函數不夠完善,無法檢測出某個模塊的測試,那么這個模塊的行為可能與其他測試套件不匹配。因此,每個模塊在測試類的名稱、操作方式和運行方式方面稍有差異。
由于主流 Python 測試框架的出現,上述的所有問題已經解決了,而且每種框架解決這些問題的方式大致相同。首先,這三種測試框架都提供了從操作系統命令行運行測試的標準方法。這樣,每個 Python 項目測試就不再需要在代碼基中維護全局測試腳本。
zope.testing 包運行測試的機制是最特殊化的:因為 Zope 開發人員常常使用 buildout 設置他們的項目,常常通過 buildout.cfg 文件中的 zc.recipe.testrunner recipe 安裝測試腳本。但是,結果在不同的項目上相當一致:在我遇到的每個 Zope 項目中,開發 buildout 都會創建一個 ./bin/test 腳本,可以通過它調用項目的測試。
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 選項在執行測試時輸出測試的名稱。可能過不了多久,只要程序員熟悉這兩種工具,就能夠運行大多數公共 Python 包的測試
【編輯推薦】