當前位置:
首頁 > 知識 > 用pytest測試python:夾具和覆蓋率

用pytest測試python:夾具和覆蓋率

用pytest測試python:夾具和覆蓋率

改善你的python測試

在我最近的兩篇文章中,我介紹了pytest,一個用來測試python代碼的library(詳見《用python的pytest測試你的代碼》第一部分和第二部分),Pytest已經非常流行,在很大程度上是因為它非常容易編寫測試並將這些測試集成到軟體開發程序中。我已經成為了它的鐵杆粉絲,主要是因為多年來我一直在說我應該更好地測試我的軟體,Pytest最終使它成為可能。

所以在本文中,我回顧了Pytest的兩個特性,在之前還沒有機會介紹它們:fixture和code coverage,這將(我希望)讓你相信Pytest是值得探索和進入到您的工作中的。

夾具:

當你寫測試的時候,很少只寫一兩個。相反,你會寫一個完整的「測試套件」,每個測試的目標是通過代碼檢查不同的路徑。通常這意味著你將有一些具有類似特性的測試,這些pytest可以用「參數化測試」處理。

但在其他情況下,情況會更複雜一些。您會想讓對象適用於所有的測試。這些對象可能包含要在測試之間共享的數據,或者它們可能涉及網路或文件系統。在測試世界中,這些通常被稱為「夾具」,它們採用各種不同的形式。

在Pytest中,可以使用Pytest.fixture裝飾器和函數定義的組合來定義fixture。例如,假設您有一個文件,該文件返回一個文件中的行列表,其中每一行都是相反的:

用pytest測試python:夾具和覆蓋率

請注意,為了避免換行符放在行首,請在反轉之前將其從字元串中刪除,然後在每個返回的字元串中添加一個" "。另外需要注意的是,雖然用生成器表達式而不是列表理解可能是個更好的想法,但我在這裡只是想讓事情相對簡單一點。

如果您要測試這個函數,您需要將它傳遞給一個類似文件的對象。在我上一篇文章中,我展示了如何使用Stringio對象來處理這樣的事情,這種情況依舊可以這樣。但是,您不必在測試文件中定義全局變數,而是可以創建一個夾具,在適當的時間為您的測試提供適當的對象。

下面看看Pytest是如何處理的:

用pytest測試python:夾具和覆蓋率

從表面上看,這看起來像是一個簡單的函數,它返回你稍後要用的值。在許多方面它與你用「簡單文件」的名稱定義全局變數所得到的類似。

同時,夾具的使用與全局變數不同。例如,如果你想讓你的一個測試中包含這個夾具。您可以在測試的參數列表中聲明它。然後在測試中就可以通過名稱訪問fixture。例如:

用pytest測試python:夾具和覆蓋率

但它會變得更好。你的fixture可能像數據一樣,因為你不必使用括弧來調用它。但它實際上是一個鉤子下的函數,這意味著它在每次引用該夾具調用測試時都會執行。說明與常規的舊數據相比,夾具可以進行計算和決策。

您還可以決定設備運行的頻率。例如,正如現在寫的,這個fixture將在提到它的每個測試中運行一次。在你想與列表或類似文件的結構進行比較的情況中,這非常好。但是如果你想設置一個對象,然後多次使用它而不重新創建它,該怎麼辦?您可以通過設置夾具的「範圍」來實現這一點。例如,如果將fixture的範圍設置為「module」,那麼它將在整個測試過程中可用,但只執行一次。可以通過將scope參數傳遞給@pytest.fixture 裝飾器來完成此操作:

用pytest測試python:夾具和覆蓋率

我應該說明給這個特定的fixture「module」範圍是一個壞主意, 因為第二個測試將會得到一個StringIO,它的位置指針(用file.tell測試)已經在末尾了。

這些夾具的工作方式與許多其他測試系統使用的傳統安裝/拆卸系統截然不同。但是,Pytest的人肯定讓我相信這是一種更好的方法。

