mcpField
P
pytest-advanced

pytest-advanced

github.com/laurigates测试与质量59357 次安装1 天前更新
代码仓库

关于 pytest-advanced

面向需要构建可维护测试套件的 Python 开发者,介绍 pytest 的进阶用法,包括 fixture 层级、复杂参数化和插件配置。还涵盖异步测试、并行执行及 CI 集成。

主要功能

  1. 01按作用域和工厂模式组织 fixture
  2. 02复杂参数化与标记筛选
  3. 03配置 pytest 插件
  4. 04异步测试与 mock
  5. 05并行执行及 CI 集成

适用场景

  1. 01为多模块测试套件共享 fixture
  2. 02测试多种输入或数据库后端
  3. 03并行运行测试并快速定位失败
  4. 04为 CI 输出覆盖率和测试结果

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/laurigates/claude-plugins --skill pytest-advanced

安装后在 Claude Code 中输入/pytest-advanced确认已加载。

附带文件REFERENCE.md

详细介绍

高级 Pytest 模式

用于构建健壮、易维护测试套件的高级 pytest 功能。

何时使用此技能

在以下情况下使用此技能……在以下情况下改用 python-testing……
编写带作用域/工厂的 fixture了解基本测试结构
使用复杂数据进行参数化使用简单的 assert 模式
设置 pytest 插件(cov、xdist)运行现有测试
组织 conftest.py 层级结构了解测试发现基础知识
使用 pytest-asyncio 进行异步测试编写同步单元测试

安装

# Core + common plugins
uv add --dev pytest pytest-cov pytest-asyncio pytest-xdist pytest-mock

配置(pyproject.toml)

[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = [
    "-v",
    "--strict-markers",
    "--tb=short",
    "-ra",
    "--cov=src",
    "--cov-report=term-missing",
    "--cov-fail-under=80",
]
markers = [
    "slow: marks tests as slow (deselect with '-m \"not slow\"')",
    "integration: marks tests as integration tests",
]
asyncio_mode = "auto"

[tool.coverage.run]
branch = true
source = ["src"]

[tool.coverage.report]
exclude_lines = ["pragma: no cover", "if TYPE_CHECKING:", "@abstractmethod"]

Fixture

作用域与生命周期
import pytest
from typing import Generator

# function (default) - fresh per test
@pytest.fixture
def db() -> Generator[Database, None, None]:
    database = Database(":memory:")
    database.create_tables()
    yield database
    database.close()

# session - shared across all tests
@pytest.fixture(scope="session")
def app():
    return create_app("testing")

# autouse - applies automatically
@pytest.fixture(autouse=True)
def reset_state():
    clear_cache()
    yield
作用域生命周期
function每个测试(默认)
class每个测试类
module每个测试文件
session整个测试运行期间
参数化 Fixture
@pytest.fixture(params=["sqlite", "postgres", "mysql"])
def database_backend(request) -> str:
    return request.param  # Test runs 3 times

# Indirect parametrization
@pytest.fixture
def user(request) -> User:
    return User(**request.param)

@pytest.mark.parametrize("user", [
    {"name": "Alice", "age": 30},
    {"name": "Bob", "age": 25},
], indirect=True)
def test_user_validation(user: User):
    assert user.name
工厂模式
@pytest.fixture
def user_factory() -> Callable[[str], User]:
    created: list[User] = []
    def _create(name: str, **kwargs) -> User:
        user = User(name=name, **kwargs)
        created.append(user)
        return user
    yield _create
    for u in created:
        u.delete()

标记

# Built-in markers
@pytest.mark.skip(reason="Not implemented")
@pytest.mark.skipif(sys.version_info < (3, 12), reason="Requires 3.12+")
@pytest.mark.xfail(reason="Known bug #123")
@pytest.mark.timeout(10)

# Parametrize
@pytest.mark.parametrize("input,expected", [
    pytest.param(2, 4, id="two"),
    pytest.param(3, 9, id="three"),
    pytest.param(-2, 4, id="negative"),
])
def test_square(input: int, expected: int):
    assert input ** 2 == expected
# Run by marker
pytest -m unit                    # Only unit tests
pytest -m "not slow"              # Skip slow tests
pytest -m "integration and not slow"  # Combine markers

主要插件

插件用途主要命令
pytest-cov覆盖率pytest --cov=src --cov-report=term-missing
pytest-xdist并行pytest -n auto
pytest-asyncio异步测试配置中的 asyncio_mode = "auto"
pytest-mock模拟mocker fixture
pytest-timeout超时@pytest.mark.timeout(10)
异步测试(pytest-asyncio)
@pytest.mark.asyncio
async def test_async_function():
    result = await fetch_data()
    assert result is not None

@pytest.fixture
async def async_client() -> AsyncGenerator[AsyncClient, None]:
    async with AsyncClient() as client:
        yield client
模拟(pytest-mock)
def test_with_mock(mocker):
    mock_api = mocker.patch("myapp.external.api_call")
    mock_api.return_value = {"data": "test"}
    result = my_function()
    assert result["data"] == "test"
    mock_api.assert_called_once()

运行测试

# Execution
pytest                           # All tests
pytest tests/test_models.py::test_user  # Specific test
pytest -k "user and not slow"    # Pattern matching

# Parallel
pytest -n auto                   # All CPUs
pytest -n 4                      # 4 workers

# Coverage
pytest --cov=src --cov-report=html --cov-report=term-missing

# Failed tests
pytest --lf                      # Last failed only
pytest --ff                      # Failed first
pytest -x                        # Stop on first failure
pytest --maxfail=3               # Stop after 3

# Debugging
pytest -x --pdb                  # Debug on failure
pytest -s                        # Show print output
pytest --collect-only            # Dry run

CI 集成

# .github/workflows/test.yml
- name: Run tests
  run: |
    uv run pytest \
      --cov=src \
      --cov-report=xml \
      --cov-report=term-missing \
      --junitxml=test-results.xml

Agentic 优化

场景命令
快速检查pytest -x --tb=short -q
快速失败pytest -x --maxfail=1 --tb=short
并行快速运行pytest -n auto -x --tb=short -q
指定测试pytest tests/test_foo.py::test_bar -v
按标记筛选pytest -m "not slow" -x --tb=short
覆盖率检查pytest --cov=src --cov-fail-under=80 -q
CI 模式pytest --junitxml=results.xml --cov-report=xml -q
上次失败的测试pytest --lf --tb=short
调试pytest -x --pdb -s

有关 conftest.py 层级结构、异步测试、测试组织和常见模式的详细说明,请参阅 REFERENCE.md。

评论

支持 Markdown