Accueil Nos publications Blog Comment faire du Test Driven Development (TDD) pour Ansible ? #1

Comment faire du Test Driven Development (TDD) pour Ansible ? #1

tdd-ansible-neosoft-vignette

Sommaire

  1. Il existe des techniques Test Driven Development (TDD) que nous pouvons adapter à l’infrastructure…
  2. Qu’est-ce que le développement piloté par les tests (TDD) ?
  3. Comment le TDD peut-il aider le développement de logiciels ?
  4. Comment peut-il être utile pour l’infrastructure ?

Il existe des techniques Test Driven Development (TDD) que nous pouvons adapter à l’infrastructure. Voici ce que nous allons couvrir dans cet article…

Il existe des techniques Test Driven Development (TDD) que nous pouvons adapter à l’infrastructure…

Voici ce que nous allons couvrir :

  • Qu’est-ce que le développement piloté par les tests (TDD) ?
  • Comment peut-il aider le développement de logiciels ?
  • Comment peut-il être utile pour l’infrastructure ?
  • Un exemple concret pour Ansible ?

Dans cet exemple, nous allons passer en revue le TDD d’une simple application en go.

Qu’est-ce que le développement piloté par les tests (TDD) ?

Le développement piloté par les tests (TDD) est une approche du développement logiciel qui écrit d’abord des tests pour une fonctionnalité, puis implémente cette fonctionnalité afin qu’elle réussisse les tests. Le premier test devrait échouer dès le départ et la fonction est conçue pour réussir. Nous continuons à exécuter les tests et à corriger notre implémentation jusqu’à ce que les tests réussissent.

  • Écrire un test pour la prochaine fonctionnalité que vous voulez ajouter.
  • Écrire le code fonctionnel jusqu’à ce que le test soit réussi.
  • Refaire l’ancien et le nouveau code pour le rendre bien structuré.

La façon la plus courante de se tromper en TDD est d’ignorer l’étape 3. La refactorisation de votre code pour le garder propre est une partie importante du processus, sinon vous vous retrouverez avec un désordre de fragments de code (au moins, ceux-ci auront des tests, donc c’est un résultat moins douloureux que la plupart des échecs de conception).

Prenons un exemple. Nous voulons mettre en place une calculatrice qui renvoie la valeur absolue de la somme de deux nombres. La fonctionnalité est décrite comme suit :

  • La calculatrice doit pouvoir additionner deux entiers.
  • La calculatrice doit pouvoir soustraire deux entiers.
  • La calculatrice doit pouvoir multiplier deux entiers.
  • La calculatrice doit pouvoir diviser deux entiers.

Pour la suite, je vais m’inspirer d’un excellent article disponible ici :

Initialisons notre projet en go : go mod init calculator

touch calculator.go

En TDD, on écrit notre premier test comme suit :

touch calculator_test.go

Maintenant, exécutons le code pour voir le résultat du test en exécutant go test -v

Comme vous pouvez le voir dans la console, undefined : addition signifie que la fonction addition n’est pas encore implémentée.

Donc, ajoutons la fonction addition dans calculator.go.

calculator.go

Nos tests devraient passer ! De même, nous ajouterons des tests pour les autres fonctions comme suit :

calculator_test.go

Nos tests ne passent plus, ajoutons les fonctions dans calculator.go comme suit :

calculator.go

Comment le TDD peut-il aider le développement de logiciels ?

Il existe de nombreux arguments en faveur du TDD et contre le TDD. Voici quelques “contres” :

  • Je préfère passer mon temps à construire des fonctionnalités plutôt qu’à écrire un tas de tests.
  • Il semble contre-intuitif d’écrire les tests en premier.
  • Les tests sont difficiles. Chaque fois que j’ai essayé d’écrire des tests, j’ai toujours fini par réécrire un tas de mon code fonctionnel pour le rendre testable.

Le TDD peut être frustrant au début, surtout si on l’applique à l’inverse, c’est-à-dire en écrivant notre code et ensuite, en passant un temps précieux à tout simuler.

Une fois le TDD adopté, voici ce qu’il apporte :

  • Il fait réfléchir à la fonctionnalité que nous sommes censés mettre en œuvre
  • Les tests sont plus faciles parce que nous les rendons testables dès le début
  • Notre code est plus propre parce que nous savons quelles fonctions nous devons aborder le moins possible
  • Nous prenons moins de temps, car nous n’avons pas à se rappeler ce qu’une fonction est censée faire
  • Lorsque nous lisons le code de quelqu’un, nous pouvons d’abord lire les tests pour savoir ce que ses fonctions sont censées faire.
  • Il ouvre la voie à l’automatisation de bout en bout

Bien sûr, il y a des avantages et des inconvénients à utiliser le TDD. L’utilisation du TDD est un choix personnel. 

Le défi suivant a été de trouver comment l’appliquer à Ansible.

Comment peut-il être utile pour l’infrastructure ?

Les principes fondamentaux du TDD dans le développement de logiciels sont les suivants :

  • Développer uniquement les fonctionnalités qui sont nécessaires
  • Exprimer la fonctionnalité en attentes humaines plutôt qu’en code
  • Organiser la plus petite unité de code pour mettre en œuvre la fonctionnalité ou la logique

Sur la base de ces concepts, l’infrastructure est assez similaire :

  • Ne créer / configurer que les ressources d’infrastructure qui sont nécessaires
  • Exprimer la configuration de manière déclarative, en utilisant les tests comme référence
  • Organiser le plus petit ensemble de ressources d’infrastructure pour répondre à une exigence de sécurité, de résilience ou d’exploitation

L’application du TDD à l’infrastructure contribue à l’approche globale des tests de l’infrastructure. Parfois, les ingénieurs se disent qu’ils sont découragés par la difficulté de tester l’infrastructure. Ils n’ont pas forcément accès à un environnement cloud sandbox ou à des ressources d’infrastructure. Par conséquent, les changements apportés sont poussés aveuglément vers la production. Le manque de “testabilité” de l’infrastructure est lié à la pyramide des tests. Elle postule que plus on monte dans la pyramide des tests, plus le type de test est coûteux en temps et en ressources (et donc en argent).

Sur cette pyramide de tests, les types de tests situés en haut de la pyramide sont plus coûteux à réaliser que les tests situés en bas de la pyramide.

Dans le cas du TDD, nous écrivons autant de tests unitaires que possible pour vérifier rapidement notre logique sans intégrations ou interactions compliquées.

Dans le cas de l’infrastructure, et si nous testions le contenu de la configuration pour une fonctionnalité minimale plutôt que l’intégration de plusieurs composants ?

L’écriture des tests avant l’implémentation nous oblige à réfléchir à la meilleure façon de vérifier rapidement une petite quantité de configuration, sans dépenser de ressources supplémentaires pour exécuter un test d’intégration complet ou un test de bout en bout.

Et pour découvrir le cas concret avec Ansible, voici la deuxième partie de l’article :