Un test peut en cacher un autre - Tests d'intégration - P1

le 18/08/2020 par Mickael Wegerich
Tags: Software Engineering

Introduction

L’article d’introduction débute en listant certaines différences de visions que je peux avoir avec d'autres développeurs concernant l'architecture applicative ou encore la rédaction des tests. À travers elles, j’évoque les difficultés qu’ils peuvent rencontrer à identifier précisément quoi tester et comment.

Nous avons pu voir dans ces articles autour des tests unitaires :

Que ces tests sont exclusivement centrés sur les règles métiers qui sont validées via de fausses implémentations.

À un moment, il va falloir réaliser des implémentations afin de pouvoir sauvegarder en base de données, envoyer un SMS ou encore afficher des données à l'utilisateur.

Ici, nous allons nous focaliser sur les tests d'intégration des adaptateurs de gauche ou encore adaptateurs primaires, il existe d'autres synonymes. Pour connaître leurs particularités, je vous conseille ces articles :

Dans l’article : Un test peut en cacher un autre — Tests d’intégration — P2 nous nous attardons davantage sur les tests des adaptateurs de droite.


Kata

On va travailler avec un Kata qui sera la gestion d’un système de réservation de livres dans une librairie, dont les règles sont les suivantes :

  • Un client peut ajouter des livres dans son panier
  • Le client peut visualiser les informations du panier (prix et livres ajoutés)
  • Le panier est sauvegardé
  • Tous les livres coûtent 8€
  • Le prix du panier varie en fonction du nombre de livres identiques ajoutés :
    • 2 livres identiques donne une réduction de 5% de la somme du prix des 2 livres
    • 3 livres et plus identiques donne une réduction de 25% de la somme du prix des n livres
    • Exemple pour l’achat de :
      • 2 fois le livre 1
      • 3 fois le livre 2
      • 4 fois le livre 3
      • 1 fois le livre 4
      • 1 fois le livre 5
      • Le montant du panier est égale à 73,20€
  • Quand le client emprunte des livres :
    • Les livres ne sont plus disponibles (stock de 1)
    • Un SMS est envoyé
    • Un email est envoyé
  • Quand le client retourne des livres :
    • Les livres sont disponibles
    • Un email est envoyé

NDR : le code est en TypeScript, qui propose un typage statique fort. Néanmoins, le code peut être transposé dans des langages comme JavaScript, Python ou PHP qui ont nativement un typage dynamique et faible pour certains.


Les tests d'intégration (TI)

Ces tests ont pour but de s’assurer que les implémentations choisies s'intègrent bien avec nos Use Cases et respectent bien un port défini (le contrat). Ils ont en point d’entrée l’Adaptateur. Ils sont fortement couplés à un choix d'architecture (librairie, framework, technologie, etc.).

On fera de manière intelligente un ou quelques cas passant et non passant, si ces derniers existent. Le tout en évitant de re tester les règles métiers, car c’est déjà fait ! On souhaite uniquement savoir si l'interaction avec la base de données choisie fonctionnent, que notre appel HTTP s'effectue bien, etc.

Adaptateur utilisant les Use Cases (à gauche**/primaire****)**

Test de composant (front end)

Comment s’affiche le composant en donnant telles données. Est-ce que je fais bien la bonne action quand j’appuie sur ce bouton, etc.

https://gist.github.com/mickaelw/479192a4da649110b4a6be2c5b9bad95

https://gist.github.com/mickaelw/045c7255d54b6e7026226b233ae41f2a

Ici, vérification uniquement de cas passant :

  • L’affichage avec le snapshot proposé par Jest
  • Action au cycle de vie du composant
  • Action quand on clique sur un bouton

À noter le passage des dépendances en Props/Input/Entrée du composant.

Un autre style de composant :

https://gist.github.com/mickaelw/4be2434cc0277b85d3b81bda4c2f134f

https://gist.github.com/mickaelw/8426952250d2108ebb3ef7f40faba4bc

Ici, vérification d’un cas passant et non-passant:

  • L’affichage d’un livre avec un snapshot proposé par Jest
  • L’affichage sans livre avec un snapshot proposé par Jest

NB : les implémentations et le format des tests choisis sont une façon de faire.

Test de Controller (back end)

Comment sont envoyées les données quand j’appelle telle route. Est-ce que j’ai le bon code d’erreur HTTP ? Si je fais de REST, etc.

https://gist.github.com/mickaelw/16a596f4a2e6e2e9d84f81890e508cab

https://gist.github.com/mickaelw/8febd3d94a7cffaaa18dfabc09390c83

https://gist.github.com/mickaelw/6d6b6ab7b4e987e005defe1d29565d40

On peut remarquer que les dépendances sont doublées par une librairie de tests. Il est également possible de le faire manuellement.

Ici, vérification d’un cas passant et non-passant :

  • Récupération des informations au bon format du livre quand il existe avec un code HTTP 200
  • Information que le livre demandé n’existe pas avec un code HTTP 404

À noter le passage des dépendances en paramètre de la fonction utilisée en Controller (getBookById)

Autres (ex. : ligne de commande)

Les autres cas possibles, exemple avec une invite de commandes, les mêmes principes que pour les deux cas précédents seront appliqués.


Conclusion

Pour ne pas s’embrouiller entre les tâches, on évite d’en faire plusieurs en même temps, pour nos tests c’est pareil.

Les TI doivent nous permettre de nous concentrer sur la bonne intégration avec un système tiers et chasser de notre esprit les règles métiers qui sont gérées par les tests unitaires et les tests d’acceptation.

L'objectif d’un TI est de tester l’intégration d’un système tiers (librairie, framework, etc.) pour vérifier ses comportements lors de l’utilisation des Use Cases, sans se préoccuper des règles métier**.**

**Il  va nous permettre de construire l’**Adaptateur par rapport aux interactions avec le monde extérieur (exemple : affichage de données, déclenchement d’actions, etc. ) et aux contraintes liées au système tiers choisi.

Nous utilisons l’injection de dépendances, ce qui nous aide à tester sans se préoccuper du métier.

En prenant en compte ces deux points, les tests deviennent :

  • Plus lisibles et maintenables :
    • Il n’y a pas d’initialisation de données complexes pour reproduire des règles métiers tordues.
    • Le fichier est souvent petit car il y a uniquement quelques cas.
  • Plus faciles à écrire : l’injection possible de fausses implémentations donne une grande souplesse pour les tests.

Résumé en une image :