Terratest : tester son infrastructure
Dans les pratiques DevOps modernes, l'Infrastructure-as-Code a révolutionné la manière de gérer les environnements. Mais une question demeure souvent négligée : comment s'assurer que l'infrastructure déployée fonctionne réellement comme prévu ? Comment valider qu'un module Terraform crée bien les ressources attendues avec les bonnes configurations ? Comment détecter une régression avant qu'elle n'impacte la production ? Ces interrogations, familières aux équipes qui maintiennent des infrastructures complexes, trouvent leur réponse dans une pratique encore trop peu répandue : le test d'infrastructure.

Dans les pratiques DevOps modernes, l'Infrastructure-as-Code a révolutionné la manière de gérer les environnements. Mais une question demeure souvent négligée : comment s'assurer que l'infrastructure déployée fonctionne réellement comme prévu ? Comment valider qu'un module Terraform crée bien les ressources attendues avec les bonnes configurations ? Comment détecter une régression avant qu'elle n'impacte la production ? Ces interrogations, familières aux équipes qui maintiennent des infrastructures complexes, trouvent leur réponse dans une pratique encore trop peu répandue : le test d'infrastructure.
Véritable extension des bonnes pratiques de développement logiciel au monde de l'infrastructure, Terratest est une bibliothèque Go développée par Gruntwork qui permet d'écrire des tests automatisés pour le code d'infrastructure. Là où les équipes testent rigoureusement leur code applicatif, l'infrastructure reste souvent validée manuellement ou par simple inspection visuelle des plans Terraform. Terratest change cette donne en permettant de déployer réellement l'infrastructure dans un environnement de test, d'exécuter des validations, puis de tout détruire automatiquement. Adopté par des organisations soucieuses de fiabilité comme HashiCorp, Gruntwork ou encore de nombreuses équipes Platform Engineering, Terratest apporte au monde de l'infrastructure la rigueur des tests automatisés qui a fait ses preuves dans le développement logiciel.
Pourquoi tester son infrastructure ?
L'Infrastructure-as-Code a transformé la gestion des environnements en permettant de versionner, reviewer et automatiser les déploiements. Terraform, Pulumi ou CloudFormation décrivent l'état souhaité de l'infrastructure, et les outils se chargent de converger vers cet état. Pourtant, une question fondamentale reste souvent sans réponse : le code fait-il réellement ce qu'on attend de lui ?
Un terraform plan montre les changements prévus, mais ne garantit pas que l'infrastructure résultante fonctionnera correctement. Un module peut créer les bonnes ressources tout en oubliant une règle de security group critique. Un réseau peut être provisionné avec des CIDR qui se chevauchent. Une base de données peut être créée sans les paramètres de performance appropriés. Ces problèmes ne se manifestent souvent qu'en production, avec les conséquences que l'on imagine.
Les bénéfices du test d'infrastructure sont multiples :
- Détection précoce des erreurs : identifier les problèmes avant qu'ils n'atteignent la production, réduisant le coût et l'impact des corrections.
- Confiance dans les modifications : refactorer un module Terraform devient moins risqué quand une suite de tests valide son comportement.
- Documentation vivante : les tests constituent une spécification exécutable de ce que l'infrastructure doit accomplir.
- Validation de bout en bout : contrairement à une simple validation syntaxique, les tests d'intégration vérifient que l'infrastructure fonctionne réellement.
- Régression évitée : s'assurer qu'une modification n'a pas cassé un comportement existant.
L'approche traditionnelle consistant à "tester en staging" présente des limitations significatives. Le staging est souvent différent de la production (taille réduite, données synthétiques), et les tests manuels sont lents, non reproductibles et sujets aux oublis. Terratest propose une alternative : des tests automatisés, reproductibles et intégrables dans une pipeline CI/CD.
Terratest : fonctionnement et concepts clés
Terratest est une bibliothèque Go qui fournit des fonctions et des patterns pour tester du code d'infrastructure. Son approche est pragmatique : plutôt que de simuler ou de mocker l'infrastructure, Terratest la déploie réellement, exécute des validations, puis la détruit. Cette philosophie de test d'intégration garantit que les tests reflètent fidèlement le comportement en production.

