name: python-pytest-patterns description: “Python的pytest测试模式。触发词:pytest、fixture、mark、parametrize、mock、conftest、测试覆盖率、单元测试、集成测试、pytest.raises。” compatibility: “pytest 7.0+, Python 3.9+。部分功能需要pytest-asyncio、pytest-mock、pytest-cov。” allowed-tools: “Read Write Bash” depends-on: [] related-skills: [python-typing-patterns, python-async-patterns]
Python pytest 模式
用于高效测试的现代pytest模式。
基本测试结构
import pytest
def test_basic():
"""简单的断言测试。"""
assert 1 + 1 == 2
def test_with_description():
"""描述性名称和文档字符串。"""
result = calculate_total([1, 2, 3])
assert result == 6, "总和应等于6"
夹具
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(sample_user):
"""通过名称注入的夹具。"""
assert sample_user["name"] == "测试用户"
夹具作用域
@pytest.fixture(scope="function") # 默认 - 每个测试
@pytest.fixture(scope="class") # 每个测试类
@pytest.fixture(scope="module") # 每个测试文件
@pytest.fixture(scope="session") # 整个测试运行
参数化
@pytest.mark.parametrize("input,expected", [
(1, 2),
(2, 4),
(3, 6),
])
def test_double(input, expected):
assert double(input) == expected
# 多个参数
@pytest.mark.parametrize("x", [1, 2])
@pytest.mark.parametrize("y", [10, 20])
def test_multiply(x, y): # 4个测试组合
assert x * y > 0
异常测试
def test_raises():
with pytest.raises(ValueError) as exc_info:
raise ValueError("无效输入")
assert "无效" in str(exc_info.value)
def test_raises_match():
with pytest.raises(ValueError, match=r".*[Ii]nvalid.*"):
raise ValueError("Invalid input")
标记器
@pytest.mark.skip(reason="尚未实现")
def test_future_feature():
pass
@pytest.mark.skipif(sys.platform == "win32", reason="仅限Unix")
def test_unix_feature():
pass
@pytest.mark.xfail(reason="已知bug")
def test_buggy():
assert broken_function() == expected
@pytest.mark.slow
def test_performance():
"""自定义标记器 - 在pytest.ini中注册。"""
pass
模拟
from unittest.mock import Mock, patch, MagicMock
def test_with_mock():
mock_api = Mock()
mock_api.get.return_value = {"status": "ok"}
result = mock_api.get("/endpoint")
assert result["status"] == "ok"
@patch("module.external_api")
def test_with_patch(mock_api):
mock_api.return_value = {"data": []}
result = function_using_api()
mock_api.assert_called_once()
pytest-mock(推荐)
def test_with_mocker(mocker):
mock_api = mocker.patch("module.api_call")
mock_api.return_value = {"success": True}
result = process_data()
assert result["success"]
conftest.py
# tests/conftest.py - 共享夹具
import pytest
@pytest.fixture(scope="session")
def app():
"""所有测试可用的应用程序夹具。"""
return create_app(testing=True)
@pytest.fixture
def client(app):
"""测试客户端夹具。"""
return app.test_client()
快速参考
| 命令 | 描述 |
|---|---|
pytest |
运行所有测试 |
pytest -v |
详细输出 |
pytest -x |
首次失败时停止 |
pytest -k "test_name" |
运行匹配的测试 |
pytest -m slow |
运行标记的测试 |
pytest --lf |
重新运行上次失败的测试 |
pytest --cov=src |
覆盖率报告 |
pytest -n auto |
并行运行(pytest-xdist) |
附加资源
./references/fixtures-advanced.md- 工厂夹具、自动使用、conftest模式./references/mocking-patterns.md- Mock、patch、MagicMock、side_effect./references/async-testing.md- pytest-asyncio模式./references/coverage-strategies.md- pytest-cov、分支覆盖率、报告./references/integration-testing.md- 数据库夹具、API测试、testcontainers./references/property-testing.md- Hypothesis框架、策略、收缩./references/test-architecture.md- 测试金字塔、组织、隔离策略
脚本
./scripts/run-tests.sh- 使用推荐选项运行测试./scripts/generate-conftest.sh- 生成conftest.py样板文件
资产
./assets/pytest.ini.template- 推荐的pytest配置./assets/conftest.py.template- 常见夹具模式
另请参阅
相关技能:
python-typing-patterns- 类型安全的测试代码python-async-patterns- 异步测试模式(pytest-asyncio)
测试特定框架:
python-fastapi-patterns- TestClient、API测试python-database-patterns- 数据库夹具、事务