立志做國内自動化/AI測試領域最好的原創公衆号。歡迎微信關注公号"測試不将就"(ID: awesometest),更多原創文章在路上。我們的口号是:“插上自動化/AI的翅膀,軟體測試也能高大上”,同時會釋出關于Python開發, 持續內建等精彩文章。
作者:資深碼農/技術寫作者,歡迎添加作者微信(slxiaozju)交流。
PART I: 前言
在進行Python程式單元測試時,測試架構的選型是一個首要的問題。面對衆多Python單元測試架構,我應該選擇哪一個?
本文将探讨這個問題。文章的結構如下。首先,介紹單元測試,架構以及測試架構的基本概念;接着,介紹三種最流行的Python單元測試架構,分别是unittest, nose和pytest;然後,介紹作者關于Python單元測試架構選型的思考和心得;最後,總結全文。
PART 2: 基本概念
在介紹具體的Python單元測試架構之前,我們先來回顧一些基本概念。
什麼是單元測試?
單元測試是軟體測試的一種類型。顧名思義,單元測試就是測試的對象是程式中的最小單元的測試。程式的最小單元可以是一個函數,一個類,也可以是函數的組合,類的組合。
單元測試是軟體測試中最低級别的測試活動,與之相對的更進階别的測試有子產品測試,內建系統和系統測試等。單元測試一般由軟體開發者而不是獨立的測試工程師完成。另外,單元測試有一個隐含的性質,那就是單元測試天然就是自動化的,單元測試屬于自動化測試。
什麼是架構?
首先,架構是一個“架子”。這個架子能夠完成領域内基礎的、重要的功能。基于這個已有的架子,我們可以将重心放在面向業務的開發上。
其次,架構也是一個“框框”。“框框”為我們設定了有形和無形的限制。所謂有形的限制,就是我們的開發工作需要符合架構的定義、與架構相容。所謂無形的限制,就是我們的開發工作需要承受架構的缺點和不足(畢竟,沒有十全十美的架構)。
什麼是測試架構?
我們知道,軟體測試分為手工測試和自動化測試。需要注意的是,一般隻有自動化測試才有架構的概念。(自動化)測試架構,需要提供自動化測試用例編寫、自動化測試用例執行、自動化測試報告生成等基礎功能。
有了測試架構,我們隻需要完成和業務高度相關的測試用例設計和實作即可。另外,架構會為我們處理好複雜度與擴充性的問題,我們無需為此操心。
有了這些概念作為支撐,我們就很容易了解什麼是Python單元測試架構了。所謂Python單元測試架構,就是面向Python程式設計語言,服務于Python單元測試的自動化測試架構。
PART 3:主流架構
Python單元測試架構有很多,我們介紹最流行的三種。
1,unittest
unittest是Python标準庫中自帶的單元測試架構。unittest有時候也被稱為PyUnit。就像JUnit是Java語言的标準單元測試架構一樣,unittest(PyUnit)則是Python語言的标準單元測試架構。
unittest支援自動化測試,測試用例的初始化和關閉,測試用例的聚合等功能。unittest有一個很重要的特性:它通過類(class)的方式,将測試用例組織在一起。
一個簡單的示例如下:
importunittest
class TestStringMethods(unittest.TestCase):
def test_upper(self):
self.assertEqual('foo'.upper(), 'FOO')
if__name__=='__main__':
unittest.main()
執行結果:
...
--------------------- Ran1 tests in 0.000s OK
需要注意的是,unittest有一個關聯子產品unittest2。但是unittest2僅适用于Python 2.4-2.6。這是因為,從Python 2.7開始,unittest增加一些新的特性。為了在老的版本Python 2.4-2.6支援這些特性,提供了unittest2這個庫。對于Python 2.7及之後的版本,unittest是唯一的。
2,nose
nose是Python的一個第三方單元測試架構。這意味着,如果要使用nose,需要先顯式安裝它:
pip install nose
與unittest不同的是,nose的測試用例并不限制于類。任何函數和類,隻要名稱比對一定的條件(例如,以test開頭或以test結尾等),都會被自動識别為測試用例;并且,為了相容unittest, 所有的基于unitest編寫的測試用例,也會被nose自動識别為。
一個簡單的nose單元測試示例如下:
import nose
def test_example ():
pass
if __name__ == '__main__':
nose.runmodule()
執行結果:
... --------------------- Ran1 tests in 0.000s OK
需要注意的是,nose已經進入維護模式,從github (https://github.com/nose-devs/
nose/commits/master)上可以看到,nose最近的一次代碼送出還是在2016年5月4日。繼承nose的是nose2,但要注意的是,nose2并不支援nose的全部功能,它們的差別可以參見:
https://nose2.readthedocs.io/en/latest/differences.html。
nose2的主要目的是擴充Python的标準單元測試庫unittest,是以它的定位是“帶插件的unittest”。nose2提供的插件,例如測試用例加載器,覆寫度報告生成器,并行測試等内置插件和第三方插件,讓單元測試變得更加完善。
3,pytest
pytest是Python另一個第三方單元測試庫。它的目的是讓單元測試變得更容易,并且也能擴充到支援應用層面複雜的功能測試。
pytest的特性有:
1)支援用簡單的assert語句實作豐富的斷言,無需複雜的self.assert*函數
2)自動識别測試子產品和測試函數
3)相容unittest和nose測試集
4)支援Python3和PyPy3
5)豐富的插件生态,已有300多個各式各樣的插件,和活躍的社群
pytest一個簡單的示例如下:
def inc(x):
return x +1
def test_answer():
assert inc(3) == 5
執行結果如下:
$ pytest
============================= test session starts=============================
collected 1 items
test_sample.py F
================================== FAILURES===================================
_________________________________ test_answer_________________________________
def test_answer():
> assert inc(3)== 5
E assert 4 == 5
E + where 4 = inc(3)
test_sample.py:5: AssertionError
========================== 1 failed in 0.04 seconds===========================
PART 4: 架構選型
(1) 從入門難度看,pytest/nose優于unittest
雖然unittest是Python自帶的單元測試庫,但是要上手unittest是有難度的,既需要了解testrunner, testsuite, testcase等基本概念,還需要熟悉面向對象程式設計。而pytest/nose則為我們隐藏了這些細節,因而能夠降低入門單元測試的難度。
對于有一定Python程式設計基礎的人來說,unittest是适合的;對于Python程式設計基礎較弱的人來說,nose和pytest則比較适合。另外,對比nose和pytest,一般認為pytest的入門難度更低。
(2) 同為第三方庫,pytest的生态優于nose/nose2
我們知道,nose已經進入了維護模式,取代者是nose2。相比nose2,pytest的生态無疑更具優勢,社群的活躍度也更高。
例如,在github上,截止現在,pytest的STAR數量是4229,而nose2的STAR數量是558;pytest的送出數量是10384,而nose2的送出數量是917。最重要的,pytest的插件數量是300多個,遠高于nose2的20多個插件。
如果隻需要基本的插件,那麼nose和pytest都是适合的;如果追求單元測試更豐富的插件,那麼pytest更适合。
(3) 從通用性角度看,pytest優于unittest和nose
與unittest/nose不同的是,pytest不僅能用于單元測試,還能用于更進階别的,面向應用的功能測試。是以,如果需要進行更進階别的測試,則适合采用Pytest。
PART 5: 總結
在進行Python程式測試時,測試架構的選型是一個重要的問題。衆多測試架構之間,我到底應該選擇哪一個?
本文對比了unittest,nose和pytest這三種最流行的Python單元測試測試,指出了各個架構的特點,指出了在不同場景和不同需求下,哪一種架構更适合。當然,本文的分析還是比較初步的,在實際中,還需要結合具體情況深入分析後再做決定。
立志做國内自動化/AI測試領域最好的原創公衆号。歡迎微信關注公号"測試不将就"(ID: awesometest),更多原創文章在路上。我們的口号是:“插上自動化/AI的翅膀,軟體測試也能高大上”,同時會釋出關于Python開發, 持續內建等精彩文章。
作者:資深碼農/技術寫作者,歡迎添加作者微信(slxiaozju)交流