返回 Skill 列表
extension
分类: 开发与工程无需 API Key

pytest-fixtures

Pytest fixture设计,conftest.py层级结构以及DRY测试代码模式。识别重复的fixture,规划fixture的作用域,并设计conftest.py结构。在创建测试目录、重构测试fixture或审查测试代码以查找重复时使用。

person作者: jakexiaohubgithub

Pytest Fixtures

Fixture management and conftest.py design for Python test suites.

When to Use

  • Creating new test directories
  • Refactoring test fixtures
  • Reviewing tests for DRY violations
  • Planning fixture hierarchy

MCP Workflow

# 1. Find existing conftest files
serena.search_for_pattern("conftest\\.py", paths_include_glob="**/tests/**")

# 2. Identify fixture definitions
serena.search_for_pattern("@pytest\\.fixture", paths_include_glob="**/tests/**")

# 3. Find duplicate fixture names
jetbrains.search_in_files_by_text("def sample_", fileMask="test_*.py")

# 4. Check existing helpers
serena.get_symbols_overview(relative_path="tests/")

Fixture Hierarchy

tests/
├── conftest.py           # Shared across ALL tests
│   └── Fixtures: session-scoped, DB connections, API clients
├── cli/
│   ├── conftest.py       # CLI-specific fixtures
│   │   └── Fixtures: CLI runner, mock console, sample paths
│   └── test_*.py
└── core/
    ├── conftest.py       # Core-specific fixtures
    │   └── Fixtures: domain models, sample data
    └── {module}/
        ├── conftest.py   # Module-specific (rarely needed)
        └── test_*.py

Scope Selection Guide

| Scope | Recreated | Use When | |-------|-----------|----------| | function | Each test | Default; mutable state | | class | Each class | Class-based tests, shared setup | | module | Each file | Expensive setup, immutable data | | session | Once | DB connections, API clients |

Rule: Start with function, widen scope only for performance.

Fixture Design Patterns

1. Factory Fixture (Preferred for Flexibility)

@pytest.fixture
def make_user():
    """Factory that creates users with custom attributes."""
    def _make_user(name: str = "test", role: str = "user") -> User:
        return User(name=name, role=role)
    return _make_user

# Usage in test
def test_admin_access(make_user):
    admin = make_user(role="admin")
    assert admin.can_access_admin_panel()

2. Parameterized Fixture

@pytest.fixture(params=["sqlite", "postgres", "mysql"])
def database(request):
    """Runs test with each database type."""
    return create_connection(request.param)

3. Cleanup Fixture (yield pattern)

@pytest.fixture
def temp_file(tmp_path):
    """Provides temp file and cleans up after test."""
    path = tmp_path / "test.txt"
    path.write_text("content")
    yield path
    # Cleanup happens after test

Duplicate Detection Checklist

Run before creating fixtures:

# Find fixtures with same name
grep -r "@pytest.fixture" tests/ | grep "def " | cut -d: -f2 | sort | uniq -d

# Find common helper patterns
grep -rh "def get_output\|def create_\|def make_\|def sample_" tests/

conftest.py Planning

Before Creating New Test Directory

  1. Check parent conftest - What fixtures already exist?
  2. Identify shared fixtures - What 2+ tests need?
  3. Plan fixture scope - Function/module/session?
  4. Document dependencies - What does each fixture need?

conftest.py Template

"""
Fixtures for {directory} tests.

Shared fixtures:
- {fixture_name}: {description}

Dependencies:
- Uses: {parent_fixture} from parent conftest
"""
import pytest

@pytest.fixture
def fixture_name():
    """One-line description."""
    return value

DRY Violation Patterns

| Pattern | Problem | Solution | |---------|---------|----------| | Same fixture in 2+ files | Maintenance burden | Move to shared conftest | | get_output() in multiple files | Helper duplication | Create helpers.py | | Copy-paste setup code | Test fragility | Factory fixture | | Inline data creation | Readability | Data fixtures |

Helper Function Consolidation

tests/
├── conftest.py       # Fixtures only
├── helpers.py        # Shared utility functions
│   ├── get_output()
│   ├── assert_table_contains()
│   └── create_mock_response()
└── fixtures/         # Complex fixture data
    ├── sample_metrics.json
    └── sample_datasets.yaml

Output Format

## Fixture Analysis: {directory}

### Existing Fixtures
| Location | Fixture | Scope | Used By |
|----------|---------|-------|---------|
| tests/conftest.py | db_session | session | 15 tests |
| tests/cli/conftest.py | cli_runner | function | 8 tests |

### Issues Found
1. **Duplicate**: `sample_project_path` in test_a.py and test_b.py
   - Action: Move to tests/cli/conftest.py

2. **Missing conftest**: tests/core/workflow/ has no conftest
   - Action: Create with shared fixtures

### Recommendations
- [ ] Create tests/cli/conftest.py with: cli_runner, mock_console
- [ ] Move get_output() to tests/helpers.py
- [ ] Change db_session scope from function to module

Quality Checklist

  • [ ] No duplicate fixture definitions across files
  • [ ] Fixtures use narrowest appropriate scope
  • [ ] conftest.py exists for directories with 3+ test files
  • [ ] Helper functions in helpers.py, not test files
  • [ ] Fixtures have docstrings explaining purpose
  • [ ] Factory pattern used for flexible data creation