mcpField
P
pytest-advanced

pytest-advanced

github.com/laurigatesテスト・品質59357 回インストール1 日前に更新
リポジトリ

pytest-advanced について

堅牢で保守しやすいテストスイートを作る Python 開発者向けの pytest 応用ガイドです。フィクスチャ階層、複雑なパラメーター化、プラグイン、非同期テスト、並列実行、CI 連携を扱います。

主な機能

  1. 01スコープ別・ファクトリー型フィクスチャの構成
  2. 02複雑なパラメーター化とマーカー
  3. 03pytest プラグインの設定
  4. 04非同期テストとモック
  5. 05並列実行と CI 連携

活用シーン

  1. 01複数パッケージのテストでフィクスチャを共有
  2. 02複数の入力やデータベースバックエンドをテスト
  3. 03並列実行で失敗箇所を特定
  4. 04CI でカバレッジとテスト結果を出力

インストール

コマンドをコピーしてターミナルで実行します。

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

インストール後、Claude Code で/pytest-advancedを入力して読み込まれたか確認します。

同梱ファイルREFERENCE.md

詳細

高度な Pytest パターン

堅牢で保守しやすいテストスイートを実現するための、pytest の高度な機能です。

このスキルを使う場合

次の場合はこのスキルを使います…次の場合は python-testing を使います…
スコープやファクトリーを使ったフィクスチャを書く基本的なテスト構成について質問する
複雑なデータでパラメーター化するシンプルな 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"]

フィクスチャ

スコープとライフサイクル
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テスト実行全体
パラメーター化されたフィクスチャ
@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 フィクスチャ
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

エージェント向けの最適化

コンテキストコマンド
クイックチェック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 を参照してください。

コメント