設定檔與 conftest.py
pytest 有兩種調整行為的地方:設定檔(建議用 pyproject.toml)存放「每次執行都要套用」的選項,例如測試路徑、預設參數、自訂 marker;conftest.py 是一般的 Python 檔,用來放共用的 fixture 與 hook。前者是設定值,後者是程式碼。
在 pyproject.toml 設定 pytest
pytest 9 起支援原生 TOML 格式的 [tool.pytest] 區段:
[tool.pytest]
minversion = "9.0"
testpaths = ["tests"]
addopts = ["-ra", "--strict-markers", "--import-mode=importlib"]
markers = [
"slow: 執行時間較長的測試",
"integration: 會呼叫外部服務的整合測試",
]
filterwarnings = ["error"]
| 設定 | 作用 |
|---|---|
minversion |
pytest 版本太舊時直接報錯,避免團隊成員用不同版本 |
testpaths |
只在這些資料夾找測試 |
addopts |
每次執行自動加上的命令列選項 |
markers |
註冊自訂 marker,見 Marker |
filterwarnings |
設為 error 會把警告當成錯誤,及早發現棄用 API |
舊版寫法
pytest 6~8 使用 [tool.pytest.ini_options],值的寫法沿用 INI 格式,例如 addopts = "-ra -q" 是一整個字串。pytest 9 仍支援舊寫法,但新專案建議用 [tool.pytest]。也可以改用獨立的 pytest.ini 檔。
pytest 怎麼找到設定檔?
pytest 從命令列指定的路徑往上層尋找 pytest.ini、pyproject.toml、tox.ini、setup.cfg,第一個含有 pytest 設定的檔案所在資料夾就是根目錄(rootdir)。執行時輸出的第一段會顯示 rootdir: 與 configfile:,設定沒生效時先看這兩行。
conftest.py 的作用
conftest.py 放在測試資料夾內,pytest 會自動載入,不需要 import。它的內容只對所在資料夾與子資料夾生效:
tests/
├── conftest.py # 所有測試都能用
├── unit/
│ ├── conftest.py # 只有 unit/ 的測試能用
│ └── test_price.py
└── integration/
├── conftest.py # 只有 integration/ 的測試能用
└── test_api.py
同名 fixture 以「離測試最近」的 conftest.py 為準,所以子資料夾可以覆寫上層的 fixture。
conftest.py 裡通常放什麼?
- 共用 fixture:多個測試檔都要用的資料或資源。
- Hook 函式:以
pytest_開頭的特殊函式,可以介入 pytest 的執行流程。 - 自訂命令列選項:搭配 hook 新增
--run-slow之類的選項。
下例新增 --run-slow 選項,沒加這個選項時自動跳過所有 slow 測試:
import pytest
def pytest_addoption(parser):
parser.addoption("--run-slow", action="store_true", help="執行標記為 slow 的測試")
def pytest_collection_modifyitems(config, items):
if config.getoption("--run-slow"):
return
skip_slow = pytest.mark.skip(reason="需要 --run-slow 才會執行")
for item in items:
if "slow" in item.keywords:
item.add_marker(skip_slow)
不要在測試檔 import conftest
conftest.py 由 pytest 自動載入,手動 import conftest 可能讓它被載入兩次。需要共用的一般工具函式,請放在獨立模組再 import。
推薦影音
This Is How Marie Kondo Sets up Her Pytest(ArjanCodes)
ArjanCodes 用「斷捨離」的極簡方式從零建立 pytest 環境:安裝 pytest、建立測試資料夾、設定 VS Code 的測試面板並開始寫測試,約 16 分鐘,適合想要乾淨專案設定的讀者。