Aller au contenu
Infrastructure as Code medium
🔐 Alerte sécurité — Incident supply chain Trivy : lire mon analyse de l'attaque

Tester un module Terraform avec terraform test

12 min de lecture

logo terraform

terraform test exécute des assertions sur votre configuration, crée les ressources, vérifie les résultats, puis détruit tout automatiquement. C’est le framework de test natif de Terraform (depuis la version 1.6). Il permet de valider qu’un module produit les outputs attendus, que les valeurs par défaut sont correctes, et que les paramètres personnalisés sont bien appliqués — le tout sans laisser de ressources orphelines.

Prérequis : Terraform >= 1.6. Les exemples de ce site restent alignés sur la base projet Terraform >= 1.11, mais terraform test lui-même est bien disponible depuis la version 1.6. Avoir lu Créer un module Terraform et Variables et outputs.

  • Écrire des fichiers de test .tftest.hcl avec des assertions
  • Exécuter les tests avec terraform test
  • Distinguer les tests plan (validation) et apply (intégration)
  • Filtrer les tests par fichier
  • Lire les résultats d’échec pour diagnostiquer un problème

Les fichiers de test vont dans un dossier tests/ à la racine du projet :

mon-projet/
├── modules/
│ └── reseau/
│ ├── versions.tf
│ ├── variables.tf
│ ├── main.tf
│ └── outputs.tf
├── versions.tf
├── variables.tf
├── main.tf
├── outputs.tf
└── tests/
├── valeurs_par_defaut.tftest.hcl
├── parametres_custom.tftest.hcl
└── validation_plan.tftest.hcl

Les fichiers .tftest.hcl ne testent pas un module isolé dans le vide. Ils s’exécutent dans le projet racine où vous lancez terraform test. Cela signifie que la configuration racine doit déjà appeler le module à tester et exposer les outputs utilisés dans les assertions.

Dans ce guide, les tests supposent cette configuration minimale :

main.tf
module "reseau" {
source = "./modules/reseau"
nom = "test-reseau"
cidr = {
adresse = "10.10.90.0"
masque = "255.255.255.0"
}
plage_dhcp = {
debut = "10.10.90.10"
fin = "10.10.90.50"
}
}
outputs.tf
output "reseau_nom" {
value = module.reseau.nom
}
output "reseau_config" {
value = module.reseau.configuration
}

Sans ces outputs racine, une assertion comme output.reseau_nom échouera immédiatement avec une erreur du type Reference to undefined output.

Un fichier .tftest.hcl contient un ou plusieurs blocs run :

run "nom_du_test" {
command = apply
# ↑ apply (crée les ressources) ou plan (vérifie sans créer)
assert {
condition = output.reseau_nom == "test-reseau"
# ↑ expression booléenne qui doit être true
error_message = "Le nom du réseau devrait être 'test-reseau'"
# ↑ message affiché si la condition est false
}
assert {
condition = output.reseau_config.mode == "nat"
error_message = "Le mode par défaut devrait être 'nat'"
}
}
ÉlémentRôle
run "..."Bloc de test nommé
commandapply (intégration réelle) ou plan (validation sans déploiement)
assertAssertion à vérifier — plusieurs assertions par bloc run possibles
conditionExpression booléenne — true = test passé
error_messageMessage affiché si le test échoue

Le premier test vérifie que le module fonctionne correctement avec les valeurs par défaut de la configuration racine :

tests/valeurs_par_defaut.tftest.hcl
run "deployer_avec_defaults" {
command = apply
assert {
condition = output.reseau_nom == "test-reseau"
error_message = "Le nom du réseau devrait être 'test-reseau'"
}
assert {
condition = output.reseau_config.mode == "nat"
error_message = "Le mode par défaut devrait être 'nat'"
}
assert {
condition = output.reseau_config.dns_actif == true
error_message = "Le DNS devrait être activé par défaut"
}
assert {
condition = output.reseau_config.adresse == "10.10.90.0"
error_message = "L'adresse devrait être '10.10.90.0'"
}
}

Ce test utilise command = apply : Terraform crée réellement la ressource, vérifie les outputs, puis détruit automatiquement la ressource à la fin.

Écrire un test avec des paramètres personnalisés

Section intitulée « Écrire un test avec des paramètres personnalisés »

Le bloc variables au niveau du fichier permet de surcharger les valeurs :

tests/parametres_custom.tftest.hcl
variables {
nom = "custom-test"
cidr = {
adresse = "10.10.91.0"
masque = "255.255.255.0"
}
plage_dhcp = {
debut = "10.10.91.10"
fin = "10.10.91.50"
}
activer_dns = false
mode_forward = "route"
}
run "deployer_avec_custom" {
command = apply
assert {
condition = output.reseau_nom == "custom-test"
error_message = "Le nom devrait être 'custom-test'"
}
assert {
condition = output.reseau_config.mode == "route"
error_message = "Le mode devrait être 'route'"
}
assert {
condition = output.reseau_config.dns_actif == false
error_message = "Le DNS devrait être désactivé"
}
}

