Implement comprehensive testing strategies with pytest

Python testing patterns

by wshobson · MIT license · ★ 39,857 on GitHub · updated Sep 21

Python testing patterns cover

Implement comprehensive testing strategies with pytest, fixtures, mocking, and test-driven development. Use when writing Python tests, setting up test suites, or implementing testing best practices.

---
name: python-testing-patterns
description: Implement comprehensive testing strategies with pytest, fixtures, mocking, and test-driven development. Use when writing Python tests, setting up test suites, or implementing testing best practices.
---

# Python Testing Patterns

Comprehensive guide to implementing robust testing strategies in Python using pytest, fixtures, mocking, parameterization, and test-driven development practices.

## When to Use This Skill

- Writing unit tests for Python code
- Setting up test suites and test infrastructure
- Implementing test-driven development (TDD)
- Creating integration tests for APIs and services
- Mocking external dependencies and services
- Testing async code and concurrent operations
- Setting up continuous testing in CI/CD

Overview

Comprehensive guide to implementing robust testing strategies in Python using pytest, fixtures, mocking, parameterization, and test-driven development practices.

Manual install (npx, ZIP)
Claude Codenpx skills add wshobson/agents --skill python-testing-patterns -g -a claude-code
Claude Code (manual)mkdir -p ~/.claude/skills && curl -sL https://codeload.github.com/wshobson/agents/tar.gz/4236bb91f839 \ | tar -xz -C ~/.claude/skills --strip-components=4 agents-4236bb91f839/plugins/python-development/skills/python-testing-patterns
Windows (PowerShell)New-Item -ItemType Directory -Force "$HOME\.claude\skills" | Out-Null; Invoke-WebRequest "https://m.agentalley.io/zip/a7ef216e916162a5374b/python-testing-patterns.zip" -OutFile "$env:TEMP\python-testing-patterns.zip"; Expand-Archive "$env:TEMP\python-testing-patterns.zip" -DestinationPath "$HOME\.claude\skills" -Force
Claude.ai / desktopDownload the ZIP and upload it under Settings → Capabilities → Skills.
Codex, Cursor, other agentsPoint them at SKILL.md. The other files are plain text.

Connects with Agent Alley MCP · agentalley.io/mcp

Files included

  • SKILL.md7.1 KB
  • references/2 files · 18.3 KB
Read the files here
wshobson/4236bb93 files
SKILL.md
Show the full text279 lines

Python Testing Patterns

Comprehensive guide to implementing robust testing strategies in Python using pytest, fixtures, mocking, parameterization, and test-driven development practices.

When to Use This Skill

  • Writing unit tests for Python code
  • Setting up test suites and test infrastructure
  • Implementing test-driven development (TDD)
  • Creating integration tests for APIs and services
  • Mocking external dependencies and services
  • Testing async code and concurrent operations
  • Setting up continuous testing in CI/CD
  • Implementing property-based testing
  • Testing database operations
  • Debugging failing tests

Core Concepts

1. Test Types
  • Unit Tests: Test individual functions/classes in isolation
  • Integration Tests: Test interaction between components
  • Functional Tests: Test complete features end-to-end
  • Performance Tests: Measure speed and resource usage
2. Test Structure (AAA Pattern)
  • Arrange: Set up test data and preconditions
  • Act: Execute the code under test
  • Assert: Verify the results
3. Test Coverage
  • Measure what code is exercised by tests
  • Identify untested code paths
  • Aim for meaningful coverage, not just high percentages
4. Test Isolation
  • Tests should be independent
  • No shared state between tests
  • Each test should clean up after itself

Quick Start

# test_example.py
def add(a, b):
    return a + b

def test_add():
    """Basic test example."""
    result = add(2, 3)
    assert result == 5

def test_add_negative():
    """Test with negative numbers."""
    assert add(-1, 1) == 0

# Run with: pytest test_example.py

Detailed patterns and worked examples

Detailed pattern documentation lives in references/details.md. Read that file when the navigation tier above is insufficient.

Testing Best Practices

