說說Python中的單元測試

單元測試是每種編程語言必學的課題,是保護開發者的強力護盾,每一個程序員都在時間容許的狀況下儘量多的寫單元測試,今天咱們不討論其必要性,只拋磚引玉聊一聊Python中的單元測試,本文僅表明我的見解。html

標準庫中難以忍受的 unittest

不少時候咱們老是認爲標準庫裏的帶的老是精挑細選的,若是不通過仔細打磨怎麼可能入選爲一等公民?但我要告訴你,Python標準庫裏的單元測試框架真不是最好的,隨着你對Python的熟悉你甚至會討厭這個unittest。python

Python一直崇尚簡單,優雅,高效地完成事情,當你寫完一個函數須要測試一下時,使用標準庫的unittest你須要作這些事情:程序員

  • 新建單元測試腳本
  • 導入單元測試依賴
  • 繼承單元測試類
  • 實現單元測試方法

具體的實例代碼以下:編程

import unittest

class IntegerArithmeticTestCase(unittest.TestCase):
    def testAdd(self):  # test method names begin with 'test'
        self.assertEqual((1 + 2), 3)
        self.assertEqual(0 + 1, 1)

if __name__ == '__main__':
    unittest.main()

看上去還行,不是很難。可是漸漸地你會吐槽:框架

  • 爲啥我要新建一個文件來寫測試?
  • 爲啥我要繼承一個類來寫測試?
  • 爲啥我要用unittest的Assertion來作斷言?
  • 爲啥unitunit的命名規則跟最佳實踐不同(mixedCase vs lower_case)?

要回答以上問題,答案只有一個:歷史緣由編程語言

好久好久之前,Python從Java借鑑了單元測試框架,包括命名規則和實現方式,一直沿用至今。不得不說這個框架沒啥毛病,該有的功能的都有,想作的事均可以作,可是用起來老是沒有爽的感受。ide

可是爲啥偉大的社區力量爲啥不把這個框架改的爽一點呢?沒辦法,我估計是爲了世界和平,你要知道Python這個龐然大物能健康地活着,後面有無數的類庫和方法在支撐,而這些類庫和方法都被單元測試保護着,若是修改了單元測試框架致使兼容性問題,就成了千古罪人。函數

見識簡潔的單元測試 pytest

Python中不少大牛其實都有嚴重的強迫症,追求簡潔和優雅的代碼。必然的,他們會拋棄標準庫中的unittest,使用或者發明本身心儀的單元測試框架。單元測試

正如其名,pytest是一個無數人推薦並在使用的Python單元測試框架,它使用起來很是簡單,只要你的方法名以 test 開頭就能夠,你能夠和須要測試的方法放在一塊兒,亦或是新建一個文件來專門整理單元測試,均可以。測試

def your_func():
  pass

def test_your_func():
  assert result

這樣的設計,就讓你寫單元測試成了順手拈來的事,假如你寫完了一個方法,想看看是否工做,在旁邊直接寫上一個test 開頭的方法,稍微準備一下數據就能夠驗證這個方法好很差用,豈不妙哉?

The idioms that pytest first introduced brought a change in the Python community because they made it possible for test suites to be written in a very compact style, or at least far more compact than was ever possible before. Pytest basically introduced the concept that Python tests should be plain Python functions instead of forcing developers to include their tests inside large test classes.

pytest 的發明讓你們意識到單元測試原來能夠這麼輕鬆和隨意,徹底沒有必要去繼承一個所謂的測試類或者按照複雜的規則才能開始書寫測試代碼,這也是我選擇和推薦它的理由。

固然,若是原來你的單元測試時unittest寫的話,pytest其實也是有可能兼容的的。

pytest 可以識別 unittest.TestCase 子類中的測試方法,若是文件名符合 test_*.py 或者 *_test.py 這樣的規則。

而且大多數 unittest 的功能都是被支持的,例如:

  • @unittest.skip 裝飾器;
  • setUp/tearDown;
  • setUpClass/tearDownClass();

我以爲,pytest有如下優勢:

  • 上手和使用足夠簡單
  • 當case失敗時信息足夠豐富和直觀,好比最後致使失敗的變量值會打印出來
  • 更豐富的運行參數
  • 可使用 assert 而不是 self.assert*
  • 被廣大IDE支持,社區資源豐富,用戶羣體大

讓單元測試和IDE無縫集成

畢竟咱們大多數人都不是神,不能用記事本寫代碼,IDE纔是咱們正確搬磚的方式。Python的首選IDE毋庸置疑就是 JetBrain 公司出品的 PyCharm

在PyCharm中只要你將默認的單元測試驅動改爲pytest,就能夠在任意test開頭的方法上經過右鍵菜單運行或者調試這個測試案例,很是方便。

更改PyCharm設置

右鍵菜單運行或者調試

若是你要運行當前文件的全部測試,只要從非test方法的其餘區域點擊右鍵便可。或者修改任意已經運行過的Configuration,添加你想要的參數,好比最多運行掛3個case就終止測試等等。

自定義Run Configuration

閒話和總結

單元測試的重要性你們都知道,大名鼎鼎的TDD應該都聽過,可是真正在實踐的少之又少。

究其緣由,一些人會說時間寫代碼都不夠,哪還有空寫單元測試。還有一些人就是嫌麻煩,在絕大多數編程語言裏單元測試都是須要單獨創建工程和目錄的,寫單元測試須要不少基礎工做要作,本覺得順手就能夠寫的單元測試,實際上須要費九牛二虎之力仍是在搭架子,太沮喪了。

Python的動態特性和靈活性讓它有可能讓單元測試超級簡單,有可能你認爲單元測試仍是不要和業務代碼混合在一塊兒的好,那就多辛苦一點新建一個文件導入要測試的方法,寫一個 test 開頭的方法便可,不算太難,不要找辭讓的理由。

最後個人我的觀點,單元測試其實還有一個很是重要的做用,就是替代函數文檔註釋。好比你寫了一個函數,使用起來可能有那麼一點複雜,你能夠給它寫一份清晰的註釋文檔,可是千言萬語不如給我來個例子,單元測試能夠充當例子的角色,什麼樣的輸入,輸出結果如何,一目瞭然。

但願從今天起,你的代碼也都有單元測試。

關於做者:

Toby Qin, Python 技術愛好者,目前從事測試開發相關工做,轉載請註明原文出處。

歡迎關注個人博客 https://betacat.online,你能夠到個人公衆號中去當吃瓜羣衆。

Betacat.online

相關文章
相關標籤/搜索