Pyramide ou crabe ? Trouvez une stratégie de test adaptée

Découvrez comment combiner différents types de tests dans une stratégie raisonnable adaptée à votre projet.

Bienvenue ! Le dernier article a posé de nombreuses bases sur la façon d'aborder les différents types de tests et leur contenu, et a clarifié les définitions des types de tests. Vous vous souvenez de cette petite image de meme ? Vous vous êtes peut-être demandé comment tous ces types de tests que vous avez découverts pouvaient fonctionner ensemble.

Un placard avec deux tiroirs que vous pouvez ouvrir en même temps.

Vous allez le découvrir. Cet article vous explique comment combiner ces types de tests dans des stratégies raisonnables et en choisir une qui correspond à votre projet.

Vous pouvez comparer les stratégies à un certain nombre de formes pour mieux en saisir la signification. Voici une liste de stratégies avec les tailles et les champs d'application de développement respectifs.

Taille de l'application Composition de l'équipe Recours aux tests manuels Stratégie de test
Petite Développeurs uniquement Élevée Test du cornet de glace
Test du crabe
Petite Développeurs et ingénieurs QA Élevée Test du cornet de glace
Test du crabe
Petite Développeurs uniquement Faible Pyramide de test
Grande Développeurs uniquement Élevée Trophée de test
Test du diamant
Grande Développeurs et ingénieurs QA Élevée Trophée de test
Crabe de test
Grande Développeurs uniquement Faible Trophée de test
Test de Honeycomb

Examinons de plus près ces stratégies et découvrons la signification de leur nom.

Déterminez les objectifs des tests: que voulez-vous accomplir avec ces tests ?

Avant de pouvoir élaborer une bonne stratégie, vous devez déterminer votre objectif de test. Quand considérez-vous que votre application a été suffisamment testée ?

Obtenir une couverture de test élevée est souvent considéré comme l'objectif ultime des développeurs en matière de test. Mais est-ce toujours la meilleure approche ? Un autre facteur crucial à prendre en compte lorsque vous choisissez une stratégie de test est de répondre aux besoins de vos utilisateurs.