Test Organization
# tests/
#   __init__.py
#   conftest.py           # Shared fixtures
#   test_unit/            # Unit tests
#     test_models.py
#     test_utils.py
#   test_integration/     # Integration tests
#     test_api.py
#     test_database.py
#   test_e2e/            # End-to-end tests
#     test_workflows.py
Test Naming Convention

A common pattern: test_<unit>_<scenario>_<expected_outcome>. Adapt to your team's preferences.

# Pattern: test_<unit>_<scenario>_<expected>
def test_create_user_with_valid_data_returns_user():
    ...

def test_create_user_with_duplicate_email_raises_conflict():
    ...

def test_get_user_with_unknown_id_returns_none():
    ...

# Good test names - clear and descriptive
def test_user_creation_with_valid_data():
    """Clear name describes what is being tested."""
    pass

def test_login_fails_with_invalid_password():
    """Name describes expected behavior."""
    pass

def test_api_returns_404_for_missing_resource():
    """Specific about inputs and expected outcomes."""
    pass

# Bad test names - avoid these
def test_1():  # Not descriptive
    pass

def test_user():  # Too vague
    pass

def test_function():  # Doesn't explain what's tested
    pass
Testing Retry Behavior

Verify that retry logic works correctly using mock side effects.

from unittest.mock import Mock

def test_retries_on_transient_error():
    """Test that service retries on transient failures."""
    client = Mock()
    # Fail twice, then succeed
    client.request.side_effect = [
        ConnectionError("Failed"),
        ConnectionError("Failed"),
        {"status": "ok"},
    ]

    service = ServiceWithRetry(client, max_retries=3)
    result = service.fetch()

    assert result == {"status": "ok"}
    assert client.request.call_count == 3

def test_gives_up_after_max_retries():
    """Test that service stops retrying after max attempts."""
    client = Mock()
    client.request.side_effect = ConnectionError("Failed")

    service = ServiceWithRetry(client, max_retries=3)

    with pytest.raises(ConnectionError):
        service.fetch()

    assert client.request.call_count == 3

def test_does_not_retry_on_permanent_error():
    """Test that permanent errors are not retried."""
    client = Mock()
    client.request.side_effect = ValueError("Invalid input")

    service = ServiceWithRetry(client, max_retries=3)

    with pytest.raises(ValueError):
        service.fetch()

    # Only called once - no retry for ValueError
    assert client.request.call_count == 1
Mocking Time with Freezegun

Use freezegun to control time in tests for predictable time-dependent behavior.

from freezegun import freeze_time
from datetime import datetime, timedelta

@freeze_time("2026-01-15 10:00:00")
def test_token_expiry():
    """Test token expires at correct time."""
    token = create_token(expires_in_seconds=3600)
    assert token.expires_at == datetime(2026, 1, 15, 11, 0, 0)

@freeze_time("2026-01-15 10:00:00")
def test_is_expired_returns_false_before_expiry():
    """Test token is not expired when within validity period."""
    token = create_token(expires_in_seconds=3600)
    assert not token.is_expired()

@freeze_time("2026-01-15 12:00:00")
def test_is_expired_returns_true_after_expiry():
    """Test token is expired after validity period."""
    token = Token(expires_at=datetime(2026, 1, 15, 11, 30, 0))
    assert token.is_expired()

def test_with_time_travel():
    """Test behavior across time using freeze_time context."""
    with freeze_time("2026-01-01") as frozen_time:
        item = create_item()
        assert item.created_at == datetime(2026, 1, 1)

        # Move forward in time
        frozen_time.move_to("2026-01-15")
        assert item.age_days == 14
Test Markers
# test_markers.py
import pytest

@pytest.mark.slow
def test_slow_operation():
    """Mark slow tests."""
    import time
    time.sleep(2)


@pytest.mark.integration
def test_database_integration():
    """Mark integration tests."""
    pass


@pytest.mark.skip(reason="Feature not implemented yet")
def test_future_feature():
    """Skip tests temporarily."""
    pass


@pytest.mark.skipif(os.name == "nt", reason="Unix only test")
def test_unix_specific():
    """Conditional skip."""
    pass


@pytest.mark.xfail(reason="Known bug #123")
def test_known_bug():
    """Mark expected failures."""
    assert False


