Skip to content
Back to skills

Python Testing

ASecurity

Comprehensive Python testing patterns using pytest. Covers fixtures, parametrize, async testing, mocking, property-based testing, and coverage analysis.

  • 3 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 14, 2026
ai-agentspythontestingapidatabase

Works with

  • claude code
  • cli
  • api

Security analysis

A100/100

Scanned October 14, 2026

npx -y skills add peopleforrester/claude-dotfiles --skill python-testing --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Python Testing?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Python Testing
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/peopleforrester-python-testing/badge)](https://www.skillsdirectory.com/skills/peopleforrester-python-testing)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: python-testing
description: |
  Comprehensive Python testing patterns using pytest. Covers fixtures,
  parametrize, async testing, mocking, property-based testing, and
  coverage analysis.
license: MIT
compatibility: Claude Code 2.1+
metadata:
  author: peopleforrester
  version: "1.0.0"
  tags: [python, testing, pytest, tdd]
---

# Python Testing Patterns

## Framework: pytest

### Project Setup
```toml
# pyproject.toml
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_functions = ["test_*"]
addopts = "-v --tb=short --strict-markers"
markers = [
    "slow: marks tests as slow",
    "integration: marks integration tests",
]

[tool.coverage.run]
source = ["src"]
omit = ["tests/*", "*/__init__.py"]

[tool.coverage.report]
fail_under = 80
show_missing = true
```

## Fixtures

### Basic Fixtures
```python
@pytest.fixture
def sample_user() -> User:
    return User(name="Test User", email="test@example.com")

@pytest.fixture
def db_session():
    session = create_test_session()
    yield session
    session.rollback()
    session.close()
```

### Factory Fixtures
```python
@pytest.fixture
def make_user():
    def _make_user(name: str = "Test", email: str | None = None) -> User:
        return User(
            name=name,
            email=email or f"{name.lower()}@example.com",
        )
    return _make_user
```

### Shared Fixtures (conftest.py)
```python
# tests/conftest.py
@pytest.fixture(scope="session")
def app():
    """Create application for testing."""
    app = create_app(testing=True)
    yield app

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

## Parametrize

```python
@pytest.mark.parametrize("input_val, expected", [
    ("hello@example.com", True),
    ("invalid-email", False),
    ("", False),
    ("user@.com", False),
    ("user@domain.co.uk", True),
])
def test_validate_email(input_val: str, expected: bool) -> None:
    assert validate_email(input_val) == expected
```

## Async Testing

```python
import pytest_asyncio

@pytest_asyncio.fixture
async def async_client():
    async with AsyncClient(app=app, base_url="http://test") as client:
        yield client

@pytest.mark.asyncio
async def test_fetch_user(async_client: AsyncClient) -> None:
    response = await async_client.get("/api/users/1")
    assert response.status_code == 200
    assert response.json()["name"] == "Test User"
```

## Mocking

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

def test_send_email(mocker):
    mock_send = mocker.patch("myapp.email.send_email")
    mock_send.return_value = True

    result = notify_user("user@example.com", "Hello")

    assert result is True
    mock_send.assert_called_once_with("user@example.com", "Hello")
```

## Property-Based Testing

```python
from hypothesis import given, strategies as st

@given(st.lists(st.integers()))
def test_sort_is_idempotent(xs: list[int]) -> None:
    assert sorted(sorted(xs)) == sorted(xs)

@given(st.text(min_size=1))
def test_uppercase_preserves_length(s: str) -> None:
    assert len(s.upper()) == len(s)
```

## Exception Testing

```python
def test_invalid_input_raises() -> None:
    with pytest.raises(ValueError, match="must be positive"):
        calculate(-1)

def test_file_not_found_error() -> None:
    with pytest.raises(FileNotFoundError):
        load_config(Path("/nonexistent/path"))
```

## Test Organization

```
tests/
  conftest.py              # Shared fixtures
  unit/
    test_models.py         # Model unit tests
    test_services.py       # Service unit tests
    test_utils.py          # Utility unit tests
  integration/
    test_api.py            # API integration tests
    test_database.py       # Database integration tests
  e2e/
    test_workflows.py      # End-to-end workflows
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.