Python testing
Skill Mattakushi432/Claude-Code-Skills-Custom-DevTools-Pack/plugins/devtools-pack/skills/python-testing
When to activate: pytest, TDD, test fixtures, parametrize, async tests, coverage, mocking, hypothesisFrom its SKILL.md
npx -y skills add Mattakushi432/Claude-Code-Skills-Custom-DevTools-Pack --skill python-testingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
4.0 KB, 912 tokens by cl100k_base, as published. Nobody here has run it
Python Testing Patterns
pytest Setup
# pyproject.toml
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
addopts = ["--strict-markers", "-ra"]
[tool.coverage.run]
source = ["app"]
omit = ["tests/*", "*/migrations/*"]
[tool.coverage.report]
fail_under = 80
Fixture Patterns
import pytest
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from httpx import AsyncClient, ASGITransport
# Scope: session for expensive setup, function for isolation
@pytest.fixture(scope="session")
async def engine():
engine = create_async_engine("postgresql+asyncpg://test:test@localhost/test_db")
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
yield engine
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.drop_all)
@pytest.fixture
async def db(engine) -> AsyncGenerator[AsyncSession, None]:
async with AsyncSession(engine) as session:
yield session
await session.rollback() # isolation between tests
@pytest.fixture
async def client(app) -> AsyncGenerator[AsyncClient, None]:
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as ac:
yield ac
# Factory fixtures
@pytest.fixture
def user_factory(db):
async def _create(**kwargs) -> User:
defaults = {"email": "[email protected]", "name": "Test User"}
return await user_service.create(db, {**defaults, **kwargs})
return _create
Parametrize Patterns
@pytest.mark.parametrize("email,expected", [
("[email protected]", True),
("invalid-email", False),
("", False),
("[email protected]", True),
])
def test_email_validation(email: str, expected: bool) -> None:
assert is_valid_email(email) == expected
# Parametrize with IDs for readable output
@pytest.mark.parametrize("status_code,expected_error", [
pytest.param(400, "bad_request", id="bad-request"),
pytest.param(404, "not_found", id="not-found"),
pytest.param(422, "validation_error", id="validation"),
], ids=...)
Async Tests
# asyncio_mode = "auto" in pyproject.toml means no @pytest.mark.asyncio needed
async def test_create_user(client: AsyncClient, db: AsyncSession) -> None:
response = await client.post("/api/v1/users", json={
"email": "[email protected]",
"password": "securepass123",
"name": "New User",
})
assert response.status_code == 201
data = response.json()
assert data["email"] == "[email protected]"
assert "password" not in data # PII not leaked
Mocking Patterns
from unittest.mock import AsyncMock, patch, MagicMock
# Patch at the usage site, not the definition site
async def test_sends_email_on_signup(client: AsyncClient) -> None:
with patch("app.services.email.send_welcome_email", new_callable=AsyncMock) as mock_email:
response = await client.post("/api/v1/users", json={...})
assert response.status_code == 201
mock_email.assert_called_once_with(email="[email protected]")
# Use respx for HTTP mocking in async context
import respx
import httpx
@respx.mock
async def test_external_api_call() -> None:
respx.get("https://api.example.com/data").mock(
return_value=httpx.Response(200, json={"value": 42})
)
result = await fetch_external_data()
assert result == 42
Property-Based Tests
from hypothesis import given, strategies as st
@given(
email=st.emails(),
name=st.text(min_size=1, max_size=100),
)
def test_user_creation_never_raises_for_valid_input(email: str, name: str) -> None:
user = UserCreate(email=email, name=name, password="valid123")
assert user.email == email
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.