01 - Quelle stratégie de test pour quel projet
Ce que tu vas apprendre
- Pourquoi il n'existe pas de stratégie de test universelle
- Quel type de test privilegier selon l'architecture du projet
- La stratégie concrète utilisee sur paltemps.fr
- Comment décider ou mettre son effort de test
Prerequisites
Connaitre les types de tests (unit, intégration, e2e). Voir la pyramide des tests pour un rappel.
La question que personne ne pose
"Il faut tester." D'accord. Mais tester quoi ? Un junior qui debarque sur un projet CRUD avec 5 routes va écrire 40 tests unitaires sur des getters. Un autre va couvrir 100% des lignes de son fichier de config Docker Compose. Les deux perdent leur temps.
La bonne question c'est : quel test a le meilleur rapport effort/valeur pour MON projet ? Et la réponse depend entièrement de l'architecture.
CRUD simple (5 endpoints, peu de logique)
Une API REST basique : créer, lire, modifier, supprimer. Le code c'est essentiellement du mapping entre des requêtes HTTP et des requêtes SQL. Pas de regles métier complexes.
La stratégie :
- Unit tests : peu. Il n'y a quasiment rien a tester en isolation. Une fonction qui fait
db.insert(data)n'a pas besoin d'un test unitaire. - Intégration tests : beaucoup. C'est la que la valeur est. Tester que les requêtes SQL retournent les bonnes donnees, que les validations bloquent les mauvaises entrees, que les codes HTTP sont corrects.
- E2e : quelques-uns. Le happy path de chaque endpoint. Verifier que tout fonctionne de bout en bout.
typescript// Le test qui a le plus de valeur sur un CRUD
it("POST /users returns 400 if email is invalid", async () => {
const res = await app.handle(
new Request("http://localhost/api/users", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email: "pas-un-email", name: "Test" }),
})
);
expect(res.status).toBe(400);
});
API avec logique métier (architecture hexagonale)
Une API ou le domaine contient des regles. Des calculs de prix, des transitions d'état, des validations métier. Le genre de projet qu'on decrit dans la serie architecture hexagonale.
La stratégie change complètement :
- Unit tests : beaucoup. Sur le domaine. Entités, value objects, regles de calcul. C'est la que les bugs sont les plus dangereux et les tests les moins chers.
- Tests fonctionnels : modere. Sur les use cases, avec des fakes pour les ports. Verifier que l'orchestration fonctionne.
- Intégration : modere. Sur les repositories et les adaptateurs. Verifier que la persistence fonctionne.
- E2e : quelques-uns. Les parcours critiques seulement.
typescript// Le domaine merite des dizaines de tests unitaires
describe("Order", () => {
it("refuses discount above 50%", () => {
const order = Order.create({ items: [{ price: 100, qty: 1 }] });
expect(() => order.applyDiscount(0.6)).toThrow("Discount cannot exceed 50%");
});
it("calculates total with tax", () => {
const order = Order.create({ items: [{ price: 100, qty: 2 }] });
expect(order.totalWithTax(0.2)).toBe(240);
});
});
Frontend SPA
Une application React, Vue ou Svelte. Beaucoup de composants, des interactions utilisateur, des appels API.
La stratégie :
- Unit tests : sur les utils et helpers. Les fonctions de formatage, de validation, de transformation de donnees.
- Tests de composants : modere. Render + interactions. Verifier qu'un clic sur un bouton affiche le bon élément, qu'un formulaire envoie les bonnes donnees.
- E2e : sur les flows critiques. Login, checkout, formulaires multi-étapes. Tout ce qui traverse plusieurs pages.
Le piège classique en frontend : tester l'implementation plutot que le comportement. Un test qui vérifié qu'un useState a change de valeur ne sert a rien. Un test qui vérifié que l'utilisateur voit le bon message apres un clic, ca c'est utile.
Microservices
Plusieurs services qui communiquent entre eux. Le problème c'est l'intégration entre services.
- Unit + fonctionnel : par service. Chaque service a sa propre suite de tests.
- Tests de contrat : entre services. Verifier que le service A envoie bien ce que le service B attend. Voir la serie microservices pour le détail.
- E2e sur le flow complet : rarement. C'est cher, c'est lent, c'est fragile. A reserver pour les parcours les plus critiques. Une fois par jour en CI, pas a chaque push.
Le monolithe paltemps.fr
Voila ce qu'on fait concrètement sur paltemps.fr. C'est un monolithe Bun/Elysia avec un frontend intégré.
- Tests de contrat API pour toutes les routes. On utilise
app.handle()pour tester le routage Elysia sans serveur HTTP. C'est rapide et ca couvre les validations, les codes de retour, les headers. - Intégration pour le mail. On a un serveur SMTP de test et on vérifié que les mails partent avec le bon contenu. Pas de mock ici, un vrai envoi sur un serveur local.
- E2e Playwright pour le webmail et le deck (les deux interfaces utilisateur). Les parcours critiques : connexion, envoi de mail, gestion des contacts.
Les tests unitaires purs sont rares parce que la logique métier est simple. Si demain on ajoute un système de facturation avec des calculs complexes, on ajoutera des tests unitaires sur ce domaine.
Tableau recapitulatif
| Architecture | Unit | Intégration | Fonctionnel | E2e |
|---|---|---|---|---|
| CRUD simple | Peu | Beaucoup | - | Quelques |
| API hexagonale | Beaucoup | Modere | Modere | Quelques |
| Frontend SPA | Utils only | - | Composants | Flows critiques |
| Microservices | Par service | Contrats | Par service | Rarement |
| Monolithe paltemps.fr | Peu (domaine simple) | Mail, DB | Contrat API | Webmail, deck |
Mon conseil
Commence par les tests qui te font le plus peur de déployer sans. Si tu as une trouille bleue de casser le système de paiement, c'est la qu'il faut tester en premier. Si tu deploies sereinement les pages statiques mais que tu stresses sur les webhooks, teste les webhooks.
Pas besoin de couvrir tout le projet d'un coup. Ajoute des tests là où la douleur est réelle. Avec le temps, la couverture augmente naturellement.
Article précédent : 00 - Les tests dans un pipeline CI/CD
Article suivant : 02 - Coverage : le piège du 100%