home / skills / autumnsgrove / groveengine / python-testing

python-testing skill

/.claude/skills/python-testing

This skill helps you write and run Python tests with pytest, fixtures, mocking, and coverage, boosting test quality and confidence.

npx playbooks add skill autumnsgrove/groveengine --skill python-testing

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
3.7 KB
---
name: python-testing
description: Write and run Python tests using pytest with fixtures, mocking, coverage, and the AAA pattern. Use when writing Python tests, creating test files, or setting up pytest configuration.
---

# Python Testing Skill

## When to Activate

Activate this skill when:
- Writing Python unit tests
- Creating test files or test directories
- Setting up pytest configuration
- Working with test fixtures or mocking
- Running tests or checking coverage

## Quick Commands

```bash
# Run all tests
uv run pytest

# Run specific file
uv run pytest tests/test_auth.py

# Run with coverage
uv run pytest --cov=src --cov-report=html

# Run verbose with output
uv run pytest -v -s

# Run tests matching pattern
uv run pytest -k "test_user"

# Run last failed
uv run pytest --lf
```

## Test Structure: AAA Pattern

Follow **Arrange-Act-Assert** for clear, maintainable tests:

```python
def test_user_registration():
    # Arrange - set up test data
    email = "[email protected]"
    password = "secure_pass123"
    user_service = UserService()

    # Act - execute the function
    result = user_service.register(email, password)

    # Assert - verify the outcome
    assert result.success is True
    assert result.user.email == email
```

## Directory Structure

```
project/
├── src/
│   └── myapp/
├── tests/
│   ├── conftest.py      # Shared fixtures
│   ├── unit/
│   │   └── test_utils.py
│   ├── integration/
│   │   └── test_api.py
│   └── e2e/
│       └── test_workflows.py
└── pyproject.toml
```

## Fixtures (conftest.py)

```python
import pytest
from myapp import create_app

@pytest.fixture
def app():
    """Create application for testing."""
    app = create_app("testing")
    yield app

@pytest.fixture
def client(app):
    """Create test client."""
    return app.test_client()

@pytest.fixture
def sample_user():
    """Create a sample user for testing."""
    return User(email="[email protected]", username="testuser")
```

## Parametrized Tests

```python
@pytest.mark.parametrize("email,expected", [
    ("[email protected]", True),
    ("invalid.email", False),
    ("[email protected]", True),
])
def test_email_validation(email, expected):
    assert is_valid_email(email) == expected
```

## Mocking

```python
from unittest.mock import Mock, patch

def test_api_call():
    mock_response = Mock()
    mock_response.json.return_value = {"data": "success"}

    with patch("requests.get", return_value=mock_response):
        result = fetch_data("https://api.example.com")
        assert result == {"data": "success"}
```

## Common Patterns

### Testing Exceptions
```python
def test_division_by_zero():
    with pytest.raises(ValueError, match="Cannot divide by zero"):
        divide(10, 0)
```

### Testing with Temp Files
```python
def test_file_processing(tmp_path):
    test_file = tmp_path / "test.txt"
    test_file.write_text("Hello World")
    result = process_file(str(test_file))
    assert result.word_count == 2
```

### Testing Environment Variables
```python
def test_config_from_env(monkeypatch):
    monkeypatch.setenv("API_KEY", "test_key_123")
    assert load_config().api_key == "test_key_123"
```

## Coverage Configuration

```toml
# pyproject.toml
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "-v --cov=src --cov-report=term-missing"

[tool.coverage.run]
source = ["src"]
omit = ["tests/*"]
```

## Naming Conventions

- Test files: `test_*.py`
- Test functions: `test_*`
- Test classes: `Test*`

## Related Resources

See `AgentUsage/testing_python.md` for complete documentation including:
- Async testing patterns
- Integration test examples
- CI/CD integration
- Test priority guidelines

Overview

This skill helps you write and run Python tests using pytest, with practical patterns for fixtures, mocking, parametrization, and coverage. It focuses on clear, maintainable tests using the Arrange-Act-Assert (AAA) pattern and standard pytest conventions. Use it to create test files, configure pytest, or troubleshoot test runs and coverage reports.

How this skill works

The skill provides concrete examples and templates for test structure, conftest fixtures, parametrized tests, mocking with unittest.mock, and environment-dependent testing using monkeypatch and tmp_path. It also supplies common pytest commands and a recommended pyproject.toml coverage configuration so you can run tests locally or in CI and produce meaningful coverage output. Follow the snippets to organize tests into unit, integration, and e2e directories and to name tests for discoverability.

When to use it

  • Writing new unit, integration, or end-to-end tests for Python code
  • Creating or updating conftest.py and shared fixtures
  • Mocking external dependencies like HTTP calls or database clients
  • Running tests locally, checking coverage, or preparing CI pipelines
  • Refactoring tests to follow AAA for readability and reliability

Best practices

  • Follow Arrange-Act-Assert for each test to keep intent clear.
  • Centralize reusable fixtures in conftest.py and scope them appropriately (function, module, session).
  • Use parametrization for input matrices instead of duplicating tests.
  • Prefer monkeypatch or unittest.mock.patch to isolate external systems and make tests deterministic.
  • Run pytest with coverage flags and add a minimal coverage threshold in CI.
  • Name test files test_*.py and test functions test_* so pytest discovers them automatically.

Example use cases

  • Unit test a service layer with fixtures that provide a fake database connection.
  • Mock external API calls to verify error handling without network access.
  • Write parametrized validators to verify many input cases in one test function.
  • Use tmp_path to test file processing without touching the real filesystem.
  • Add --cov=src to pytest runs and generate an HTML report for local inspection.

FAQ

How do I structure fixtures across tests?

Place shared fixtures in tests/conftest.py. Keep fixtures small and focused; use module or session scope when setup is costly.

When should I mock vs use a real dependency?

Mock external network, third-party services, or costly resources. Use real dependencies for integration tests that validate interactions end-to-end.