Découvrez comment combiner différents types de tests dans une stratégie raisonnable qui correspond à votre projet.
Bienvenue ! L'article précédent a posé les bases de l'approche des différents types de tests et de leur contenu, et a clarifié les définitions des types de tests. Vous vous souvenez de ce mème ? Vous vous êtes peut-être demandé comment tous les types de tests que vous avez découverts pouvaient fonctionner ensemble.

C'est précisément ce que vous allez apprendre dans la suite de ce module. Cet article explique comment combiner ces types de tests dans des stratégies raisonnables et choisir celle 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 leurs tailles et champs d'application respectifs.
Examinons de plus près les stratégies et découvrons la signification de leurs noms.
Déterminez les objectifs des tests : que souhaitez-vous accomplir avec ces tests ?
Avant de commencer à élaborer une bonne stratégie, déterminez l'objectif de votre test. Quand considérez-vous que votre application a été suffisamment testée ?
Atteindre une couverture de test élevée est souvent considéré comme l'objectif ultime des développeurs en matière de tests. Mais est-ce toujours la meilleure approche ? Il existe un autre facteur essentiel à prendre en compte pour choisir une stratégie de test : répondre aux besoins de vos utilisateurs.
En tant que développeur, vous utilisez également de nombreux autres appareils et applications. En ce sens, vous êtes l'utilisateur qui compte sur tous ces systèmes pour qu'ils "fonctionnent". À votre tour, vous comptez sur d'innombrables développeurs pour qu'ils fassent de leur mieux pour que leurs applications et leurs appareils fonctionnent. En tant que développeur, vous devez également vous efforcer d'être à la hauteur de cette confiance. Votre premier objectif doit donc toujours être de livrer un logiciel fonctionnel et de répondre aux besoins de vos utilisateurs. Cela s'applique également 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 vs Unit vs Integration vs E2E Testing for Frontend Apps (en anglais) :
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 le fait de gagner en confiance dans les tests. Plus vous vous rapprochez des utilisateurs en choisissant un type de test adapté, plus vous pouvez être sûr que vos tests donneront des résultats valides. En d'autres termes, plus vous montez dans la pyramide, plus vous gagnez en confiance. Mais qu'est-ce que la pyramide ?
Déterminer les stratégies de test : comment choisir une stratégie de test
La première étape consiste à 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'obtenir le plus de confiance possible tout en maintenant une structure de coûts efficace. De nombreux développeurs abordent ce sujet en utilisant des analogies. Voici les plus courants, en commençant par le classique bien connu.

Le classique : la pyramide de tests
Dès que vous commencerez à chercher des stratégies de test, vous tomberez probablement sur 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 The Practical Test Pyramid. Vous pouvez représenter visuellement la pyramide comme suit :

Comme le montre ce schéma, la pyramide de tests se compose de trois couches :
Unité. Ces tests se trouvent à la base de la pyramide, car ils sont rapides à exécuter et simples à gérer. Ils sont isolés et ciblent les unités de test les plus petites. Par exemple, consultez un test unitaire standard pour un très petit produit.
Intégration. Ces tests se trouvent au milieu de la pyramide, car ils ont une vitesse d'exécution acceptable, mais vous rapprochent de l'utilisateur plus que les tests unitaires. Un test d'API est un exemple de test d'intégration. Vous pouvez également classer les tests de composants dans cette catégorie.
Tests de bout en bout (également appelés tests d'interface utilisateur). Ces tests simulent un utilisateur réel et son interaction. Ces tests nécessitent plus de temps d'exécution et sont donc plus coûteux. Ils se trouvent au sommet de la pyramide.
Confiance et ressources
Comme nous l'avons brièvement évoqué, l'ordre des couches n'est pas le fruit du hasard. Elles indiquent les priorités et les coûts correspondants. Vous aurez ainsi une idée précise du nombre de tests à écrire pour chaque couche. Vous l'avez déjà vu dans la définition des types de tests.
Comme les tests de bout en bout sont les plus proches de vos utilisateurs, ils vous permettent de vous assurer 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 coûteux. La confiance est donc en concurrence directe avec les ressources dont vous avez besoin pour exécuter les tests.

La pyramide tente de résoudre ce problème en vous incitant à vous concentrer davantage sur les tests unitaires et à prioriser 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 le souligne Martin Fowler, les deux points les plus importants de la pyramide de Cohn sont les suivants :
- Écrire des tests avec différents niveaux de précision
- Plus vous montez en niveau, moins vous devriez avoir de tests.
Pyramide a évolué ! Adaptations des pyramides de test
Depuis plusieurs années, les discussions tournent autour de la pyramide. La pyramide semble simplifier à l'extrême les stratégies de test, omet de nombreux types de tests et ne correspond plus à tous les projets réels. Par conséquent, il peut être trompeur. La pyramide a-t-elle perdu sa forme ? Guillermo Rauch a un avis sur la question :
Écrire des tests c'est tout. Principalement l'intégration.
par Guillermo Rauch
C'est l'une des citations les plus courantes sur ce sujet. Analysons-la :
- "Écrire des tests". Non seulement parce qu'elle renforce la confiance, mais aussi parce qu'elle permet de gagner du temps lors de la maintenance.
- "Pas trop". Une couverture à 100 % n'est pas toujours une bonne chose, car vos tests ne sont pas priorisés et la maintenance sera importante.
- "Mostly integration" (Principalement l'intégration). Ici encore, l'accent est mis sur les tests d'intégration : ils ont la plus grande valeur commerciale en vous offrant un niveau de confiance élevé au quotidien tout en maintenant un temps d'exécution raisonnable.
Cela vous amène à repenser la pyramide de tests et à vous concentrer 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 supprime l'accent excessif mis sur les tests unitaires, comme on le voit dans la pyramide des tests. Imaginons que vous ayez atteint une couverture de 100 % pour les tests unitaires. Cependant, 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. Ils s'érodent donc.
Par conséquent, et en raison de l'accent mis sur les tests d'intégration, la forme suivante peut apparaître :

Une pyramide évolue en un 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 les avez définis précédemment. Toutefois, comme ils ont tendance à s'éroder, hiérarchisez-les et ne couvrez que 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'UI, de la même manière que la pyramide de tests. Veillez à n'écrire des tests de bout en bout que pour les scénarios de test les plus critiques.
Tester les alvéoles
Il existe une autre adaptation, introduite par Spotify, qui est similaire au diamant de test, mais plus spécialisée pour les systèmes logiciels basés sur des microservices. Le nid d'abeilles de test est une autre analogie visuelle de la précision, 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 plus grande complexité 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.

Cette forme nous 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 réussit ou échoue en fonction de l'exactitude d'un autre système." Ces tests ont des dépendances externes que vous devez prendre en compte. À l'inverse, votre système peut être une dépendance qui interrompt d'autres systèmes. Comme pour les tests de bout en bout dans d'autres analogies, utilisez-les 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 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 l'article de Martin Fowler comparant la pyramide de tests au nid d'abeille et l'article d'origine de Spotify.
Trophée de test
Vous pouvez déjà voir que l'accent est mis à plusieurs reprises sur les tests d'intégration. Cependant, un autre type que vous avez rencontré dans l'article précédent n'est pas un test en théorie, mais reste un aspect important que vous devez prendre en compte dans une stratégie de test. L'analyse statique est absente de la pyramide de test 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 se concentrant sur les tests d'intégration. Le trophée des tests est issu de la citation précédente de Guillermo Rauch et a été développé par Kent C. Dodds :

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 mettra pas en avant autant que la pyramide de test.
- Intégration. C'est l'objectif principal, car il permet d'équilibrer au mieux le coût et la confiance, comme pour les autres adaptations.
- Tests de l'interface utilisateur Y compris les tests E2E et visuels, ils se trouvent en haut du trophée de test, comme 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.
Approches plus axées sur l'interface utilisateur
C'est bien beau, mais peu importe comment vous appelez votre stratégie ("pyramide", "nid d'abeille" ou "diamant"), il manque encore 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 essentiels. L'automatisation ne doit pas remplacer les tests manuels, mais les compléter. Existe-t-il un moyen d'intégrer les tests manuels à l'automatisation pour obtenir des résultats optimaux ?
Cône de glace de test et crabe de test
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'UI. Ces deux types de tests offrent un niveau de confiance élevé, mais sont naturellement plus coûteux en raison d'une exécution de test plus lente.
Le premier, le cône de glace de test, ressemble à une pyramide inversée. Sans l'étape de test manuel, on parle également de "pizza de test".

Le cône de glace met davantage l'accent sur les tests manuels ou d'UI, et moins sur les tests unitaires. Elle prend souvent forme dans les projets où les développeurs ont commencé à travailler avec seulement quelques idées sur la stratégie de test. Le code ICE est considéré comme un anti-modè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 de glace de test, mais il met davantage l'accent sur les tests de bout en bout et visuels :

Cette stratégie de test inclut un autre aspect : elle vérifie 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, passent au second plan, et les tests unitaires jouent un rôle encore plus secondaire ici. 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 plus petits où moins de tests sont nécessaires ou lorsque la complexité à couvrir est moindre. Dans ce cas, une stratégie de test complète axée sur les tests d'intégration peut s'avérer excessive.
Bien que ces deux stratégies de test soient plus coûteuses, elles ont leur place, par exemple, dans les projets de plus petite envergure qui nécessitent moins de tests et n'ont pas besoin de 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.
Conseils pratiques : place à la stratégie !
Vous connaissez désormais les stratégies de test les plus courantes. Vous avez commencé par le classique, la pyramide de tests, et vous avez découvert ses nombreuses adaptations. Vous devez maintenant les évaluer pour votre produit et décider de la meilleure option pour votre projet. La réponse à cette question commence par la phrase que tout le monde adore : "Ça dépend". Cela ne la rend pas moins précise pour autant.

Le choix de la stratégie de test la plus appropriée parmi celles décrites (et même celles qui ne le sont pas) dépend de votre application. Il doit être adapté à votre architecture, à vos exigences et, enfin et surtout, à 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 principal est de répondre aux besoins de vos utilisateurs, et non de suivre une définition théorique.
Le plus souvent, 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 l'indique à juste titre 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 des erreurs réelles que les utilisateurs pourraient rencontrer, et ne vous laissez pas distraire de votre objectif. Les tests doivent être conçus pour être utiles à l'utilisateur, et pas seulement pour fournir une couverture à 100 % ou pour débattre du pourcentage de chaque type de test à écrire.
Concentrez-vous sur les tests qui signalent des erreurs réelles que vos utilisateurs pourraient rencontrer, et ne vous laissez pas distraire de votre objectif. Les tests doivent être conçus pour être utiles à l'utilisateur, et pas seulement pour fournir une couverture à 100 % ou susciter des débats sur le pourcentage d'un type de test particulier que vous devez écrire.