testing-python
Stratégie de Tests Python 3.14+
Versions : Python 3.14+ | pytest 8.x | Ruff 0.8+ | mypy 1.13+ | Playwright
Stack recommandée 2026
| Type | Outil | Usage |
|---|---|---|
| Unit/Integration | pytest 8.x | Tests backend FastAPI/Django |
| Linting + Format | Ruff 0.8+ | 10-100× plus rapide que Black+Flake8 |
| Type checking | mypy 1.13+ strict | Vérification statique |
| E2E/Browser | Playwright | Tests frontend web |
| Mutation | Mutmut | Qualité des tests (score >= 80%) |
Sources : pytest, Ruff, Mutmut
Configuration pytest + Ruff + mypy
# pyproject.toml
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py", "*_test.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = "--cov=app --cov-report=term-missing --cov-fail-under=80"
[tool.ruff]
line-length = 88
target-version = "py314"
select = ["E", "F", "I", "N", "W", "UP", "B", "C4", "SIM"]
fix = true
[tool.mypy]
python_version = "3.14"
strict = true
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
Source : Ruff Configuration
Tests pytest avec fixtures
# tests/test_user_service.py
import pytest
from app.services.user_service import UserService
from app.models.user import User
@pytest.fixture
def user_service():
"""Fixture pour créer un service utilisateur avec dépendances mockées."""
return UserService(db=MockDatabase())
def test_create_user_returns_user_with_id(user_service):
# Arrange
user_data = {"name": "Alice", "email": "alice@example.com"}
# Act
user = user_service.create_user(user_data)
# Assert
assert user.id is not None
assert user.name == "Alice"
assert user.email == "alice@example.com"
Source : pytest fixtures
Mutation Testing avec Mutmut
# Installation
pip install mutmut
# Exécution
mutmut run
# Rapport
mutmut results
mutmut html # Génère rapport HTML
# Seuil minimum mutation score
mutmut run --min-msi=80
Philosophie : "Coverage mesure la quantité, mutation score mesure la qualité."
Source : Mutmut
Property-based Testing avec Hypothesis
# tests/test_calculator.py
from hypothesis import given, strategies as st
from app.calculator import calculate_total
@given(st.lists(st.floats(min_value=0, max_value=1000)))
def test_calculate_total_is_never_negative(prices):
"""Le total ne peut jamais être négatif."""
total = calculate_total(prices)
assert total >= 0
@given(st.lists(st.floats(min_value=0, max_value=1000)))
def test_calculate_total_order_independent(prices):
"""L'ordre des prix ne change pas le total."""
total1 = calculate_total(prices)
total2 = calculate_total(prices[::-1])
assert total1 == total2
Source : Hypothesis
Tests FastAPI avec pytest
# tests/test_api.py
from fastapi.testclient import TestClient
from app.main import app
client = TestClient(app)
def test_get_user_returns_200():
response = client.get("/users/123")
assert response.status_code == 200
assert response.json()["id"] == "123"
def test_create_user_validates_email():
response = client.post("/users", json={"name": "Bob", "email": "invalid"})
assert response.status_code == 422 # Validation error
Source : FastAPI Testing
Ruff — Linting + Formatting unifié
Remplace Black, isort, Flake8, pyupgrade — 10-100× plus rapide.
# Check
ruff check .
# Format
ruff format .
# Fix automatique
ruff check --fix .
Source : Ruff
mypy strict mode
# app/services/user_service.py
from typing import Protocol
class Database(Protocol):
def save(self, user: User) -> None: ...
class UserService:
def __init__(self, db: Database) -> None:
self._db = db
def create_user(self, data: dict[str, str]) -> User:
user = User(**data)
self._db.save(user)
return user
Source : mypy strict mode
Tests Playwright pour E2E
# tests/e2e/test_login.py
from playwright.sync_api import Page, expect
def test_user_can_login(page: Page):
page.goto("http://localhost:8000/login")
page.fill('input[name="email"]', "alice@example.com")
page.fill('input[name="password"]', "secret")
page.click('button[type="submit"]')
expect(page).to_have_url("http://localhost:8000/dashboard")
Source : Playwright Python
Voir @.claude/rules/07-testing.md pour principes transverses.
More from thebeardedbearsas/claude-craft
kiss-dry-yagni
Principes KISS, DRY, YAGNI. Use when reviewing code quality or refactoring.
96documentation
Documentation. Use when writing docs or reviewing documentation.
31solid-principles
SOLID principles for object-oriented design. Use when reviewing code quality, refactoring, designing classes or interfaces, or discussing architecture patterns.
23security
Security guidelines and OWASP Top 10. Use when reviewing security, implementing authentication or authorization, hardening code, or discussing vulnerabilities.
22testing
TDD/BDD testing principles. Use when writing tests, reviewing test coverage, setting up testing, or discussing test strategy and test architecture.
21workflow-analysis
Workflow d'Analyse Obligatoire. Use when working with workflow analysis.
20