Contrats internes
Contract testing, consumer-driven contracts, Pact et conception contract-first pour garantir la compatibilité entre services.
Que sont les contrats internes ?
Dans un système distribué, chaque service expose des interfaces que d’autres services consomment. Un contrat interne est l’accord — explicite ou implicite — sur la forme, les types et la sémantique de ces interfaces. Quand un service modifie son contrat sans se coordonner avec ses consommateurs, tout casse.
Les contrats internes formalisent ces dépendances afin qu’elles puissent être vérifiées automatiquement, avant qu’un changement n’arrive en production.
Contract Testing
Le contract testing vérifie que deux services (producteur et consommateur) sont d’accord sur la forme de leur communication. Contrairement aux tests d’intégration end-to-end, les contract tests s’exécutent de manière indépendante sur chaque service.
Pourquoi les tests d’intégration ne suffisent-ils pas ?
- Les tests d’intégration nécessitent que tous les services tournent simultanément
- Ils sont lents, fragiles et difficiles à maintenir
- Ils ne passent pas à l’échelle quand on a des dizaines de services
- Un échec n’indique pas toujours clairement quel service a rompu le contrat
Comment fonctionne le contract testing
- Le consommateur définit ce qu’il attend du producteur (le contrat)
- Le contrat est vérifié par rapport au producteur de manière indépendante
- Si le producteur respecte le contrat, les deux services sont compatibles
- S’il ne le respecte pas, le test échoue avant d’arriver en production
Consumer-Driven Contracts (CDC)
Dans l’approche consumer-driven, ce sont les consommateurs qui définissent les contrats. Cela inverse la dynamique traditionnelle où le producteur définit son API et les consommateurs s’adaptent.
Workflow CDC
- Le consommateur écrit un contrat : il définit les interactions dont il a besoin — quelles requêtes il fait et quelles réponses il attend
- Le contrat est partagé : il est publié dans un broker ou un dépôt partagé
- Le producteur vérifie : il exécute les contrats de tous ses consommateurs contre son implémentation
- Feedback rapide : si un changement chez le producteur casse un contrat, le pipeline échoue
Avantages de l’approche CDC
- Les producteurs savent exactement ce qu’utilisent leurs consommateurs
- On peut faire des changements breaking en toute confiance — on sait qui est affecté
- Les consommateurs ne définissent que ce dont ils ont réellement besoin, pas toute l’API
- Cela réduit le couplage — le producteur peut modifier ce que personne n’utilise
Pact
Pact est l’outil le plus populaire pour le consumer-driven contract testing. Il prend en charge plusieurs langages (Java, JavaScript, Python, Go, .NET, Ruby) et propose un flux complet.
Concepts clés de Pact
- Pact file : fichier JSON qui décrit les interactions attendues entre consommateur et producteur
- Pact Broker : service centralisé qui stocke et gère les pact files
- Can-I-Deploy : outil qui vérifie s’il est sûr de déployer une version donnée
Flux typique avec Pact
Consumidor Pact Broker Productor
| | |
|-- genera pact file --------->| |
| | |
| |<-- descarga pact files ------|
| | |
| |<-- publica resultados -------|
| | |
|-- can-i-deploy? ------------>| |
|<-- sí/no -------------------| |
Exemple d’interaction Pact
Côté consommateur, on définit l’interaction attendue :
Dado: que existe un producto con ID 123
Cuando: hago GET /api/products/123
Entonces: recibo status 200 con body { id: 123, name: "string", price: "number" }
Côté producteur, Pact rejoue l’interaction contre l’implémentation réelle et vérifie que la réponse correspond.
Conception Contract-First
Dans l’approche contract-first, le contrat est défini avant d’écrire la moindre ligne de code. C’est particulièrement utile quand plusieurs équipes travaillent en parallèle.
Flux contract-first
- Définir le contrat : en utilisant OpenAPI, AsyncAPI, Protobuf ou un autre format de spécification
- Revoir et se mettre d’accord : les équipes productrice et consommatrice examinent et approuvent le contrat
- Générer le code : utiliser des outils de génération de code pour créer des stubs, des clients et des validateurs
- Implémenter : chaque équipe implémente sa partie en respectant le contrat convenu
- Vérifier : des contract tests automatiques valident que les deux implémentations respectent le contrat
Outils pour le contract-first
| Outil | Type | Usage |
|---|---|---|
| OpenAPI / Swagger | REST APIs | Définition des endpoints, schémas et exemples |
| AsyncAPI | Event-driven | Définition des channels, messages et schémas |
| Protobuf | gRPC | Définition de services et messages typés |
| JSON Schema | Général | Validation des structures de données |
Bonnes pratiques
- Commencez par contract-first pour les nouvelles API — c’est plus facile que d’ajouter des contrats après coup
- Utilisez un Pact Broker (ou équivalent) pour centraliser et versionner les contrats
- Intégrez les contract tests dans la CI/CD — pour qu’ils échouent avant d’arriver en staging
- Ne testez pas toute l’API dans le contrat du consommateur — seulement ce que vous utilisez réellement
- Versionnez les contrats avec le code — un contrat est aussi important que le code qui l’implémente
- Relisez les contrats en code review — un changement de contrat mérite la même attention qu’un changement de schéma de base de données