跳轉至

建立 2026-10-11 更新 2026-10-11

內建 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 一節。