Pytest 實踐:Python 測試技術基礎知識

TesterHome小助手發表於2024-04-25

綜合編譯|TesterHome 社群
作者|Rafał Buczyński

一、簡介

在 Python 中建立、組織和執行測試。pytest 的獨特之處在於它的簡單性、可擴充套件性以及處理複雜測試需求的能力。它支援固定裝置、自動測試發現和豐富的外掛,以及其他顯著的功能,這使其成為從小型到大型應用程式的任何規模專案的可行選擇。

文件:http://docs.pytest.org/en/latest/contents.html#ttoc

第三方庫:https://pypi.org/search/?g=pytest

Github 地址:https://github.com/pytest-dev/pytest/

二. 安裝與配置

在深入使用 pytest 進行測試之前,正確設定至關重要。pytest 的安裝和配置過程非常簡單,使其成為各個級別的開發人員都可以使用的工具。

如何安裝 Pytest

Pytest 可以使用 pip 來安裝,pip 是 Python 的包安裝程式。建議在安裝 pytest 之前建立一個虛擬環境,因為這種做法有助於保持不同專案所需的依賴關係分離和組織。可以這樣做:

1.首先,在專案目錄中建立一個虛擬環境:

  1. 啟用虛擬環境,在 Windows 上使用:

在 Unix 或 MacOS 上使用:

3.啟用虛擬環境後,使用 pip 安裝 pytest:

配置測試環境

配置 pytest 輕而易舉。然而,瞭解一些基礎知識將幫助你從一開始就充分利用它。Pytest 需要知道在哪裡可以找到你的測試以及應該考慮什麼作為測試。

以下是一些基礎知識:

1.命名約定:預設情況下,pytest 會將任何字首為 test_ 或字尾為 test.py 的檔案視為測試檔案。同樣,這些檔案中任何以 test 為字首的函式都被視為測試函式。遵循這一命名約定將使你的測試井井有條,易於識別。

2.目錄結構:雖然 pytest 的目錄結構非常靈活,但在專案中通常會有一個專門的測試目錄,存放所有測試檔案。這樣可以將測試與實際程式碼分開,是一種很好的做法。

專案結構:

  1. 配置檔案:對於更高階的配置,pytest 支援名為 pytest.ini、pyproject.toml 或 tox.ini 的配置檔案。在該檔案中,你可以指定各種選項,如新增命令列引數、設定 python 路徑等。

pytest.ini 檔案示例:

在這個配置檔案中,我們指定了 pytest 的最低版本,新增了一些命令列選項,並將 pytest 指向測試目錄。

按照上述步驟,你將擁有一個組織有序、配置完備的測試環境,為你的 pytest 之旅做好準備。在隨後的章節中,當你深入研究 pytest 的特性和功能時,這個設定將為你提供良好的服務。

三、Pytest 基礎知識

使用 pytest 開始測試,首先要了解它的基本功能。下面的內容旨在提供一個基礎,你可以在此基礎上隨著你的進步構建更復雜的測試場景。這裡將介紹的三個主要方面包括:建立簡單的功能測試、利用斷言以及從命令列識別和執行測試。

建立簡單的功能測試

功能測試是一種黑盒測試,透過提供輸入並檢查輸出來測試應用程式的功能。Pytest 簡化了建立功能測試的過程。讓我們深入研究一個基本示例:

假設在名為 math_operations.py 的檔案中有一個函式 add:

要測試該 add 函式,請建立一個名為的新檔案 test_math_operations.py 並定義一個函式 test_add:

在此示例中,test_add 是一個簡單的功能測試,用於檢查 add 函式是否返回正確的輸出。

在 Pytest 中使用斷言

斷言是程式設計師在程式碼中假定為真的條件或布林表示式。Pytest 使斷言的使用變得輕鬆易讀。斷言語句用於在給定條件為真的情況下繼續執行。如果 assert 判斷為 false,pytest 將停止測試執行,報告失敗,並提供深入的回溯資訊。讓我們擴充套件一下前面的例子:

在這裡,我們新增了更多斷言來檢查 add 具有不同輸入的函式,確保其在這些場景中的行為符合預期。

從命令列識別並執行測試

Pytest 提供了用於執行測試的命令列介面。編寫測試後,執行它們就像在終端中執行單個命令一樣簡單。導航到包含測試檔案的目錄,然後執行以下命令:

Pytest 將自動發現當前目錄和子目錄中遵循測試檔案命名約定的所有檔案,然後執行它們包含的測試。

要進行更精細的控制,可以指定要執行的檔案、測試類甚至測試方法。例如,要只執行 test_math_operations.py 檔案中的 test_add 方法,可以執行:

