在 Python 中編寫代碼時,確保您的代碼按預期運行是非常重要的。做到這一點的最佳方法之一是使用單元測試,這幫助您檢查代碼的小部分(或單元)是否正常工作。
在這篇文章中,我們將學習如何使用 PyTest 編寫和運行有效的單元測試,這是最受歡迎的 Python 測試框架之一。
什麼是單元測試?
單元測試是小型簡單的測試,專注於檢查單個函數或小段代碼。它們幫助確保您的代碼按預期運行,並能及早捕捉錯誤。
可以為代碼的不同部分編寫單元測試,例如函數、方法,甚至類。通過編寫單元測試,您可以在不運行整個程序的情況下測試您的代碼。
為什麼使用 PyTest?
PyTest 是一個流行的 Python 測試框架,使編寫和運行測試變得簡單。
它使用簡單,並擁有許多有用的功能,例如:
- 它允許您編寫簡單明了的測試用例。
- 它提供了高級功能,如夾具、參數化測試和插件。
- 它與其他測試工具和庫兼容良好。
- 它生成易於閱讀的測試結果和報告。
在 Linux 中設置 PyTest
在我們開始編寫測試之前,我們需要安裝 PyTest。如果您尚未安裝 PyTest,可以使用名為 pip 的 Python 套件管理器進行安裝。
pip install pytest
一旦安裝了 PyTest,您就準備好開始編寫測試了!
使用 PyTest 編寫您的第一個測試
讓我們從編寫一個簡單的函數開始,然後為它編寫測試。
步驟 1:編寫一個簡單的函數
首先,讓我們創建一個我們想要測試的 Python 函數。假設我們有一個將兩個數字相加的函數:
# add.py def add(a, b): return a + b
這是一個簡單的函數,接受兩個數字 a 和 b,將它們相加並返回結果。
步驟 2:為函數編寫測試
現在,讓我們為 add 函數編寫一個測試。在 PyTest 中,測試通常寫在單獨的文件中,通常命名為 test_*.py
以便於識別測試文件。
創建一個名為 test_add.py
的新文件並編寫以下測試代碼:
# test_add.py from add import add def test_add_numbers(): assert add(2, 3) == 5 assert add(-1, 1) == 0 assert add(0, 0) == 0
以上代碼的解釋:
- 我們從
add.py
文件中導入add
函數。 - 我們定義了一個名為
test_add_numbers()
的測試函數。在 PyTest 中,測試函數應以test_
開頭。 - 在測試函數內,我們使用
assert
語句來檢查調用add
函數的結果是否與預期值匹配。如果assert
語句中的條件為True
,則測試通過;否則,測試失敗。
步驟 3:運行測試
要運行測試,打開終端並導航到您的test_add.py
文件所在的目錄,然後運行以下命令:
pytest
PyTest將自動找到所有測試文件(以test_
開頭的文件)並運行其中的測試。如果一切正常,您應該會看到如下輸出:

點(.)
表示測試通過。如果有任何問題,PyTest將顯示錯誤信息。
編寫更高級的測試
現在我們知道如何編寫和運行基本測試,讓我們探索一些PyTest的更高級功能。
測試預期的異常
有時,您希望測試當出錯時您的代碼是否引發了正確的異常。您可以使用pytest.raises()
函數來做到這一點。
假設我們想要測試一個將兩個數字相除的函數。如果第二個數字為零,我們希望引發異常(以避免除以零的錯誤)。
這是divide
函數:
# divide.py def divide(a, b): if b == 0: raise ValueError("Cannot divide by zero") return a / b
現在,讓我們為此函數編寫一個測試,以檢查在我們嘗試除以零時是否引發ValueError
:
# test_divide.py from divide import divide import pytest def test_divide_numbers(): assert divide(10, 2) == 5 assert divide(-10, 2) == -5 assert divide(10, -2) == -5 def test_divide_by_zero(): with pytest.raises(ValueError): divide(10, 0)
代碼解釋:
- 我們新增了一個測試函數叫做
test_divide_by_zero()
。 - 在這個函數內,我們使用
pytest.raises(ValueError)
來檢查當我們以零作為第二個參數來調用除法函數時是否會引發ValueError
。
再次使用 pytest 命令運行測試。如果一切正常,你應該會看到這個輸出:

使用 Fixtures 進行設置和清理
在某些情況下,你可能需要在運行測試之前設置某些條件,或在測試完成後進行清理。PyTest 提供了 fixtures 來處理這些情況。
Fixture 是一個函數,你可以用來設置或拆除測試的條件。Fixtures 通常用於創建物件或連接到測試所需的資料庫。
這裡是一個使用 fixture 來設置臨時目錄以進行文件操作測試的例子:
# test_file_operations.py import pytest import os @pytest.fixture def temporary_directory(): temp_dir = "temp_dir" os.mkdir(temp_dir) yield temp_dir # This is where the test will run os.rmdir(temp_dir) # Cleanup after the test def test_create_file(temporary_directory): file_path = os.path.join(temporary_directory, "test_file.txt") with open(file_path, "w") as f: f.write("Hello, world!") assert os.path.exists(file_path)
代碼解釋:
- 我們定義了一個名為
temporary_directory
的 fixture,它在測試之前創建一個臨時目錄,並在之後刪除它。 - 測試函數
test_create_file()
使用這個 fixture 在臨時目錄中創建一個文件並檢查該文件是否存在。
再次使用 pytest 命令運行測試。PyTest 將自動檢測並使用這個 fixture。
使用 Pytest 參數化你的測試
有時,你想要用不同的輸入運行相同的測試。PyTest 允許你輕鬆地使用參數化來做到這一點。
假設我們想要測試我們的 add
函數與幾對數字。與其為每一對編寫單獨的測試函數,我們可以使用 pytest.mark.parametrize
來使用不同的輸入運行相同的測試。
# test_add.py import pytest from add import add @pytest.mark.parametrize("a, b, expected", [ (2, 3, 5), (-1, 1, 0), (0, 0, 0), (100, 200, 300) ]) def test_add_numbers(a, b, expected): assert add(a, b) == expected
代碼解釋:
- 我們使用
pytest.mark.parametrize
裝飾器來定義多組輸入(a
、b
和expected
)。 - 測試
function test_add_numbers()
將對每組輸入運行一次。
再次使用 pytest 命令運行測試,這將對每組輸入運行測試四次。
結論
在這篇文章中,我們學會了如何在 Python 中使用 PyTest 寫和運行有效的單元測試,以便及早捕捉錯誤並確保您的代碼按預期工作。
PyTest 使得編寫和運行這些測試變得簡單,隨著您在 Python 旅程中的成長,您可以利用其強大的功能來處理更複雜的測試需求。
Source:
https://www.tecmint.com/unit-testing-python-code-with-pytest/