從開源項目看 Python 單元測試

來源:互聯網
上載者:User

從開源項目看 Python 單元測試

我覺得以前在我開發程式的時候,除了文檔,可能單元測試是另外一個讓我希望別人都寫,但是自己又一點都不想寫的東西。但是,隨著開發程式的增多,以及自己對 Bug 的修改的增多,我發現,UT 在很大程度上是對我有利的,雖然帶來的結果就是可能我的 Dev 時間會增加 20-40% 左右,但是,相比較於一段時間之後突然冒出來一個 Bug,讓你摸不著頭腦;或者說突然一個接一個的 Bug 在你轉測試之後提過來,寫 UT 的幸福感和自豪感明顯是更高的。

就我目前而言,我認為寫單元測試有這麼幾個好處:

  1. 協助減小代碼的耦合度,這樣你才能更容易得編寫 UT
  2. 理清代碼的模組依賴,這樣你才能在 UT 中知道哪些東西要 Mock,哪些東西要 Stub
  3. 保持介面的乾淨和明朗,UT 就是針對介面編程,Input 和 Ouput 都需要明確
  4. UT 是一個自詮釋的文檔,別人可以通過你的 UT 來學習你的介面使用方式

這裡我需要提出一點的就是,一般而言,我很難做到 Test First,也就是所謂的先完成 UT 代碼的編寫,然後再寫實現代碼。當然,這不是說不行,就以目前的經曆來說,這做法欠妥,一個很重要的原因是項目周期的把控,如果你 UT First,萬一後面你時間不夠實現 Logical Code 了怎麼辦?光有 UT 並不能讓你的整個 Project 跑起來。所以,一般來說,我經曆的大部分項目都是先 Run 起來,然後再通過 UT 保證目前的功能是正常的,並且可以保證在以後的維護和更新中,功能的正確性不會被破壞。

測試方法

學過完善的軟體工程體系的同學都知道,軟體測試是軟體工程中非常重要的一環,甚至於可以說對於一個 Project,測試人員的參與度比 Developer 的高多了,我剛畢業那會,測試人員的參與度可以說是貫穿了全流程,從需求的提出到驗收發布,這整個流程都有測試人員的參與,而 Developer,可能參與到"轉測試"環境就差不多完了,所以測試工程也是一項非常複雜的學科。

測試覆蓋

因為測試非常複雜,所以也是有很多方法論和實踐的。就拿 UT 來說,對於代碼我們可以有幾個不同的測試角度。例如覆蓋角度來說,我們就有語句覆蓋,分支覆蓋,條件覆蓋,路徑覆蓋和迴圈覆蓋;測試內容來說,我們又會分模組測試,資料結構測試,路徑測試,錯誤處理測試和邊界測試等等。對於這麼多測試,其實我發現大部分開源項目都沒有很嚴格得遵守這些理論,因為可能說隨便一條理論在實踐中都能讓人抓狂。

其實在我見過的幾個流行的開源項目中,基本上都是以語句覆蓋為目標進行的,並且並不能達到 100%,所以更多得是以主要功能是正常的為目標進行 UT 測試的。以下是部分開源項目的測試結果:

除此之外,對於 UT 的增加是在 issue 的基礎上建立的,也就說當有使用者提了一個 issue 之後,Maintener 覺得這個 issue 是個問題,並且會影響到我這個項目,那麼就會開發開發相應的 patch fix 它,並且補上 UT,這種情況也是比較常見,這樣的話,漸漸地 UT 的覆蓋率也就慢慢上去了。

測試方法

在測試中,我們的代碼可能會有很多依賴,例如模組依賴,組件依賴等等,為瞭解決這些依賴,我們總要有一些方法來處理,這裡就有兩項經常使用的技術:Stub 和 Mock。

我以前喜歡說講一個對象 Mock 掉,意思就是講一個對象用自訂的類比類替換掉,從而讓我們可以自訂類的行為和輸出,但是,我發現這其實在測試中是 Stub,所謂的 Stub 就是類比測試代碼調用的模組和組件,從而自訂被調用後的行為和輸出;而相比之下,Mock 的功能是驗證模板或者組件有沒有被調用,很常見的例子就是郵件發送服務有沒有被調用,有沒有輸出日誌內容等等。關於 Stub 和 Mock 更多的內容介紹我推薦 Martin Folwer 的這篇文章:Mocks Aren't Stubs。

測試載入器

在 Python 中,自身就帶了類 XUnit 的 unittest 架構,使用也很簡單,例如下面就是一個很簡單的測試案例:

其實使用起來已經很簡單了,但是 Python 的小夥伴還是嫌他又囉嗦又慢,所以你會發現 pytest 這個庫很受歡迎。

pytest

pytest 作為一個單元測試架構,使用方法有多種,既可以和 python 內建的 unittest 類似,又可以很簡單得就一個函數來寫 UT;不僅開發效率會更高,而且執行效率也可以更高,其他優點就不囉嗦介紹了,官網裡面都羅列了:pytest。

至於有多簡單方便,你將下面這段代碼儲存到 test_sample.py 檔案中,然後在對應的目錄路徑下執行 pytest 命令

執行之後你應該會發現:

對,你會發現,就這麼簡單得執行起來了。但是,很多同學還是不滿於此,因為很多 Python 項目不僅僅適應於一個版本的 Python,所以就會有多一個 Python 版本的測試(Python 的又一坑,2.6/2.7/3.x/3.5 不相容)。

tox

為了滿足一個 Python 項目可以在多個 Python 版本中可以正常運行,很多人會使用 tox 進行不同環境下的相容性測試,所以 tox 的功能就是環境管理和測試回合。關於 tox 的更多功能使用和細則可以參考一下 tox 官網:Tox。

tox 一般都會有一個 tox.ini 檔案,例如一個簡單的例子:

然後執行 tox 命令列工具就可以了,它就會找你機器上的各種環境,然後測試起來,最後的結果就有點類似於:

小結

單元測試是一種習慣,也是一種責任。通過單元測試,我們可以告訴別人My Code是 Work 的,同時也給別人一種信任感,可以讓別人相信你寫的代碼。同時,編寫單元測試也是一項比較繁瑣的事情,我們要處理依賴,考慮 Test Case,但是,這些過程都可以協助我們更好得思考我們的項目和軟體,從而讓軟體的結構和代碼的品質提升一個台階。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.