內建 Fixture
pytest 內建了一組現成的 fixture,只要寫在測試參數列就能使用:tmp_path 提供每個測試專屬的暫存資料夾,monkeypatch 暫時修改環境變數或物件屬性,capsys 擷取 print 輸出,caplog 擷取 logging 訊息。它們都會在測試結束後自動復原,不會汙染其他測試。
tmp_path:暫存檔案與資料夾
測試讀寫檔案時,絕對不要寫進專案目錄。tmp_path 是一個 pathlib.Path 物件,指向這個測試專屬、全新的暫存資料夾:
def save_report(path, lines):
path.write_text("\n".join(lines), encoding="utf-8")
def test_save_report(tmp_path):
report = tmp_path / "report.txt"
save_report(report, ["第一行", "第二行"])
assert report.read_text(encoding="utf-8") == "第一行\n第二行"
pytest 只保留最近幾次執行的暫存資料夾,不需要手動刪除。多個測試要共用同一份暫存資料時,在 session 範圍的 fixture 裡改用 tmp_path_factory。
monkeypatch:暫時修改環境
monkeypatch 能在測試期間修改環境變數、物件屬性、字典內容,測試結束後自動還原:
import os
def get_api_url():
return os.environ.get("API_URL", "https://api.example.com")
def test_api_url_from_env(monkeypatch):
monkeypatch.setenv("API_URL", "http://localhost:8000")
assert get_api_url() == "http://localhost:8000"
def test_api_url_default(monkeypatch):
monkeypatch.delenv("API_URL", raising=False)
assert get_api_url() == "https://api.example.com"
常用方法:
| 方法 | 作用 |
|---|---|
setenv(name, value)/delenv(name) |
設定/刪除環境變數 |
setattr(obj, "name", value) |
替換物件或模組的屬性,例如把會連網的函式換成假的 |
setitem(dict, key, value) |
修改字典內容 |
chdir(path) |
暫時切換工作目錄 |
用 monkeypatch.setattr 把外部呼叫換成假函式:
import weather
def test_weather_message(monkeypatch):
monkeypatch.setattr(weather, "fetch_temperature", lambda city: 31)
assert weather.message("台北") == "台北 31°C,天氣炎熱"
需要驗證「被呼叫了幾次、傳了什麼參數」時,改用 Mock。
capsys:檢查 print 輸出
命令列工具常用 print 輸出結果,用 capsys.readouterr() 取得目前為止的標準輸出(stdout)與標準錯誤(stderr):
def greet(name):
print(f"哈囉,{name}!")
def test_greet(capsys):
greet("Amy")
captured = capsys.readouterr()
assert captured.out == "哈囉,Amy!\n"
assert captured.err == ""
caplog:檢查 logging 訊息
import logging
logger = logging.getLogger(__name__)
def withdraw(balance, amount):
if amount > balance:
logger.warning("餘額不足:balance=%s amount=%s", balance, amount)
return balance
return balance - amount
def test_withdraw_logs_warning(caplog):
with caplog.at_level(logging.WARNING):
withdraw(100, 500)
assert "餘額不足" in caplog.text
其他實用的內建 fixture
| Fixture | 用途 |
|---|---|
request |
取得目前測試的資訊,參數化 fixture 時用 request.param |
pytestconfig |
讀取命令列選項與設定值 |
recwarn |
記錄測試期間發出的所有警告 |
capfd |
與 capsys 類似,但連子行程與 C 擴充模組的輸出也能擷取 |
執行 pytest --fixtures 可以看到完整清單與說明。
推薦影音
testing output with pytest
Anthony Sottile 約 7 分鐘示範如何在 pytest 中檢查程式的輸出,對應本頁 capsys 一節。