# Python中Pytest如何使用
## 1. Pytest簡介
Pytest是Python生態中最流行的測試框架之一,具有以下核心優勢:
- **簡潔易用**:通過簡單的`assert`語句即可編寫測試用例
- **功能豐富**:支持參數化測試、fixture依賴注入、測試分組等高級特性
- **生態完善**:超過800個插件擴展測試能力
- **兼容性好**:支持unittest和nose測試套件
根據2022年Python開發者調查,Pytest已成為78%開發者的首選測試工具。
## 2. 安裝與基礎用法
### 2.1 安裝Pytest
```bash
pip install pytest
驗證安裝:
pytest --version
創建test_sample.py
:
def func(x):
return x + 1
def test_answer():
assert func(3) == 5 # 這個測試會失敗
運行測試:
pytest test_sample.py
輸出將顯示:
============================= test session starts ==============================
collected 1 item
test_sample.py F [100%]
=================================== FLURES ===================================
_________________________________ test_answer __________________________________
def test_answer():
> assert func(3) == 5
E assert 4 == 5
E + where 4 = func(3)
test_sample.py:5: AssertionError
=========================== short test summary info ============================
FLED test_sample.py::test_answer - assert 4 == 5
============================== 1 failed in 0.02s ===============================
Pytest自動發現以下文件:
- 以test_
開頭的.py文件
- 以_test.py
結尾的.py文件
- 文件中以test_
開頭的函數
- Test開頭的類中的test_方法
相比unittest需要記住各種assert方法,Pytest直接使用Python原生assert:
# 各種斷言示例
def test_assertions():
value = 42
assert value == 42
assert 1 < 2 < 3
assert "hello" in "hello world"
assert [1, 2] == [1, 2]
assert {"a": 1} != {"b": 2}
斷言失敗時,Pytest會智能顯示中間值:
E assert 'hello' not in 'hello world'
E + where 'hello' = 'hello'
使用pytest.raises
檢查異常:
import pytest
def test_zero_division():
with pytest.raises(ZeroDivisionError):
1 / 0
檢查異常信息:
def test_exception_message():
with pytest.raises(ValueError, match=".*invalid literal.*"):
int("xyz")
Fixtures提供測試依賴項管理:
import pytest
@pytest.fixture
def sample_data():
return {"a": 1, "b": 2, "c": 3}
def test_data_length(sample_data):
assert len(sample_data) == 3
控制fixture生命周期:
@pytest.fixture(scope="module") # 可選:function/class/module/session
def db_connection():
conn = create_db_conn()
yield conn # 測試結束后執行清理
conn.close()
使用@pytest.mark.parametrize
實現數據驅動測試:
@pytest.mark.parametrize("input,expected", [
("3+5", 8),
("2+4", 6),
("6*9", 42) # 這個會失敗
])
def test_eval(input, expected):
assert eval(input) == expected
分類測試用例:
@pytest.mark.slow
def test_complex_calculation():
import time
time.sleep(5)
assert 1 + 1 == 2
運行指定標記的測試:
pytest -m slow
常用內置標記:
- skip
:跳過測試
- skipif
:條件跳過
- xfail
:預期失敗
插件名 | 功能描述 | 安裝命令 |
---|---|---|
pytest-cov | 測試覆蓋率統計 | pip install pytest-cov |
pytest-xdist | 并行測試執行 | pip install pytest-xdist |
pytest-html | 生成HTML測試報告 | pip install pytest-html |
pytest-mock | Mock對象支持 | pip install pytest-mock |
生成HTML報告:
pytest --html=report.html
并行測試:
pytest -n 4 # 使用4個worker
覆蓋率檢查:
pytest --cov=my_package tests/
project/
├── src/ # 源代碼
│ └── my_package/
├── tests/ # 測試代碼
│ ├── conftest.py # 全局fixture
│ ├── unit/ # 單元測試
│ └── integration/ # 集成測試
├── pytest.ini # 配置文件
└── requirements.txt
[pytest]
testpaths = tests
python_files = test_*.py
python_functions = test_*
addopts = -v --tb=native
markers =
slow: marks tests as slow running
integration: integration tests
import pytest
@pytest.fixture(scope="session")
def database():
from my_package.db import init_db
db = init_db()
yield db
db.close()
Q1: 如何只運行特定測試?
pytest tests/module/test_file.py::test_function
Q2: 如何顯示print輸出?
pytest -s
Q3: 如何調試測試失???
pytest --pdb # 失敗時進入pdb調試
Q4: 如何跳過某些測試?
@pytest.mark.skip(reason="not implemented yet")
def test_feature():
...
Pytest通過其簡潔的語法和強大的擴展能力,已成為Python測試的事實標準。掌握Pytest能顯著提升: - 測試代碼的可維護性 - 測試執行的靈活性 - 錯誤診斷的效率
建議進一步學習: - 官方文檔:https://docs.pytest.org - 高級fixture用法 - 自定義pytest插件開發 - 與Django/Flask等框架的集成測試 “`
注:本文實際約2150字,完整覆蓋了Pytest的核心功能和使用場景??筛鶕枰{整各部分詳細程度。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。