但是等等,也許您可以看到這些設備中的「設置」功能在哪裡。「拆卸」功能在哪裡?答案既簡單又優雅。如果您的fixture使用「yield」而不是「return」,那麼pytest就會知道post-yield代碼用於分解對象和連接。是的,如果您的夾具具有「模塊」範圍,那麼pytest將等到範圍中的所有功能都完成執行後再將其拆下。

覆蓋率

這一切都很棒,但是如果您曾經做過任何測試,那麼您知道總是有一個問題,即您對代碼的測試有多徹底。畢竟,假設您已經編寫了五個函數,並且已經為所有函數編寫了測試。你能確定通過這些函數你已經測試了所有的可能路徑嗎?

例如,假設您有一個非常奇怪的函數,only_odd_mul,它只乘奇數:

用pytest測試python:夾具和覆蓋率

這是一個你可以運行該函數的測試

用pytest測試python:夾具和覆蓋率

當然,測試通過了。它很管用!軟體太棒了!

哦,但是你可能已經注意到了,那不是一個很好的測試工作。有一些方法可以讓函數給出一個完全不同的結果(例如,引發一個異常),而測試沒有檢查這個結果。

也許在這個例子中很容易找到它,但是當軟體變得越來越大、越來越複雜時,就不那麼容易看到它了。在您想要「代碼覆蓋率」的地方,檢查您的測試是否運行了所有代碼。

現在,100%的代碼覆蓋率並不意味著您的代碼是完美的或者它沒有漏洞。但它確實讓您對代碼有更大的信心,而且它至少運行過一次。

那麼,如何在pytest中包含代碼覆蓋率呢?答案是PyPI上有一個名為pytest-cov的包,您可以下載並安裝它。完成後,可以使用--cov選項調用pytest。如果你不再說其他的話,你將得到你的程序使用的python庫的每個部分的覆蓋率報告,因此我強烈建議您提供一個參數—cov來指定要測試的程序。並且,您應該指出報告應該寫入的目錄。在這種情況下,你會說:

用pytest測試python:夾具和覆蓋率

一旦你做到了這一點,你就需要把覆蓋率報告轉化為人類可讀的東西。我建議使用HTML,儘管其他輸出格式也是可以用的:

用pytest測試python:夾具和覆蓋率

這將創建一個名為htmlcov的根目錄。使用瀏覽器打開這個目錄中的index.html文件,您將得到一個基於Web的報告,其中顯示(紅色)您的程序仍然沒有覆蓋範圍。當然,在本例中,它顯示偶數路徑沒有被覆蓋。讓我們添加一個測試來執行此操作

用pytest測試python:夾具和覆蓋率

正如預期的那樣,覆蓋率現在已經上升到100%!這絕對是值得讚賞和慶祝的,但並不意味著你已經達到了最佳測試。你可以也應該考慮不同的混合論點,以及當你通過它們時會發生什麼。

總結

如果你還沒有從我關於Pytest的第三部分猜到,我已經被這個測試系統的設計方式所折服了。在談到測試時羞愧地絞盡腦汁數年之後,我開始將它融入到我的代碼中,包括在我的在線「每周Python練習」課程中。如果我能參加測試,你也能。雖然我還沒有嘗試pytest提供的所有內容,但是您現在應該對它是什麼以及如何開始使用它有了很好的了解。

資源

Pytest網站:http://pytest.org。

關於這個主題的有一本很棒的書是Brian Okken的用pytest測試python,由Pragmatic Programmers出版。他還有很多其他關於pytest和一般的代碼測試的資源,請訪問http://pythontesting.net。

布賴恩關於Pytest裝置的博客文章對任何想開始使用它們的人都是有益和有價值的。

英文原文:https://www.linuxjournal.com/content/python-testing-pytest-fixtures-and-coverage
譯者:遊騎兵

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python部落 的精彩文章:

Python是如何在微軟發展壯大的
Python之tworoutine

TAG:Python部落 |