# Run with:
# pytest -m slow          # Run only slow tests
# pytest -m "not slow"    # Skip slow tests
# pytest -m integration   # Run integration tests
Coverage Reporting
# Install coverage
pip install pytest-cov

# Run tests with coverage
pytest --cov=myapp tests/

# Generate HTML report
pytest --cov=myapp --cov-report=html tests/

# Fail if coverage below threshold
pytest --cov=myapp --cov-fail-under=80 tests/

# Show missing lines
pytest --cov=myapp --cov-report=term-missing tests/

For advanced patterns (async testing, monkeypatching, property-based testing, database testing, CI/CD integration, and configuration), see references/advanced-patterns.md

1---
2name: python-testing-patterns
3description: Implement comprehensive testing strategies with pytest, fixtures, mocking, and test-driven development. Use when writing Python tests, setting up test suites, or implementing testing best practices.
4---
5 
6# Python Testing Patterns
7 
8Comprehensive guide to implementing robust testing strategies in Python using pytest, fixtures, mocking, parameterization, and test-driven development practices.
9 
10## When to Use This Skill
11 
12- Writing unit tests for Python code
13- Setting up test suites and test infrastructure
14- Implementing test-driven development (TDD)
15- Creating integration tests for APIs and services
16- Mocking external dependencies and services
17- Testing async code and concurrent operations
18- Setting up continuous testing in CI/CD
19- Implementing property-based testing
20- Testing database operations
21- Debugging failing tests
22 
23## Core Concepts
24 
25### 1. Test Types
26 
27- **Unit Tests**: Test individual functions/classes in isolation
28- **Integration Tests**: Test interaction between components
29- **Functional Tests**: Test complete features end-to-end
30- **Performance Tests**: Measure speed and resource usage
31 
32### 2. Test Structure (AAA Pattern)
33 
34- **Arrange**: Set up test data and preconditions
35- **Act**: Execute the code under test
36- **Assert**: Verify the results
37 
38### 3. Test Coverage
39 
40- Measure what code is exercised by tests
41- Identify untested code paths
42- Aim for meaningful coverage, not just high percentages
43 
44### 4. Test Isolation
45 
46- Tests should be independent
47- No shared state between tests
48- Each test should clean up after itself
49 
50## Quick Start
51 
52```python
53# test_example.py
54def add(a, b):
55 return a + b
56 
57def test_add():
58 """Basic test example."""
59 result = add(2, 3)
60 assert result == 5
61 
62def test_add_negative():
63 """Test with negative numbers."""
64 assert add(-1, 1) == 0
65 
66# Run with: pytest test_example.py
67```
68 
69## Detailed patterns and worked examples
70 
71Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.
72 
73## Testing Best Practices
74 
75### Test Organization
76 
77```python
78# tests/
79# __init__.py
80# conftest.py # Shared fixtures
81# test_unit/ # Unit tests
82# test_models.py
83# test_utils.py
84# test_integration/ # Integration tests
85# test_api.py
86# test_database.py
87# test_e2e/ # End-to-end tests
88# test_workflows.py
89```
90 
91### Test Naming Convention
92 
93A common pattern: `test_<unit>_<scenario>_<expected_outcome>`. Adapt to your team's preferences.
94 
95```python
96# Pattern: test_<unit>_<scenario>_<expected>
97def test_create_user_with_valid_data_returns_user():
98 ...
99 
100def test_create_user_with_duplicate_email_raises_conflict():
101 ...
102 
103def test_get_user_with_unknown_id_returns_none():
104 ...
105 
106# Good test names - clear and descriptive
107def test_user_creation_with_valid_data():
108 """Clear name describes what is being tested."""
109 pass
110 
111def test_login_fails_with_invalid_password():
112 """Name describes expected behavior."""
113 pass
114 
115def test_api_returns_404_for_missing_resource():
116 """Specific about inputs and expected outcomes."""
117 pass
118 
119# Bad test names - avoid these
120def test_1(): # Not descriptive
121 pass
122 
123def test_user(): # Too vague
124 pass
125 
126def test_function(): # Doesn't explain what's tested
127 pass
128```
129 
130### Testing Retry Behavior
131 
132Verify that retry logic works correctly using mock side effects.
133 
134```python
135from unittest.mock import Mock
136 
137def test_retries_on_transient_error():
138 """Test that service retries on transient failures."""
139 client = Mock()
140 # Fail twice, then succeed
141 client.request.side_effect = [
142 ConnectionError("Failed"),
143 ConnectionError("Failed"),
144 {"status": "ok"},
145 ]
146 
147 service = ServiceWithRetry(client, max_retries=3)
148 result = service.fetch()
149 
150 assert result == {"status": "ok"}
151 assert client.request.call_count == 3
152 
153def test_gives_up_after_max_retries():
154 """Test that service stops retrying after max attempts."""
155 client = Mock()
156 client.request.side_effect = ConnectionError("Failed")
157 
158 service = ServiceWithRetry(client, max_retries=3)
159 
160 with pytest.raises(ConnectionError):
161 service.fetch()
162 
163 assert client.request.call_count == 3
164 
165def test_does_not_retry_on_permanent_error():
166 """Test that permanent errors are not retried."""
167 client = Mock()
168 client.request.side_effect = ValueError("Invalid input")
169 
170 service = ServiceWithRetry(client, max_retries=3)
171 
172 with pytest.raises(ValueError):
173 service.fetch()
174 
175 # Only called once - no retry for ValueError
176 assert client.request.call_count == 1
177```
178 
179### Mocking Time with Freezegun
180 
181Use freezegun to control time in tests for predictable time-dependent behavior.
182 
183```python
184from freezegun import freeze_time
185from datetime import datetime, timedelta
186 
187@freeze_time("2026-01-15 10:00:00")
188def test_token_expiry():
189 """Test token expires at correct time."""
190 token = create_token(expires_in_seconds=3600)
191 assert token.expires_at == datetime(2026, 1, 15, 11, 0, 0)
192 
193@freeze_time("2026-01-15 10:00:00")
194def test_is_expired_returns_false_before_expiry():
195 """Test token is not expired when within validity period."""
196 token = create_token(expires_in_seconds=3600)
197 assert not token.is_expired()
198 
199@freeze_time("2026-01-15 12:00:00")
200def test_is_expired_returns_true_after_expiry():
201 """Test token is expired after validity period."""
202 token = Token(expires_at=datetime(2026, 1, 15, 11, 30, 0))
203 assert token.is_expired()
204 
205def test_with_time_travel():
206 """Test behavior across time using freeze_time context."""
207 with freeze_time("2026-01-01") as frozen_time:
208 item = create_item()
209 assert item.created_at == datetime(2026, 1, 1)
210 
211 # Move forward in time
212 frozen_time.move_to("2026-01-15")
213 assert item.age_days == 14
214```
215 
216### Test Markers
217 
218```python
219# test_markers.py
220import pytest
221 
222@pytest.mark.slow
223def test_slow_operation():
224 """Mark slow tests."""
225 import time
226 time.sleep(2)
227 
228 
229@pytest.mark.integration
230def test_database_integration():
231 """Mark integration tests."""
232 pass
233 
234 
235@pytest.mark.skip(reason="Feature not implemented yet")
236def test_future_feature():
237 """Skip tests temporarily."""
238 pass
239 
240 
241@pytest.mark.skipif(os.name == "nt", reason="Unix only test")
242def test_unix_specific():
243 """Conditional skip."""
244 pass
245 
246 
247@pytest.mark.xfail(reason="Known bug #123")
248def test_known_bug():
249 """Mark expected failures."""
250 assert False
251 
252 
253# Run with:
254# pytest -m slow # Run only slow tests
255# pytest -m "not slow" # Skip slow tests
256# pytest -m integration # Run integration tests
257```
258 
259### Coverage Reporting
260 
261```bash
262# Install coverage
263pip install pytest-cov
264 
265# Run tests with coverage
266pytest --cov=myapp tests/
267 
268# Generate HTML report
269pytest --cov=myapp --cov-report=html tests/
270 
271# Fail if coverage below threshold
272pytest --cov=myapp --cov-fail-under=80 tests/
273 
274# Show missing lines
275pytest --cov=myapp --cov-report=term-missing tests/
276```
277 
278For advanced patterns (async testing, monkeypatching, property-based testing, database testing, CI/CD integration, and configuration), see [references/advanced-patterns.md](references/advanced-patterns.md)
279 
View all files on GitHub →