這種命令列靈活性使您可以輕鬆執行單個測試、檔案中的所有測試或專案中的所有測試,隨著測試套件的增長,這會非常有幫助。

pytest 用於建立、斷言和執行測試的簡單而強大的功能使其成為 Python 開發人員珍視的工具。這些基礎知識將作為探索更高階測試概念的墊腳石,我們將在後面的文章中介紹這些概念。

四. Pytest 中的固定裝置

pytest 的一個重要特點是使用固定裝置(fixtures)來建立一個固定的基線,使測試能在這個基線上可靠地重複執行。固定裝置是為測試功能建立設定和拆卸程式碼的一種方法。這種設定可以是以資料為中心的,也可以是在多個測試中重複使用的物件。

夾具(Fixtures)介紹

在 pytest 中,固定裝置為建立可在多個測試中共享的設定程式碼提供了一種方法。一個固定裝置函式會為測試建立一個固定的基線,然後固定裝置名稱會被用作任何測試的輸入引數。真正的優勢來自於在一個或多個獨立的 conftest.py 檔案中定義固定裝置的能力,從而使它們可用於多個測試檔案。

這是一個返回字典的簡單裝置,可用於儲存測試資料:

在測試中,使用夾具名稱作為輸入引數:

使用夾具進行安裝和拆卸的示例

夾具的用途非常廣泛,可以在測試開始時進行設定,在測試結束時進行拆卸,以及其間的所有操作。這是一個更復雜的夾具示例,演示了設定和拆卸功能:

假設你有一個資料庫類:

你可以在 conftest.py 檔案中建立一個固定裝置來處理資料庫連線的設定和拆卸:

然後,在測試函式中使用該夾具 db_connection:

在此示例中,db_connection 夾具處理建立新物件並連線到資料庫的設定 Database,以及在測試函式執行後關閉資料庫連線的拆卸。

該 yield 語句是 pytest 從設定階段過渡到拆卸階段的地方。之前的所有程式碼 yield 都是設定,之後的程式碼都是拆卸。

夾具提供了一種強大的方法來管理測試的設定和拆卸程式碼,使測試保持乾淨和乾燥(不要重複)。它們提高了程式碼的可重用性,並且可以顯著減少樣板程式碼的數量,使測試更易於編寫、閱讀和維護。

五. 引數化測試

強大的測試框架應該有助於根據各種輸入驗證功能或方法,以確保其正確性。Pytest 透過引數化測試的能力在這方面表現出色。引數化有助於使用不同的輸入值多次執行測試,這是確認程式碼在不同條件下的功能和可靠性的關鍵實踐。

如何引數化測試

pytest 中的引數化是使用@pytest.mark.parametrize 裝飾器實現的。該裝飾器允許指定測試的輸入值和預期結果,使其成為增強測試套件全面性的強大工具。以下是如何使用它:

假設有一個函式 multiply 想要使用不同的輸入集進行測試:

可以建立一個測試檔案 test_math_operations.py 並使用@pytest.mark.parametrize 裝飾器來測試 multiply 具有各種輸入的函式:

在上面的程式碼中,a、b、 和 expected 是函式的輸入引數 test_multiply,列表中的元組為測試的每次迭代提供這些引數的值。

不同測試用例的引數化示例

引數化可以在多種場景中使用。這是另一個說明性示例,其中可以採用引數化來測試確定數字是否為偶數的函式:

要測試該 is_even 函式,您可以使用引數化來驗證其在一系列數字上的正確性:

在這個示例中,test_is_even 函式以不同的數值和預期引數值執行了 6 次,確保 is_even 函式對正數和負數(包括零)都表現出預期的效果。

在 pytest 中引數化測試的能力增強了測試套件的清晰度和全面性。透過利用引數化,可以確保您的函式和方法在廣泛的輸入中得到徹底的測試,從而培養出強大而可靠的程式碼庫。

六. 高階功能

隨著你越來越習慣 pytest 的基礎知識,探索其高階功能可以進一步最佳化你的測試過程。下面,讓我們將深入研究 pytest 中的標記、外掛以及異常和模擬的處理。儘管被稱為高階功能,但這些功能非常易於使用,並且可以顯著增強測試能力。

標記及其用途

pytest 中的標記提供了一種將後設資料新增到測試中的方法,允許根據標記執行測試子集。這對於具有大量測試套件的大型專案特別有用。以下是使用標記的方法:

使用配置檔案定義自定義標記 pytest.ini:

現在,將@pytest.mark.slow裝飾器應用於你想要標記為慢的任何測試:

