Apprendre à générer des tests de qualité avec l’IA et à les valider.
##Étape 1 : Identifier une fonction à tester
# Choisir une fonction
cat src/services/user_service.py
##Étape 2 : Prompt structuré pour tests
Generate comprehensive tests for user_service.create_user():
Coverage requirements:
1. Happy path: user created successfully
2. Duplicate email: raises ValidationError
3. Invalid email format: raises ValidationError
4. Missing fields: raises ValidationError
5. Database error: handles gracefully
Use pytest with fixtures from tests/conftest.py.
Assert on:
- Return value (User object)
- Database state (user exists)
- Error messages (informative)
File: tests/test_user_service.py
##Étape 3 : Valider les tests générés
Checklist de validation :
##Étape 1 : Mesurer lecoverage
# Lancer avec coverage
pytest tests/ --cov=src --cov-report=html
# Voir le rapport
open htmlcov/index.html
##Étape 2 : Identifier les manques
Chercher les lignes non couvertes :
# Lignes manquantes
grep "MISSING" htmlcov/index.html
##Étape 3 : Demander des tests pour les manques
Generate tests to cover these uncovered lines:
[Lignes non couvertes]
Focus on edge cases and error paths.
##Étape 1 : Créer un test fragile
# tests/test_fragile.py
def test_global_state():
# Ce test dépend de l'état global
assert len(User.query.all()) == 0
create_user("test@example.com")
assert len(User.query.all()) == 1
Lancer plusieurs fois :
##Étape 2 : Corriger le test
# tests/test_robust.py
def test_with_clean_state(db):
# Utiliser un fixture qui nettoie
initial = len(User.query.all())
create_user("test@example.com")
assert len(User.query.all()) == initial + 1
# Cleanup automatique via fixture
##Étape 1 : Écrire le test d’abord
# tests/test_new_feature.py
def test_user_avatar_upload():
"""Test qu'un utilisateur peut uploader un avatar."""
user = create_user()
token = get_auth_token(user)
response = client.post(
f"/users/{user.id}/avatar",
headers={"Authorization": f"Bearer {token}"},
files={"file": ("avatar.png", b"PNGDATA", "image/png")}
)
assert response.status_code == 201
assert "url" in response.json()
##Étape 2 : Demander l’implémentation
Make this test pass:
```python
[test content]
Constraints:
---
##Étape 3 : Vérifier
```bash
# Les tests passent ?
pytest tests/test_new_feature.py -v
# L'implémentation est propre ?
cat src/api/routes/users.py
##Étape 1 : Pre-commit
# Installer pre-commit
pip install pre-commit
# Créer le fichier
cat > .pre-commit-config.yaml << 'EOF'
repos:
- repo: local
hooks:
- id: test
name: Run tests
entry: pytest tests/
language: system
pass_filenames: false
- id: lint
name: Run linters
entry: make lint
language: system
pass_filenames: false
EOF
# Activer
pre-commit install
##Étape 2 : Tester le pre-commit
# Essayer de commit sans tests
git add .
git commit -m "test"
# Le pre-commit devrait bloquer si tests échouent
À la fin de ce TP :
Pattern retenu : Tests générés = à valider manuellement.
Question clé : Quel pourcentage decoverage visez-vous ?
Module 10 : Conventions d’équipe et tensions.