Le cycle de vie typique d'un test Terratest suit un pattern classique :
- Setup : configuration des options Terraform (répertoire du module, variables d'entrée).
- Deploy : exécution de
terraform initetterraform applypour créer l'infrastructure. - Validate : vérifications que l'infrastructure créée répond aux attentes (appels API, requêtes HTTP, connexions réseau).
- Teardown : exécution de
terraform destroypour nettoyer les ressources, même en cas d'échec des tests.
package test
import (
"testing"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/gruntwork-io/terratest/modules/http-helper"
"time"
)
func TestWebServerModule(t *testing.T) {
t.Parallel()
terraformOptions := &terraform.Options{
TerraformDir: "../modules/webserver",
Vars: map[string]interface{}{
"instance_type": "t3.micro",
"environment": "test",
},
}
// Garantit la destruction même en cas d'échec
defer terraform.Destroy(t, terraformOptions)
// Déploie l'infrastructure
terraform.InitAndApply(t, terraformOptions)
// Récupère l'output Terraform
serverURL := terraform.Output(t, terraformOptions, "server_url")
// Valide que le serveur répond correctement
http_helper.HttpGetWithRetry(t, serverURL, nil, 200, "Hello, World!", 30, 5*time.Second)
}
go
Cet exemple illustre la puissance de Terratest : en quelques lignes, on déploie un module, on vérifie que le serveur web répond correctement, et on nettoie automatiquement. Le defer terraform.Destroy garantit que les ressources sont supprimées même si le test échoue, évitant l'accumulation de ressources orphelines.
Terratest fournit des modules helpers pour interagir avec différents systèmes :
| Module | Fonction | Exemple d'usage |
|---|---|---|
| terraform | Exécution de commandes Terraform | Apply, Destroy, Output |
| aws | Interactions avec l'API AWS | Vérifier les propriétés d'une instance EC2 |
| k8s | Interactions avec Kubernetes | Vérifier qu'un Pod est Running |
| http-helper | Tests HTTP | Valider les endpoints d'une API |
| ssh | Connexions SSH | Exécuter des commandes sur une instance |
| docker | Interactions Docker | Tester des images localement |
Cette richesse de modules permet de valider l'infrastructure à différents niveaux : vérifier qu'une ressource existe via l'API du provider, tester qu'un service répond correctement, exécuter des commandes sur les instances déployées.
Bonnes pratiques et stratégies de test
L'écriture de tests d'infrastructure efficaces requiert une approche réfléchie pour équilibrer la couverture, le temps d'exécution et la maintenabilité.
Structurer ses tests par niveau
Une stratégie efficace consiste à organiser les tests en plusieurs niveaux, du plus rapide au plus complet. Les tests unitaires valident la syntaxe et la logique des modules sans déploiement réel (validation Terraform, linting). Les tests d'intégration légers déploient des modules individuels de manière isolée pour valider leur comportement. Les tests end-to-end déploient une infrastructure complète et valident les interactions entre composants.
Cette pyramide de tests permet d'obtenir un feedback rapide sur les erreurs simples tout en conservant une validation complète pour les changements majeurs. Les tests unitaires s'exécutent en secondes dans chaque PR, tandis que les tests end-to-end peuvent être réservés aux merges sur la branche principale.
Gérer l'isolation et le parallélisme
Les tests d'infrastructure créent de vraies ressources, ce qui pose des défis d'isolation. Deux tests exécutés en parallèle ne doivent pas interférer. Terratest encourage l'utilisation de noms uniques générés dynamiquement :
uniqueID := random.UniqueId()
terraformOptions := &terraform.Options{
TerraformDir: "../modules/vpc",
Vars: map[string]interface{}{
"vpc_name": fmt.Sprintf("test-vpc-%s", uniqueID),
},
}
go
Cette approche permet d'exécuter les tests en parallèle (t.Parallel()) sans collision de noms, réduisant significativement le temps total d'exécution de la suite de tests.
Optimiser les coûts et le temps
Déployer de l'infrastructure réelle a un coût, tant financier que temporel. Plusieurs stratégies permettent de l'optimiser :
- Utiliser des instances minimales : un
t3.microsuffit souvent pour valider le comportement d'un module. - Limiter la durée des tests : définir des timeouts appropriés pour éviter les tests qui s'éternisent.
- Nettoyer systématiquement : le pattern
defer terraform.Destroyest essentiel pour éviter les ressources oubliées. - Utiliser des comptes/projets dédiés : isoler les tests dans un compte AWS ou projet GCP dédié facilite le suivi des coûts et le nettoyage périodique.
- Tester localement quand possible : pour les modules Docker ou Kubernetes, des environnements locaux (Kind, Minikube) réduisent les coûts.
Terratest face aux alternatives
Le marché des outils de test d'infrastructure propose plusieurs approches, chacune avec ses compromis.
Kitchen-Terraform (Test Kitchen avec le driver Terraform) adopte une approche similaire à Terratest avec un déploiement réel, mais utilise InSpec pour les assertions. Son écosystème Ruby peut représenter une friction pour les équipes non familières avec ce langage.
Checkov et tfsec se concentrent sur l'analyse statique du code Terraform, détectant les problèmes de sécurité et de conformité sans déploiement. Ces outils sont complémentaires à Terratest : ils valident la configuration avant déploiement, tandis que Terratest valide le comportement après.
Open Policy Agent (OPA) avec Conftest permet de définir des policies en Rego pour valider les plans Terraform. Comme l'analyse statique, cette approche ne teste pas l'infrastructure réelle mais valide la conformité du code.
| Critère | Terratest | Kitchen-Terraform | Checkov/tfsec | OPA/Conftest |
|---|---|---|---|---|
| Type de test | Intégration (déploiement réel) | Intégration | Analyse statique | Policy-as-Code |
| Langage | Go | Ruby/InSpec | Python/YAML | Rego |
| Coût d'exécution | Ressources Cloud réelles | Ressources Cloud réelles | Aucun | Aucun |
| Temps d'exécution | Minutes | Minutes | Secondes | Secondes |
| Validations possibles | Comportement réel | Comportement réel | Configuration | Configuration |
Terratest se distingue par sa philosophie de test réel : là où l'analyse statique peut manquer des problèmes qui n'apparaissent qu'au runtime (permissions IAM insuffisantes, quotas dépassés, incompatibilités de versions), Terratest les détecte en déployant réellement l'infrastructure. Le choix de Go comme langage offre également l'avantage d'un typage fort et d'excellentes performances, particulièrement appréciables pour des suites de tests conséquentes.
L'approche recommandée combine ces outils : analyse statique (Checkov, tfsec) dans chaque PR pour un feedback rapide, policies OPA pour la conformité, et Terratest pour la validation complète du comportement.
À découvrir : notre formation DevOps Engineer
Conclusion
Terratest apporte au monde de l'Infrastructure-as-Code une rigueur de test longtemps réservée au développement applicatif. En permettant de déployer, valider et détruire automatiquement l'infrastructure dans des environnements de test, il transforme la gestion des modules Terraform d'un exercice basé sur la confiance en un processus validé par des preuves concrètes. Cette approche réduit drastiquement le risque de déployer du code d'infrastructure défaillant en production.
Au-delà de la détection des bugs, Terratest instaure une culture de qualité dans les équipes Platform et DevOps. Les développeurs peuvent refactorer leurs modules avec confiance, sachant qu'une suite de tests validera leur comportement. Les code reviews deviennent plus efficaces quand les tests documentent les attentes. Pour les organisations qui investissent sérieusement dans l'Infrastructure-as-Code et cherchent à atteindre le même niveau de maturité que pour leur code applicatif, Terratest représente un investissement stratégique qui transforme la fiabilité de l'infrastructure d'un espoir en une garantie mesurable.