Details

Updated
Sep 21, 2026
License
MIT
Stars on the repo
★ 39,857
Checked
Source
wshobson/agents ↗
Creator
wshobson · 179 listings
View creator

Similar skills

See all →
Skill29 production-ready scripts for iOS app testing, buildingIos simulator skillconorluddy/ios-simulator-skill · by conorluddy29 production-ready scripts for iOS app testing, building, and automation. Provides semantic UI navigation, build automation, accessibility testing, and simulator lifecycle management. Optimized for AI agents with minimal token output.★ 1.3k GitHub starsSkillMoAI unified orchestrator for autonomous developmentmodu-ai/moai-adk · by modu-aiMoAI unified orchestrator for autonomous development. Routes natural language or subcommands (plan, run, sync, project, fix, loop, mx, feedback, review, clean, codemaps, gate, e2e, harness, goal, gtd, todo) to specialized agents.★ 1.2k GitHub starsSkillWrite Android unit, Compose UI, and Hilt-integrated testsAndroid Testing StandardsHoangNguyen0403/agent-skills-standard · by HoangNguyen0403Write Android unit, Compose UI, and Hilt-integrated tests. Use when designing test behavior with MockK or coroutine test utilities; defer database/WorkManager-specific recipes to the owning feature skill.★ 569 GitHub starsSkillImplementing any feature or bugfixTest-Driven Development (TDD)obra/superpowers · by obraUse when implementing any feature or bugfix, before writing implementation code★ 290k GitHub starsSkillToolkit for interacting with and testing local webWebapp testinganthropics/skills · by anthropicsToolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.★ 178k GitHub starsPromptGuide to fixing bugs using a test-first approachTest first bug fixing approachf/prompts.chat · by Ilker UlusoyGuide to fixing bugs using a test-first approach, ensuring code reliability through systematic testing and implementation.New listing