要僅執行慢速測試,請使用-mpytest 選項:

外掛以及與其他工具的整合

pytest 的外掛架構允許擴充套件其功能並與其他工具整合。有許多可用的外掛,建立自己的外掛也是一個簡單的過程。這是使用該 pytest-cov 外掛來測量程式碼覆蓋率的示例:

透過 pip 安裝 pytest-cov:

現在,執行 pytest 並--cov 選擇獲取覆蓋率報告:

此命令將執行測試並提供 myproject 目錄的覆蓋率報告。

測試異常和使用模擬

測試程式碼如何處理異常對於構建健壯的應用程式至關重要。Pytest 簡化了這個過程。以下是測試函式是否引發預期異常的方法:

模擬是另一個高階功能,可以在測試期間模擬行為,這對於將測試與外部因素或系統隔離非常有用。該 unittest.mock 庫包含在 Python 中,可以與 pytest 一起使用來建立模擬。

下面是使用 mock 來模擬資料庫連線的示例:

在此示例中,Mock 用於將實際 db_connection 函式替換為模擬版本,這個模擬版本在呼叫時返回 “Connected”,從而允許進行受控和隔離測試。

探索 pytest 的這些高階功能為更有效的測試開闢了多種可能性。透過利用標記、外掛以及測試異常和使用模擬的功能,從而可以構建更加健壯、可靠和可維護的程式碼庫。

七. 實際用例

透過深入研究 pytest 用於測試的現實場景,可以很好地補充 pytest 的理論知識。下面將展示在實際專案中實施測試的示例,然後討論使用 pytest 測試軟體時採用的最佳實踐。

在實際專案中實施測試的示例

1.測試 REST API:

使用 REST API 時,測試端點的預期行為至關重要。讓我們考慮一個簡化的場景,其中您有一個 Flask 應用程式,該應用程式具有返回問候語的單個端點:

可以建立一個測試檔案 test_app.py,使用 pytest 和 requests 庫測試 /greet 端點:

  1. 測試資料庫互動:

確保應用程式按預期與資料庫互動至關重要。假設有一個查詢資料庫以按 ID 檢索使用者的函式:

可以使用 pytest 裝置來管理資料庫連線和回滾事務,以確保測試狀態一致:

使用 Pytest 進行軟體測試的最佳實踐的討論

遵循軟體測試的最佳實踐不僅可以提高程式碼質量,還可以使測試過程更加高效和有效。以下是使用 pytest 時的一些推薦做法:

1.保持測試簡單且集中:每個測試都應該驗證一個行為或概念。保持測試簡單且集中,可以更輕鬆地識別和解決出現的問題。

2.使用描述性測試函式名稱:描述性名稱有助於理解測試的目的。採用清晰表明每個測試正在檢查的內容的命名約定。

3.利用夾具進行安裝和拆卸:利用 pytest 夾具來管理安裝和拆卸操作。這促進了程式碼重用並有助於保持測試 DRY(不要重複自己)。

4.採用引數化來覆蓋一系列輸入:引數化測試有助於使用最少的程式碼針對廣泛的輸入值驗證程式碼的行為。

5.維護一致的目錄結構:遵循一致的目錄結構可以更輕鬆地查詢測試、裝置和其他相關檔案。

6.定期執行測試並自動化:定期執行測試有助於及早發現迴歸。儘可能自動化你的測試過程以確保一致性。

7.投入時間學習高階功能:Pytest 提供許多高階功能,例如標記、外掛和模擬。學習這些可以顯著提高您的測試能力。

在專案中使用 pytest 時結合這些最佳實踐將培養質量保證文化,併為專案的成功和可維護性做出重大貢獻。

八、結論

透過上面的介紹,帶領大家瞭解了用於設定和拆卸的固定裝置的概念,引數化測試以涵蓋一系列情況,並深入研究了一些高階功能,例如使用標記、外掛以及處理異常和模擬,所有這些都在 pytest 生態系統中實現的。

當你超越基礎知識時,豐富的資源和充滿活力的社群正在等待著支援您的 pytest 工作。參與 pytest 社群,參與討論,做出貢獻,並繼續探索 pytest 提供的無數功能。官方文件是一個資訊寶庫,並且有許多外掛可用於進一步擴充套件 pytest 的功能。

此外,各種部落格、論壇和 GitHub 等平臺託管了大量使用 pytest 的專案,提供了真實的示例和創新用例。這個豐富的生態系統不僅促進學習,還提供協作和為開源專案做出貢獻的機會。(原文連結:https://python.plainenglish.io/pytest-in-practice-fundamentals-of-python-testing-techniques-69f299aef09e

相關文章