En tant que développeur, vous utilisez également de nombreuses autres applications et appareils. À cet égard, vous êtes l'utilisateur qui compte sur tous ces systèmes pour "fonctionner". À votre tour, vous comptez sur d'innombrables développeurs pour faire de leur mieux pour que leurs applications et leurs appareils fonctionnent. En tant que développeur, vous devez également vous efforcer de répondre à cette confiance. Votre premier objectif doit donc toujours être de livrer un logiciel fonctionnel et de servir vos utilisateurs. Cela s'applique également aux tests que vous écrivez pour garantir la qualité de l'application. Kent C. Dodds résume très bien cela dans son article Static vs Unit vs Integration vs E2E Testing for Frontend Apps (Tests statiques, unitaires, d'intégration et E2E pour les applications frontales) :

Plus vos tests ressemblent à la façon dont votre logiciel est utilisé, plus ils peuvent vous donner confiance.

par Kent C. Dodds

Kent décrit cela comme un gain de confiance dans les tests. Plus vous vous rapprochez des utilisateurs en choisissant un type de test adapté, plus vous pouvez vous fier aux résultats de vos tests. En d'autres termes, plus vous montez dans la pyramide, plus vous gagnez en confiance. Mais attendez, qu'est-ce que la pyramide ?

Déterminer des stratégies de test: comment choisir une stratégie de test

Commencez par déterminer les parties des exigences que vous devez vérifier pour vous assurer qu'elles sont respectées. Découvrez les types de tests à utiliser et le niveau de détail qui vous permettra d'atteindre le plus haut niveau de confiance tout en conservant une structure de coûts efficace. De nombreux développeurs abordent ce sujet à l'aide d'analogies. Voici les plus courants, en commençant par le classique bien connu.

De nombreuses formes, comme une pyramide, des losanges, un cornet de glace, des nids d'abeilles et un trophée, représentant des stratégies de test.

La pyramide des tests

Dès que vous commencez à chercher des stratégies de test, vous rencontrez probablement la pyramide d'automatisation des tests comme première analogie. Mike Cohn a introduit ce concept dans son livre "Succeeding with Agile". Plus tard, Martin Fowler a développé ce concept dans son article Practical Test Pyramid (Pyramide de test pratique). Vous pouvez représenter la pyramide visuellement comme suit:

Pyramide des tests.

Comme le montre ce dessin, la pyramide des tests se compose de trois couches:

  1. Unité Ces tests se trouvent au niveau de la base de la pyramide, car ils sont rapides à exécuter et faciles à gérer. Ils sont isolés et ciblent les unités de test les plus mineures. Par exemple, consultez un test unitaire typique pour un très petit produit.

  2. Intégration. Ces tests se trouvent au milieu de la pyramide, car ils ont une vitesse d'exécution acceptable, mais vous rapprochent plus de l'utilisateur que les tests unitaires. Un test d'API est un exemple de test d'intégration. Vous pouvez également classer les tests de composants comme ce type.

  3. Tests E2E (également appelés tests d'interface utilisateur). Ces tests simulent un utilisateur réel et son interaction. L'exécution de ces tests prend plus de temps et est donc plus coûteuse. Elles se trouvent au sommet de la pyramide.

Confiance par rapport aux ressources

Comme nous l'avons brièvement vu précédemment, l'ordre des calques n'est pas le fruit du hasard. Elles indiquent les priorités et les coûts correspondants. Vous obtenez ainsi une idée claire du nombre de tests que vous devez écrire pour chaque couche. Vous l'avez déjà vu dans la définition des types de tests.

Étant donné que les tests de bout en bout sont les plus proches de vos utilisateurs, ils vous permettent d'être le plus sûr que votre application fonctionne comme prévu. Toutefois, elles nécessitent une pile d'applications complète et un utilisateur simulé. Elles sont donc potentiellement les plus coûteuses. La confiance est donc en concurrence directe avec les ressources dont vous avez besoin pour exécuter les tests.

Pyramide des tests avec des flèches indiquant le niveau de confiance et les ressources requises pour différents types de tests.

La pyramide tente de résoudre ce problème en vous incitant à vous concentrer davantage sur les tests unitaires et à hiérarchiser strictement les cas couverts par les tests E2E. Par exemple, vos parcours utilisateur les plus cruciaux ou les endroits les plus vulnérables aux défauts. Comme le souligne Martin Fowler, les deux points les plus essentiels de la pyramide de Cohn sont les suivants:

  1. Écrivez des tests avec différents niveaux de précision.
  2. Plus le niveau est élevé, moins vous devez effectuer de tests.

Pyramid a évolué ! Adaptations des pyramides de test

Depuis plusieurs années, les discussions tournent autour de la pyramide. La pyramide semble simplifier à l'excès les stratégies de test, exclure de nombreux types de tests et ne plus correspondre à tous les projets réels. Par conséquent, il peut être trompeur. La pyramide a-t-elle perdu sa forme ? Guillermo Rauch a son avis sur la question:

Écrivez des tests. c'est tout. Principalement l'intégration.

par Guillermo Rauch

Il s'agit de l'une des citations les plus couramment citées à ce sujet. Voyons-la en détail:

  • "Écrire des tests". Non seulement cela renforce la confiance, mais cela permet aussi de gagner du temps en maintenance.
  • "Pas trop". Une couverture à 100% n'est pas toujours une bonne chose, car vos tests ne sont pas priorisés et la maintenance est importante.
  • "Principalement l'intégration". Ici encore, l'accent est mis sur les tests d'intégration: ils présentent la plus grande valeur commerciale, car ils vous offrent un niveau de confiance élevé au quotidien tout en conservant un temps d'exécution raisonnable.

Vous devez donc repenser la pyramide des tests et vous concentrer sur les tests d'intégration. Au cours des dernières années, de nombreuses adaptations ont été proposées. Voyons les plus courantes.

Losange de test

La première adaptation supprime l'accentuation excessive des tests unitaires, comme le montre la pyramide des tests. Imaginons que vous ayez atteint une couverture de 100% pour les tests unitaires. Toutefois, la prochaine fois que vous refactoriserez, vous devrez mettre à jour un grand nombre de ces tests unitaires, et vous pourriez être tenté de les ignorer. Elles s'érodent donc.

Par conséquent, et avec un accent plus prononcé sur les tests d'intégration, la forme suivante peut apparaître:

Losange de test.

Une pyramide évolue en losange. Vous pouvez voir les trois couches précédentes, mais avec une taille différente, et la couche d'unité a été coupée:

  • Unité Écrivez des tests unitaires comme vous l'avez fait précédemment. Toutefois, comme ils ont tendance à s'éroder, ils ne doivent être utilisés que pour les cas les plus critiques.
  • Intégration. Les tests d'intégration que vous connaissez, qui testent la combinaison d'unités individuelles.
  • E2E Cette couche gère les tests d'interface utilisateur de manière similaire à la pyramide de test. Veillez à n'écrire des tests de bout en bout que pour les scénarios de test les plus critiques.

Tester la structure alvéolée

Spotify a introduit une autre adaptation, semblable au losange de test, mais plus spécialisée pour les systèmes logiciels basés sur des microservices. La ruche de test est une autre analogie visuelle de la granularité, de la portée et du nombre de tests à écrire pour un système logiciel basé sur des microservices. En raison de leur petite taille, la complexité la plus importante d'un microservice ne réside pas dans le service lui-même, mais dans la façon dont il interagit avec les autres. Par conséquent, une stratégie de test pour un microservice doit principalement se concentrer sur les tests d'intégration.

La grille de test.

Cette forme rappelle un nid d'abeille, d'où son nom. Il comporte les couches suivantes:

  • Tests intégrés. L'article de Spotify cite J. B. Rainsberger pour définir cette couche : "Un test qui aboutit à un résultat positif ou négatif en fonction de la validité d'un autre système". Ces tests comportent des dépendances externes que vous devez prendre en compte. À l'inverse, votre système peut être une dépendance qui fait planter d'autres systèmes. Comme pour les tests E2E dans d'autres analogies, utilisez ces tests avec précaution, uniquement dans les cas les plus essentiels.
  • Tests d'intégration. Comme pour les autres adaptations, vous devez vous concentrer sur cette couche. Il contient des tests qui vérifient la validité de votre service de manière plus isolée, mais toujours en combinaison avec d'autres services. Cela signifie que les tests incluront également d'autres systèmes et se concentreront sur les points d'interaction, par exemple via des tests d'API.
  • Tests sur les détails de l'implémentation Ces tests ressemblent à des tests unitaires, qui se concentrent sur des parties du code naturellement isolées et qui ont donc leur propre complexité interne.

Pour en savoir plus sur cette stratégie de test, consultez le post qui compare la pyramide de test à la ruche de Martin Fowler et l'article d'origine de Spotify.

Trophée de test

Vous pouvez déjà constater une attention répétée sur les tests d'intégration. Toutefois, un autre type de test que vous avez rencontré dans l'article précédent n'est pas un test en théorie, mais il reste un aspect important à prendre en compte dans une stratégie de test. L'analyse statique est absente de la pyramide des tests et de la plupart des adaptations que vous avez vues jusqu'à présent. Il existe une adaptation du trophée de test qui prend en compte l'analyse statique tout en restant axée sur les tests d'intégration. Le trophée de test est né de la citation précédente de Guillermo Rauch et a été développé par Kent C. Dodds:

Trophée de test.

Le trophée de test est une analogie qui illustre la précision des tests d'une manière légèrement différente. Il comporte quatre couches:

  • Analyse statique. Il joue un rôle essentiel dans cette analogie et vous permet de détecter les fautes de frappe, les erreurs de style et d'autres bugs en exécutant simplement les étapes de débogage déjà décrites.
  • Tests unitaires. Ils garantissent que votre plus petite unité est testée de manière appropriée, mais le trophée de test ne les met pas en avant dans la même mesure que la pyramide des tests.
  • Intégration. C'est l'objectif principal, car il équilibre le coût et la confiance accrue de la meilleure façon, comme pour les autres adaptations.
  • Tests de l'interface utilisateur. Y compris les tests E2E et visuels, ils se trouvent au sommet du trophée de test, comme dans la pyramide des tests.

Pour en savoir plus sur le trophée de test, consultez l'article de blog de Kent C. Dodds sur ce sujet.

Quelques approches plus axées sur l'UI

C'est bien, mais quel que soit le nom que vous donnez à votre stratégie (pyramide, nid d'abeille ou losange), il manque toujours quelque chose. Bien que l'automatisation des tests soit utile, il est important de se rappeler que les tests manuels restent essentiels. Les tests automatisés doivent alléger les tâches de routine et permettre aux ingénieurs d'assurance qualité de se concentrer sur les domaines cruciaux. L'automatisation ne doit pas remplacer les tests manuels, mais les compléter. Est-il possible d'intégrer les tests manuels à l'automatisation pour obtenir des résultats optimaux ?

Test du cornet glacé et du crabe

Il existe en effet deux adaptations de la pyramide de test qui se concentrent davantage sur ces méthodes de test axées sur l'interface utilisateur. Les deux présentent l'avantage d'un niveau de confiance élevé, mais sont naturellement plus coûteux en raison d'une exécution des tests plus lente.

Le premier, le cône glacé d'essai, ressemble à une pyramide inversée. Sans l'étape de test manuel, on parle également de "pizza de test".

Cornet de glace de test.

Le cône glacé est davantage axé sur les tests manuels ou d'interface utilisateur, et le moins sur les tests unitaires. Elle prend souvent forme dans les projets où les développeurs ont commencé à travailler sans avoir réfléchi beaucoup à la stratégie de test. Le code de glace est considéré comme un antimodèle, et à juste titre. Il est coûteux en termes de ressources et de travail manuel.

Le crabe de test est semblable au cône glacé de test, mais avec un accent plus marqué sur les tests E2E et visuels:

Le crabe de test.

Cette stratégie de test comprend un autre aspect: elle vérifie que votre application fonctionne et est esthétiquement correcte. Le crabe de test met en avant l'importance des tests visuels, définis dans l'article précédent. Les tests d'intégration, divisés en tests de composants et d'API, passent davantage au second plan, et les tests unitaires jouent un rôle encore plus secondaire. Pour en savoir plus sur cette stratégie de test, consultez cet article sur le crabe de test.

Bien que plus coûteuses, ces deux stratégies de test ont leur place: par exemple, dans les projets de petite envergure où moins de tests sont nécessaires ou où la complexité est moins importante. Dans ce cas, une stratégie de test complète axée sur les tests d'intégration peut être trop complexe.

Bien que ces deux stratégies de test soient plus coûteuses, elles ont leur place, par exemple, dans les projets plus petits qui nécessitent moins de tests et ne doivent pas couvrir une grande complexité. Dans ce cas, une stratégie de test à grande échelle axée sur les tests d'intégration peut être inutilement complexe.

Conseil pratique: Passons à la stratégie !

Vous connaissez maintenant les stratégies de test les plus courantes. Vous avez commencé par la pyramide de test classique et vous avez découvert ses nombreuses adaptations. Vous devez maintenant les évaluer pour votre produit et choisir celle qui convient le mieux à votre projet. La réponse à cette question doit commencer par la réponse préférée de tous : Ça dépend. Cela ne la rend pas moins précise.

Cela dépend.

Le choix de la stratégie de test la plus appropriée parmi celles décrites (et même celles omises) dépend de votre application. Il doit correspondre à votre architecture, à vos exigences et, enfin, à vos utilisateurs et à leurs exigences. Tout cela peut varier d'une application à l'autre. C'est tout à fait normal. N'oubliez pas que votre objectif le plus important est de servir vos utilisateurs, et non de suivre une définition de manuel.

Dans la plupart des cas, les tests réels sont difficiles à séparer et à définir individuellement. Même Martin Fowler lui-même souligne l'aspect positif des définitions différentes, comme dans le cas des tests unitaires. Comme le souligne correctement Justin Searls dans son tweet:

[…] écrivez des tests expressifs qui établissent des limites claires, s'exécutent rapidement et de manière fiable, et ne échouent que pour des raisons utiles.

par Justin Searls

Concentrez-vous sur les tests qui signalent les erreurs réelles que les utilisateurs peuvent rencontrer, et ne vous laissez pas distraire de votre objectif. Les tests doivent être conçus pour être bénéfiques à l'utilisateur, et non pas simplement pour couvrir 100% de la surface ou pour débattre du pourcentage de chaque type de test à écrire.

Concentrez-vous sur les tests qui signalent les erreurs réelles que vos utilisateurs peuvent rencontrer et ne vous laissez pas distraire de votre objectif. Les tests doivent être conçus pour être bénéfiques pour l'utilisateur, et non pas simplement pour couvrir 100% de la surface ou susciter des débats sur le pourcentage de tests d'un type particulier que vous devez écrire.