# Python Testing

> Use when implementing new Python code (follow TDD), designing test suites, reviewing test coverage, setting up pytest infrastructure, writing fixtures, mocking dependencies, or performing parametrized testing

- Skill: `diegosouzapw/python-testing` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add diegosouzapw/python-testing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/diegosouzapw/python-testing/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: diegosouzapw (https://skillmd.com/u/diegosouzapw)
- Updated: 2026-09-08
- Page: https://skillmd.com/skills/diegosouzapw/python-testing

---


# Python Testing Patterns

Comprehensive testing strategies for Python applications using pytest, TDD methodology, and best practices.

## When to Use

- Writing new Python code (follow TDD: red, green, refactor)
- Designing test suites for Python projects
- Reviewing Python test coverage
- Setting up testing infrastructure
- Need guidance on fixtures, mocking, or parametrization

## TDD Cycle

Always follow the Red → Green → Refactor cycle:

1. **RED**: Write a failing test for the desired behavior
2. **GREEN**: Write minimal code to make the test pass
3. **REFACTOR**: Improve code while keeping tests green

## Quick Start

```python
import pytest

# Basic test
def test_addition():
    assert 2 + 2 == 4

# Test with fixture
@pytest.fixture
def sample_data():
    return {"name": "Alice", "age": 30}

def test_sample_data(sample_data):
    assert sample_data["name"] == "Alice"

# Parametrized test
@pytest.mark.parametrize("input,expected", [
    ("hello", "HELLO"),
    ("world", "WORLD"),
])
def test_uppercase(input, expected):
    assert input.upper() == expected

# Exception testing
def test_divide_by_zero():
    with pytest.raises(ZeroDivisionError):
        _ = 1 / 0
```

## Core Topics

### Fixtures
Setup and teardown for tests, sharing data, and scopes (function, module, session).
**Details:** `references/fixtures.md`

### Parametrization
Running tests with multiple inputs using `@pytest.mark.parametrize`.
**Details:** `references/parametrization.md`

### Mocking and Patching
Using `unittest.mock` to mock external dependencies and API calls.
**Details:** `references/mocking.md`

### Markers and Test Selection
Custom markers (`@pytest.mark.slow`) and selective test execution.
**Details:** `references/markers.md`

### Async Testing
Testing async functions with `pytest-asyncio`.
**Details:** `references/async_testing.md`

### Test Organization
Directory structure, conftest.py, and grouping related tests.
**Details:** `references/test_organization.md`

## Quick Reference

| Pattern | Usage |
|---------|-------|
| `pytest.raises()` | Test expected exceptions |
| `@pytest.fixture()` | Create reusable test fixtures |
| `@pytest.mark.parametrize()` | Run tests with multiple inputs |
| `@pytest.mark.slow` | Mark slow tests |
| `pytest -m "not slow"` | Skip slow tests |
| `@patch()` | Mock functions and classes |
| `tmp_path` fixture | Automatic temp directory |
| `pytest --cov` | Generate coverage report |

## Running Tests

```bash
# Run all tests
pytest

# Run with coverage
pytest --cov=mypackage --cov-report=html

# Run only fast tests
pytest -m "not slow"

# Run with verbose output
pytest -v

# Run until first failure
pytest -x

# Run last failed tests
pytest --lf
```

## Best Practices

**DO:**
- Follow TDD (write tests before code)
- Test one thing per test
- Use descriptive test names
- Use fixtures to eliminate duplication
- Mock external dependencies
- Aim for 80%+ coverage
- Keep tests fast

**DON'T:**
- Test implementation details
- Use complex conditionals in tests
- Share state between tests
- Catch exceptions in tests (use `pytest.raises`)
- Write tests that are too brittle

**Details:** `references/best_practices.md`

## Common Patterns

### API Endpoint Testing
```python
@pytest.fixture
def client():
    app = create_app(testing=True)
    return app.test_client()

def test_get_user(client):
    response = client.get("/api/users/1")
    assert response.status_code == 200
```

### Database Testing
```python
@pytest.fixture
def db_session():
    session = Session(bind=engine)
    session.begin_nested()
    yield session
    session.rollback()
    session.close()
```

**More patterns:** `references/common_patterns.md`