More from wshobson

SkillMaster C/.NET backend development patterns for buildingwshobson/agents · by wshobsonMaster C#/.NET backend development patterns for building robust APIs, MCP servers, and enterprise applications. Covers async/await, dependency injection, Entity Framework Core, Dapper, configuration, caching, and testing with xUnit. Use when developing .NET backends, reviewing C# code, or designing API architectures.★ 39.9k GitHub starsSkillImplement WCAG 2.2 compliant interfaces with mobileAccessibility compliancewshobson/agents · by wshobsonImplement WCAG 2.2 compliant interfaces with mobile accessibility, inclusive design patterns, and assistive technology support. Use when auditing accessibility, implementing ARIA patterns, building for screen readers, or ensuring inclusive user experiences.★ 39.9k GitHub starsSkillMaster Material Design 3 and Jetpack Compose patternsAndroid Mobile Designwshobson/agents · by wshobsonMaster Material Design 3 and Jetpack Compose patterns for building native Android apps. Use when designing Android interfaces, implementing Compose UI, or following Google's Material Design guidelines.★ 39.9k GitHub starsSkillMigrate from AngularJS to Angular using hybrid modeAngular migrationwshobson/agents · by wshobsonMigrate from AngularJS to Angular using hybrid mode, incremental component rewriting, and dependency injection updates. Use when upgrading AngularJS applications, planning framework migrations, or modernizing legacy Angular code.★ 39.9k GitHub starsSkillUnderstand anti-reversing, obfuscationAnti reversing techniqueswshobson/agents · by wshobsonUnderstand anti-reversing, obfuscation, and protection techniques encountered during software analysis. Use this skill when analyzing malware evasion techniques, when implementing anti-debugging protections for CTF challenges, when reverse engineering packed binaries, or when building security research tools that need to detect virtualized environments.★ 39.9k GitHub starsSkillBuild production Apache Airflow DAGs with best practicesApache Airflow DAG Patternswshobson/agents · by wshobsonBuild production Apache Airflow DAGs with best practices for operators, sensors, testing, and deployment. Use when creating data pipelines, orchestrating workflows, or scheduling batch jobs.★ 39.9k GitHub stars