Le bloc variables s’applique à tous les blocs run du fichier.

Avec command = plan, Terraform vérifie les outputs prévus sans créer de ressource :

tests/validation_plan.tftest.hcl
run "verifier_plan" {
command = plan
assert {
condition = output.reseau_nom == "test-reseau"
error_message = "Le nom prévu devrait être 'test-reseau'"
}
}

Les tests plan sont plus rapides et ne nécessitent pas d’accès à l’infrastructure. Ils sont utiles pour valider la logique de la configuration sans effets de bord.

Fenêtre de terminal
$ terraform test
tests/parametres_custom.tftest.hcl... in progress
run "deployer_avec_custom"... pass
tests/parametres_custom.tftest.hcl... tearing down
tests/parametres_custom.tftest.hcl... pass
tests/valeurs_par_defaut.tftest.hcl... in progress
run "deployer_avec_defaults"... pass
tests/valeurs_par_defaut.tftest.hcl... tearing down
tests/valeurs_par_defaut.tftest.hcl... pass
tests/validation_plan.tftest.hcl... in progress
run "verifier_plan"... pass
tests/validation_plan.tftest.hcl... tearing down
tests/validation_plan.tftest.hcl... pass
Success! 3 passed, 0 failed.

Chaque fichier passe par trois phases :

  1. in progress — exécution du plan ou apply
  2. pass/fail — résultat des assertions
  3. tearing down — destruction automatique des ressources

Pour n’exécuter qu’un seul fichier de test :

Fenêtre de terminal
$ terraform test -filter=tests/validation_plan.tftest.hcl
run "verifier_plan"... pass
tests/validation_plan.tftest.hcl... tearing down
tests/validation_plan.tftest.hcl... pass
Success! 1 passed, 0 failed.

Quand une assertion échoue, Terraform affiche un diff entre la valeur réelle et la valeur attendue :

run "test_qui_echoue"... fail
│ Error: Test assertion failed
│ on tests/test_echec.tftest.hcl line 6, in run "test_qui_echoue":
│ 6: condition = output.reseau_nom == "mauvais-nom"
│ ├────────────────
│ │ Diff:
│ │ --- actual
│ │ +++ expected
│ │ - "test-reseau"
│ │ + "mauvais-nom"
│ Le nom devrait être 'mauvais-nom' (assertion volontairement fausse)
Failure! 2 passed, 1 failed.

Le diff indique clairement :

  • actual (-) : la valeur produite par Terraform
  • expected (+) : la valeur attendue dans l’assertion
ModeCrée des ressourcesVitesseCas d’usage
command = planNonRapideValidation de la logique, valeurs calculées, types
command = applyOui (puis détruit)Plus lentTest d’intégration, vérifier le comportement réel

La recommandation est d’utiliser les deux :

  • plan pour les tests rapides de validation (CI/CD, feedback immédiat)
  • apply pour les tests d’intégration avant un merge ou une release
PratiquePourquoi
Un fichier par scénarioLisibilité et filtrage facile
Noms de blocs run descriptifsDiagnostic rapide en cas d’échec
Tester les defaults séparémentDétecter les régressions sur les valeurs par défaut
Tester les paramètres customVérifier que les variables sont bien transmises
Utiliser plan quand possibleTests plus rapides, pas besoin d’infrastructure
Intégrer dans la CIExécuter terraform test automatiquement à chaque push
SymptômeCause probableSolution
command not found: testVersion Terraform < 1.6Mettre à jour Terraform (>= 1.6)
No test files foundFichiers pas dans tests/ ou mauvaise extensionVérifier l’extension .tftest.hcl et l’emplacement
Test apply échoue mais plan passeProblème côté provider/infrastructureVérifier la connectivité et les permissions
Ressources non détruites après un crashInterruption brutale pendant le testterraform destroy manuellement dans le dossier d’état
output.X non accessibleL’output n’est pas déclaré dans la config racineAjouter l’output dans outputs.tf de la racine
  1. terraform test exécute des fichiers .tftest.hcl depuis le dossier tests/
  2. Chaque bloc run contient une ou plusieurs assertions (assert)
  3. command = plan valide sans créer ; command = apply teste en conditions réelles
  4. Le teardown automatique détruit les ressources après chaque test — même en cas d’échec
  5. Le bloc variables permet de surcharger les valeurs pour tester différents scénarios
  6. L’option -filter permet d’exécuter un fichier de test spécifique
  7. Le diff dans les erreurs indique clairement la valeur réelle vs attendue

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn