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 établi 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 mème ? Vous vous êtes peut-être demandé comment tous les types de tests que vous avez découverts pouvaient fonctionner ensemble.

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

C'est exactement ce que vous allez apprendre à présent. Cet article explique comment combiner ces types de tests dans des stratégies raisonnables et en choisir un qui correspond à votre projet.

Vous pouvez comparer les stratégies à un certain nombre de formes pour mieux comprendre leur signification. Voici une liste de stratégies avec les tailles et niveaux 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 Tester un cornet de glace
Tester le crabe
Petite Développeurs et ingénieurs en contrôle qualité Élevée Tester un cornet de glace
Tester le crabe
Petite Développeurs uniquement Faible Pyramide de test
Volumineux Développeurs uniquement Élevée Trophée test
Diamant test
Volumineux Développeurs et ingénieurs en contrôle qualité Élevée Test du trophée
Crabe test
Volumineux Développeurs uniquement Faible Trophée test
Test Honeycomb

Examinons de plus près ces stratégies et voyons ce qui se cache derrière leur nom.

Déterminez les objectifs des tests: quels objectifs souhaitez-vous atteindre avec ces tests ?

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

Pour les développeurs, l'obtention d'une couverture de test élevée est souvent considérée comme l'objectif ultime pour les développeurs. Mais est-ce toujours la meilleure approche ? Vous devez également tenir compte d'un autre facteur essentiel lors de l'élaboration d'une stratégie de test : 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 s'appuie sur tous ces systèmes pour fonctionner. En retour, vous comptez sur d'innombrables développeurs pour que leurs applications et leurs appareils fonctionnent. Pour inverser cette tendance, en tant que développeur, vous vous efforcez également d'être à la hauteur de cette confiance. Votre premier objectif doit donc toujours être de livrer des logiciels fonctionnels et de servir vos utilisateurs. Cela s'étend aux tests que vous écrivez pour garantir la qualité de l'application. Kent C. Dodds le résume très bien dans son article Static, Unit, Integration vs E2E Testing for Frontend Apps:

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

par Kent C. Dodds

Kent décrit cela comme la prise 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 valides. En d'autres termes, plus vous gravissez 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

Dans un premier temps, déterminez quelles parties des exigences vous devez vérifier pour vous assurer qu'elles sont remplies. Découvrez les types de tests à utiliser et le niveau de détail le plus fiable tout en conservant un type de facturation efficace. De nombreux développeurs abordent ce sujet en faisant des analogies. Voici les plus courantes, en commençant par la version classique.

