From python-dev
Provides pytest patterns for Python testing: unit tests, integration tests, fixtures, mocking, async testing, and parametrized tests.
How this skill is triggered — by the user, by Claude, or both
Slash command
/python-dev:python-testingThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are a testing specialist for Python projects.
You are a testing specialist for Python projects.
conftest.py or pytest.ini → pytest[tool.pytest.ini_options] in pyproject.toml → pytestunittest imports → unittest (suggest migrating to pytest)tox.ini → tox runnernox → nox runnerimport pytest
from unittest.mock import Mock, AsyncMock, patch
class TestUserService:
@pytest.fixture
def mock_repository(self) -> Mock:
return Mock(spec=UserRepository)
@pytest.fixture
def service(self, mock_repository: Mock) -> UserService:
return UserService(mock_repository)
def test_get_user_returns_user_when_exists(
self, service: UserService, mock_repository: Mock
) -> None:
# Arrange
expected_user = User(id="1", name="Test", email="[email protected]")
mock_repository.find_by_id.return_value = expected_user
# Act
result = service.get_user("1")
# Assert
assert result == expected_user
mock_repository.find_by_id.assert_called_once_with("1")
def test_get_user_returns_none_when_not_exists(
self, service: UserService, mock_repository: Mock
) -> None:
# Arrange
mock_repository.find_by_id.return_value = None
# Act
result = service.get_user("unknown")
# Assert
assert result is None
@pytest.mark.parametrize("input_value,expected", [
("hello", "HELLO"),
("", ""),
("Hello World", "HELLO WORLD"),
])
def test_to_uppercase(input_value: str, expected: str) -> None:
assert to_uppercase(input_value) == expected
# Mock with spec for type safety
mock_repo = Mock(spec=UserRepository)
# Patch module-level dependencies
with patch("myapp.services.requests.get") as mock_get:
mock_get.return_value.json.return_value = {"id": "1"}
result = fetch_user("1")
# AsyncMock for async functions
mock_client = AsyncMock(spec=HttpClient)
mock_client.get.return_value = {"data": "value"}
Use the async plugin configured by the project (pytest-asyncio or pytest-anyio).
Note: Examples below use
@pytest.mark.asyncio(pytest-asyncio). If the project uses pytest-anyio, replace with@pytest.mark.anyio.
import pytest
from unittest.mock import AsyncMock
@pytest.mark.asyncio
async def test_async_fetch() -> None:
mock_session = AsyncMock()
mock_session.get.return_value.__aenter__.return_value.json = AsyncMock(
return_value={"id": "1"}
)
result = await fetch_data(mock_session, "http://example.com")
assert result == {"id": "1"}
@pytest.fixture
async def db_session():
"""Create a test database session."""
async with async_engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
async with AsyncSession(async_engine) as session:
yield session
async with async_engine.begin() as conn:
await conn.run_sync(Base.metadata.drop_all)
@pytest.mark.asyncio
async def test_create_and_fetch_user(db_session: AsyncSession) -> None:
repo = SqlAlchemyUserRepository(db_session)
user = User(name="Test", email="[email protected]")
await repo.save(user)
fetched = await repo.find_by_id(user.id)
assert fetched is not None
assert fetched.name == "Test"
from fastapi.testclient import TestClient
@pytest.fixture
def client() -> TestClient:
return TestClient(app)
def test_create_user(client: TestClient) -> None:
response = client.post("/users", json={"name": "Test", "email": "[email protected]"})
assert response.status_code == 201
assert response.json()["name"] == "Test"
# conftest.py - shared fixtures
import pytest
@pytest.fixture(scope="session")
def app_config() -> Config:
"""Application config for tests."""
return Config(api_url="http://test", timeout=5, debug=True)
@pytest.fixture
def temp_dir(tmp_path: "Path") -> "Path":
"""Temporary directory for file tests."""
return tmp_path
pytest-cov for coverage reports.env files or API keys in testsnpx claudepluginhub dmitriyyukhanov/claude-plugins --plugin python-devProvides pytest testing patterns for Python projects: test structure, fixtures, parametrize, conftest.py, mocking with unittest.mock and monkeypatch, and coverage with pytest-cov.
Guides Python testing with pytest: TDD cycle, fixture patterns, mocking, parametrization, and 80%+ coverage targets. Activates when writing Python tests or setting up coverage infrastructure.
Defines Python testing strategies using pytest, TDD methodology, fixtures, mocking, parametrization, and coverage requirements. Activates when writing new Python code or designing test suites.