name: pytest-mastery description: | 使用 uv 包管理器进行 Python 测试。适用于:(1) 运行 Python 测试,(2) 编写测试文件或测试函数,(3) 设置测试夹具,(4) 参数化测试,(5) 生成覆盖率报告,(6) 测试 FastAPI 应用,(7) 调试测试失败,(8) 配置 pytest 选项。触发词:“运行测试”、“编写测试”、“测试覆盖率”、“pytest”、“单元测试”、“集成测试”、“测试 FastAPI”。
使用 uv 进行 pytest 测试
快速参考
# 运行所有测试
uv run pytest
# 运行并输出详细信息
uv run pytest -v
# 运行特定文件
uv run pytest tests/test_example.py
# 运行特定测试函数
uv run pytest tests/test_example.py::test_function_name
# 运行匹配模式的测试
uv run pytest -k "pattern"
# 运行测试并生成覆盖率报告
uv run pytest --cov=src --cov-report=html
安装
# 将 pytest 添加为开发依赖
uv add --dev pytest
# 添加覆盖率支持
uv add --dev pytest-cov
# 添加异步支持(用于 FastAPI)
uv add --dev pytest-asyncio httpx
测试发现
pytest 自动发现遵循以下约定的测试:
- 文件:
test_*.py或*_test.py - 函数:
test_* - 类:
Test*(无__init__方法) - 方法:
Test*类内的test_*
标准项目结构:
project/
├── src/
│ └── myapp/
├── tests/
│ ├── __init__.py
│ ├── conftest.py # 共享夹具
│ ├── test_unit.py
│ └── integration/
│ └── test_api.py
└── pyproject.toml
夹具
夹具提供可重用的测试设置/拆卸:
import pytest
@pytest.fixture
def sample_user():
return {"id": 1, "name": "测试用户"}
@pytest.fixture
def db_connection():
conn = create_connection()
yield conn # 测试在此处运行
conn.close() # 拆卸
def test_user_name(sample_user):
assert sample_user["name"] == "测试用户"
夹具作用域
@pytest.fixture(scope="function") # 默认:每个测试新实例
@pytest.fixture(scope="class") # 每个测试类一次
@pytest.fixture(scope="module") # 每个模块一次
@pytest.fixture(scope="session") # 每个测试会话一次
共享夹具 (conftest.py)
放置在 tests/conftest.py 中以便自动可用:
# tests/conftest.py
import pytest
@pytest.fixture
def api_client():
return TestClient(app)
参数化
使用多个输入运行相同的测试:
import pytest
@pytest.mark.parametrize("input,expected", [
(1, 2),
(2, 4),
(3, 6),
])
def test_double(input, expected):
assert input * 2 == expected
@pytest.mark.parametrize("value", [None, "", [], {}])
def test_falsy_values(value):
assert not value
常用选项
| 选项 | 描述 |
|---|---|
-v |
详细输出 |
-vv |
更详细输出 |
-q |
静默模式 |
-x |
首次失败时停止 |
--lf |
仅运行上次失败的测试 |
--ff |
先运行失败的测试 |
-k "expr" |
按名称表达式过滤 |
-m "mark" |
仅运行标记的测试 |
--tb=short |
较短的回溯 |
--tb=no |
无回溯 |
-s |
显示打印语句 |
--durations=10 |
显示 10 个最慢的测试 |
-n auto |
并行执行 (pytest-xdist) |
覆盖率报告
# 终端报告
uv run pytest --cov=src
# HTML 报告(创建 htmlcov/ 目录)
uv run pytest --cov=src --cov-report=html
# 设置最低阈值(低于阈值则失败)
uv run pytest --cov=src --cov-fail-under=80
# 多种报告格式
uv run pytest --cov=src --cov-report=term --cov-report=xml
标记器
import pytest
@pytest.mark.slow
def test_slow_operation():
...
@pytest.mark.skip(reason="未实现")
def test_future_feature():
...
@pytest.mark.skipif(condition, reason="...")
def test_conditional():
...
@pytest.mark.xfail(reason="已知错误")
def test_known_failure():
...
按标记运行:
uv run pytest -m "not slow"
uv run pytest -m "integration"
pyproject.toml 配置
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_functions = ["test_*"]
addopts = "-v --tb=short"
markers = [
"slow: 将测试标记为慢速",
"integration: 集成测试",
]
[tool.coverage.run]
source = ["src"]
omit = ["tests/*", "*/__init__.py"]
[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"if TYPE_CHECKING:",
]
FastAPI 测试
有关全面的 FastAPI 测试模式,请参阅 references/fastapi-testing.md,包括:
- TestClient 设置
- 使用 httpx 进行异步测试
- 数据库夹具模式
- 依赖项覆盖
- 身份验证测试
调试失败的测试
# 运行并显示完整回溯
uv run pytest --tb=long
# 失败时进入调试器
uv run pytest --pdb
# 在回溯中显示局部变量
uv run pytest -l
# 仅运行之前失败的测试
uv run pytest --lf