From ftitos-claude-code
Python testing strategies using pytest, TDD methodology, fixtures, mocking, parametrization, and coverage requirements.
npx claudepluginhub nassimbf/ftitos-claude-codeThis skill uses the workspace's default tool permissions.
Comprehensive testing strategies for Python applications using pytest, TDD methodology, and best practices.
Guides Next.js Cache Components and Partial Prerendering (PPR): 'use cache' directives, cacheLife(), cacheTag(), revalidateTag() for caching, invalidation, static/dynamic optimization. Auto-activates on cacheComponents: true.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Share bugs, ideas, or general feedback.
Comprehensive testing strategies for Python applications using pytest, TDD methodology, and best practices.
Always follow the TDD cycle:
# Step 1: Write failing test (RED)
def test_add_numbers():
result = add(2, 3)
assert result == 5
# Step 2: Write minimal implementation (GREEN)
def add(a, b):
return a + b
# Step 3: Refactor if needed (REFACTOR)
pytest --cov to measure coveragepytest --cov=mypackage --cov-report=term-missing --cov-report=html
import pytest
def test_addition():
"""Test basic addition."""
assert 2 + 2 == 4
def test_string_uppercase():
"""Test string uppercasing."""
text = "hello"
assert text.upper() == "HELLO"
# Equality
assert result == expected
# Truthiness
assert result # Truthy
assert not result # Falsy
assert result is None # Exactly None
# Membership
assert item in collection
# Type checking
assert isinstance(result, str)
# Exception testing (preferred approach)
with pytest.raises(ValueError):
raise ValueError("error message")
# Check exception message
with pytest.raises(ValueError, match="invalid input"):
raise ValueError("invalid input provided")
@pytest.fixture
def sample_data():
return {"name": "Alice", "age": 30}
def test_sample_data(sample_data):
assert sample_data["name"] == "Alice"
@pytest.fixture
def database():
db = Database(":memory:")
db.create_tables()
db.insert_test_data()
yield db # Provide to test
db.close() # Teardown
@pytest.fixture # Function scope (default)
def temp_file(): ...
@pytest.fixture(scope="module") # Once per module
def module_db(): ...
@pytest.fixture(scope="session") # Once per session
def shared_resource(): ...
# tests/conftest.py
@pytest.fixture
def client():
app = create_app(testing=True)
with app.test_client() as client:
yield client
@pytest.mark.parametrize("input,expected", [
("hello", "HELLO"),
("world", "WORLD"),
("PyThOn", "PYTHON"),
])
def test_uppercase(input, expected):
assert input.upper() == expected
@pytest.mark.parametrize("a,b,expected", [
(2, 3, 5),
(0, 0, 0),
(-1, 1, 0),
])
def test_add(a, b, expected):
assert add(a, b) == expected
@pytest.mark.slow
def test_slow_operation(): ...
@pytest.mark.integration
def test_api_integration(): ...
pytest -m "not slow" # Skip slow tests
pytest -m integration # Only integration tests
from unittest.mock import patch, Mock
@patch("mypackage.external_api_call")
def test_with_mock(api_call_mock):
api_call_mock.return_value = {"status": "success"}
result = my_function()
api_call_mock.assert_called_once()
assert result["status"] == "success"
# Mocking exceptions
@patch("mypackage.api_call")
def test_api_error_handling(api_call_mock):
api_call_mock.side_effect = ConnectionError("Network error")
with pytest.raises(ConnectionError):
api_call()
import pytest
@pytest.mark.asyncio
async def test_async_function():
result = await async_add(2, 3)
assert result == 5
tests/
├── conftest.py
├── unit/
│ ├── test_models.py
│ └── test_services.py
├── integration/
│ └── test_api.py
└── e2e/
└── test_user_flow.py
test_user_login_with_invalid_credentials_failspytest.raisespytest # Run all tests
pytest tests/test_utils.py # Run specific file
pytest -v # Verbose output
pytest --cov=mypackage # With coverage
pytest -m "not slow" # Skip slow tests
pytest -x # Stop on first failure
pytest --lf # Run last failed
pytest -k "test_user" # Run tests matching pattern
| Pattern | Usage |
|---|---|
pytest.raises() | Test expected exceptions |
@pytest.fixture() | Create reusable test fixtures |
@pytest.mark.parametrize() | Run tests with multiple inputs |
@patch() | Mock functions and classes |
tmp_path fixture | Automatic temp directory |
pytest --cov | Generate coverage report |