De nombreuses formes (pyramide, diamants, cône de glace, nids d'abeille, trophée, etc.) représentant des stratégies de test.

Le classique: la pyramide test

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

Pyramide de test.

Comme le montre ce dessin, la pyramide de test se compose de trois calques:

  1. Unité. Vous trouverez ces tests au niveau de la couche de base de la pyramide, car ils sont rapides à exécuter et simples à gérer. Elles sont isolées et ciblent les unités de test les plus mineures. Par exemple, reportez-vous à un test unitaire classique pour un très petit produit.

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

  3. Tests de bout en bout (également appelés tests de l'interface utilisateur). Ces tests simulent un utilisateur authentique et son interaction. Ces tests nécessitent plus de temps à s'exécuter et sont donc plus coûteux. Ils sont en haut de la pyramide.

Confiance par rapport aux ressources

Comme nous l'avons brièvement vu précédemment, l'ordre des couches n'est pas une coïncidence. Ils indiquent les priorités et les coûts correspondants. Cela vous donne 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 test.

Les tests de bout en bout étant les plus proches de vos utilisateurs, ils vous donnent l'assurance que votre application fonctionne comme prévu. Cependant, ils nécessitent une pile d'applications complète et un utilisateur simulé. Ils sont donc potentiellement les plus onéreux. Vous avez donc confiance en une concurrence directe avec les ressources dont vous avez besoin pour exécuter les tests.

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

La pyramide tente de résoudre ce problème en vous concentrant sur les tests unitaires et en privilégiant strictement les cas couverts par les tests de bout en bout. Par exemple, vos parcours utilisateur les plus importants ou les endroits les plus vulnérables aux défauts. Comme Martin Fowler le souligne, les deux points les plus essentiels de la pyramide de Cohn sont les suivants:

  1. Écrivez des tests avec un niveau de précision différent.
  2. Plus le niveau est élevé, moins il y a de tests à effectuer.

La pyramide a évolué ! Adaptations des pyramides de test

Depuis plusieurs années, le sujet de la pyramide fait l'objet de discussions. La pyramide semble simplifier les stratégies de test à l'excès, omettre de nombreux types de tests et ne plus s'adapter aux projets réels. Par conséquent, elle peut être trompeuse. La pyramide est-elle déformée ? Guillermo Rauch a une opinion à ce sujet:

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

Par Guillermo Rauch

Il s'agit de l'une des citations les plus fréquemment citées sur ce sujet, décomposons-la:

  • "Écrire des tests". Non seulement cela permet de gagner la confiance des utilisateurs, mais aussi de gagner du temps en termes de maintenance.
  • "Pas trop". Une couverture de 100% n'est pas toujours une bonne solution, car vos tests ne sont pas prioritaires et nécessiteront beaucoup de maintenance.
  • "Principalement des intégrations". Là encore, l'accent est mis sur les tests d'intégration: ils ont la plus grande valeur commerciale, car ils vous procurent un niveau de confiance élevé quotidiennement tout en maintenant un temps d'exécution raisonnable.

Vous repensez ainsi à la pyramide des tests et vous concentrez sur les tests d'intégration. Ces dernières années, de nombreuses adaptations ont été proposées. Examinons les plus courantes.

Diamant de test

La première adaptation élimine l'accentuation excessive sur les tests unitaires, comme illustré dans la pyramide de test. Imaginons que vous ayez atteint une couverture de 100% pour les tests unitaires. Toutefois, la prochaine fois que vous refactoriserez un site, 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, si l'on met l'accent sur les tests d'intégration, on peut observer la forme suivante:

Losange de test.

Une pyramide se transforme en diamant. Vous pouvez voir les trois couches précédentes, mais avec une taille différente, et la couche unitaire a été découpée:

  • Unité. Écrivez des tests unitaires comme vous les avez définis précédemment. Toutefois, comme ils ont tendance à s'éroder, à hiérarchiser et à ne couvrir que les cas les plus critiques.
  • Intégration. Les tests d'intégration que vous connaissez, consistant à tester une combinaison d'unités individuelles
  • E2E. Cette couche gère les tests de l'interface utilisateur de la même manière que la pyramide de test. Veillez à n'écrire des tests de bout en bout que pour les scénarios de test les plus critiques.

Test honeycomb

Il existe une autre adaptation, introduite par Spotify, qui est semblable au losange de test, mais qui est davantage spécialisée pour les systèmes logiciels basés sur des microservices. Les tests alvéolaires constituent une autre analogie visuelle de la précision, du champ d'application et du nombre de tests à écrire pour un système logiciel basé sur des microservices. En raison de sa 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. La stratégie de test d'un microservice doit donc se concentrer principalement sur les tests d'intégration.

Les nids d'abeille des tests.

Cette forme évoque un nid d'abeille, d'où son nom. Il se compose des couches suivantes:

  • Tests intégrés. L'article de Spotify utilise une citation de J. B. Rainsberger de définir cette couche : "un test qui réussira ou échouera en fonction de l'exactitude d'un autre système". Ces tests ont des dépendances externes que vous devez prendre en compte et, au contraire, votre système peut être une dépendance qui casse d'autres systèmes. Comme pour les tests de bout en bout dans d'autres analogies, utilisez ces tests avec précaution, uniquement pour 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 l'exactitude de votre service de façon plus isolée, mais toujours en association avec d'autres services. Cela signifie que les tests comprendront é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, c'est-à-dire des tests qui se concentrent sur des parties du code naturellement isolées qui présentent leur propre complexité interne.

Pour en savoir plus sur cette stratégie de test, consultez le post de Martin Fowler qui compare la pyramide à la pyramide en nid d'abeille, ainsi que l'article original de Spotify.

Test du trophée

Vous constatez déjà que les tests d'intégration se répètent. Un autre type de test a été abordé dans l'article précédent. Il ne s'agit toutefois pas d'un test en théorie. C'est un aspect important à prendre en compte dans votre stratégie de test. L'analyse statique est absente de la pyramide de test et de la plupart des adaptations que vous avez observées jusqu'à présent. L'adaptation du trophée de test, quant à elle, tient compte de l'analyse statique tout en restant concentré sur les tests d'intégration. Le trophée de test est issu de la citation précédente de Guillermo Rauch et a été développé par Kent C. Dodds:

Le trophée du test.

Le trophée de test est une analogie avec la précision légèrement différente des tests. 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. Elles garantissent que votre plus petite unité est testée de manière appropriée, mais le trophée du test ne la mettra pas autant en avant que la pyramide de test.
  • Intégration. Il s'agit de l'objectif principal, car il permet d'équilibrer le coût et le niveau de confiance le plus élevé de la meilleure façon, comme pour les autres adaptations.
  • Tests de l'interface utilisateur. Avec les tests de bout en bout et les tests visuels, ils sont en tête du trophée des tests, tout comme leur rôle dans la pyramide de test.

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'interface utilisateur

C'est parfait, mais quel que soit le nom de votre stratégie, "pyramide", "nid d'abeille" ou "diamant", il manque encore quelque chose. Bien que l'automatisation des tests soit utile, n'oubliez pas que les tests manuels restent essentiels. Les tests automatisés doivent réduire les tâches routinières et permettre aux ingénieurs de l'assurance qualité de se concentrer sur des domaines cruciaux. Au lieu de remplacer les tests manuels, l'automatisation devrait les compléter. Existe-t-il un moyen d'intégrer des tests manuels à l'automatisation pour obtenir des résultats optimaux ?

Test du cornet de glace 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 de la lenteur de l'exécution des tests.

Le premier, le cône de glace test, ressemble à la pyramide à l'envers. Sans l'étape de test manuel, on parle également de pizza de test.

Cône de glace test.

Le cornet de glace se concentre davantage sur les tests manuels ou sur l'interface utilisateur et le moins sur les tests unitaires. Elle prend souvent forme dans des projets où les développeurs ont commencé à travailler avec seulement quelques réflexions sur la stratégie de test. Le code glace est considéré à juste titre comme un anti-modèle. Il est coûteux en termes de ressources et de travail manuel.

Le crabe d'essai est semblable au cône de glace test, mais il met davantage l'accent sur les tests de bout en bout et les tests visuels:

Le crabe test.

Cette stratégie de test inclut un autre aspect: elle permet de vérifier que votre application fonctionne et s'affiche correctement. Le crabe de test souligne 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, s'étendent davantage en arrière-plan. Dans ce cas, les tests unitaires jouent un rôle encore plus secondaire. Vous trouverez plus de détails sur cette stratégie de test dans cet article sur le crabe de test.

Bien qu'elles soient plus coûteuses, ces deux stratégies de test ont leur place: par exemple, dans les petits projets où moins de tests sont nécessaires ou où une complexité moindre doit être couverte. Dans ce cas, une stratégie de test complète axée sur les tests d'intégration risque d'ê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 qui 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 s'avérer inutilement complexe.

Conseil pratique: Élaborons une stratégie !

Vous connaissez maintenant les stratégies de test les plus courantes. Vous avez commencé par la pyramide classique, la pyramide test, et avez découvert ses nombreuses adaptations. Vous devez maintenant les évaluer pour votre produit et décider lequel est le meilleur pour votre projet. La réponse à cette question doit commencer par la phrase que tout le monde préfère : "Ça dépend". Cependant, cela n'est pas moins précis.

Cela dépend.

Le choix de la stratégie de test la plus appropriée parmi celles décrites (et même celles qui n'ont pas été prises en compte) dépend de votre application. Il doit déterminer votre architecture, vos besoins et, enfin, et non des moindres, 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, pas une définition d'un manuel.

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

[...] écrire des tests expressifs qui établissent des limites claires, s'exécutent rapidement et de manière fiable, et n'é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 par votre objectif. Les tests doivent être conçus pour profiter à l'utilisateur. Ils ne doivent pas se contenter d'offrir une couverture complète ou de débattre du pourcentage de test à écrire.

Concentrez-vous sur les tests qui signalent des erreurs réelles que vos utilisateurs peuvent rencontrer sans être distraits de votre objectif. Les tests doivent être conçus pour profiter à l'utilisateur. Ils ne doivent pas se contenter d'offrir une couverture complète ou déclencher des débats sur le pourcentage d'un type de test particulier que vous devriez écrire.