Background Image
DÉVELOPPEMENT DE LOGICIELS

Les tests contextuels dans la vie de Don Testa'lot Moore

Claudio Lassala headshot

June 2, 2021 | 3 Lecture minute

Plusieurs développeurs et organisations abandonnent certaines pratiques de tests automatisés parce que les tests deviennent fragiles et difficiles à maintenir.

Jetons un coup d'œil à la vie de notre personnage fictif Don, le charismatique développeur fils de Mme Aido Test'alot et de M. Telme Moore. Dans son emploi actuel, Don Testa'lot Moore a suivi un cours d'introduction aux tests unitaires et s'est familiarisé avec les cadres de test et les programmes de test. Il devient "fou de tests unitaires" et écrit plusieurs tests pour un cours qu'il est en train de créer. Il se sent bien en voyant la couverture de code élevée obtenue grâce à ces tests. Ses coéquipiers sont intrigués par l'excellent travail réalisé par M. Testa'lot Moore, et il organise volontiers une réunion pour partager ses nouvelles connaissances avec l'équipe.

Il montre les tests à ses collègues, en expliquant qu'ils se trouvent dans un montage de test de test. Chaque test est organisé selon le modèle "arrange-act-assert" (AAA). Les expressions faciales montrent de l'inquiétude lorsqu'ils voient des centaines de lignes de code dans le fichier ; bien plus de lignes de code que la classe réellement testée. "C'est beaucoup d'efforts", dit une personne, "et je crains que le patron ne le pense aussi".

Des semaines plus tard, un défaut est détecté. La correction est facile : un simple bloc if suffit à régler le problème. Mais M. Testa'lot Moore a appris qu'il faut d'abord écrire un test unitaire qui reproduit le défaut. Il navigue dans le long jeu de tests pour essayer d'en trouver un qui semble être un bon point de départ pour le nouveau test. La tâche s'avère difficile, car plusieurs tests se ressemblent énormément. Il s'arrête sur l'un d'entre eux, adopte une approche copier-coller et procède aux ajustements nécessaires pour reproduire le défaut signalé. Lorsqu'il a terminé, il examine les modifications apportées au code et constate qu'il y a 50 nouvelles lignes de code de test pour la une ligne de code d'implémentation (une simple utilisation de l'opérateur ternaire a fait l'affaire).

Le temps nécessaire pour corriger le défaut a été remarqué par les coéquipiers et le patron, qui a convoqué son développeur dans son bureau pour avoir une petite discussion, en lui disant de ne pas de ne plus perdre ce genre de temps à l'avenir. Après cette grève, le développeur a dû mettre un terme à sa nouvelle pratique, de sorte que M. Don Testa's Moore remet en question sa confiance dans la livraison d'un code sans tests automatisés appropriés. À son grand soulagement, un mentor entre dans sa vie et lui fournit les conseils dont il a besoin.

Voici ce que Don entend de son mentor...

Prenons ce CompteBanque pour laquelle vous avez dit avoir écrit de nombreux tests. Vous avez un fichier de test nommé BankAccountTestsqui contient tous les tests de cette classe. J'y vois près de 1 000 lignes de code. La classe BankAccount possède plusieurs méthodes, notamment Dépôt, Retraitet Transfert de fonds. La fixation comprend au moins un test pour chaque méthode, et la plupart des méthodes nécessitent plusieurs tests pour vérifier les différentes branches qui sont atteintes en fonction des paramètres transmis. Il existe également des tests qui vérifient les cas exceptionnels.

Bank account test fixture

La première étape pour améliorer ces tests est d'organiser le test en regroupant les tests pour les mêmes méthodes, de sorte que nous puissions voir tous les tests pour la méthode Deposit ensemble, ainsi que pour Withdraw, TransferFunds, etc.

Ensuite, créez un fichier BankAccountSpecs (oui, commençons à considérer ces choses comme des specsau lieu de tests). Déplacez le dossier BankAccountTests dans ce fichier.

Créez maintenant un fichier pour chaque méthode que vous testez. Copiez simplement le fichier BankAccountTests et collez-le autant de fois que nécessaire. Voici une bonne façon de nommer ces fichiers Dépôt, Retrait, Transfert de fondset ainsi de suite. Dans chaque fichier, supprimez tous les tests qui ne correspondent pas à la méthode testée.

Bank account specs

Ce seul changement est déjà bénéfique. La prochaine fois que vous devrez intervenir sur la classe BankAccount dans le cadre d'un dépôt, vous pourrez vous concentrer uniquement sur les tests de cette zone.

Continuons, choisissons l'un de ces contextes. Disons le dépôt, puisque nous venons de le mentionner. Regardez la fonction arranger de chaque test. Identifiez ce qu'ils ont en commun. Trouvez le code qui ressemble exactement exactement le même dans certains tests. Extrayez ce code dans des méthodes distinctes et réutilisez-le dans tous les tests. Trouver du code qui semble à peu près le même, à l'exception de détails mineurs (il y a peut-être une méthode vrai ici et une valeur faux là). Extrayez ces lignes dans une méthode distincte, transformez ces valeurs variables en paramètres et réutilisez la méthode le cas échéant. Suivez le même processus avec la méthode act et assert de chaque test. Le fichier devrait contenir beaucoup moins de lignes de code et chaque test devrait être beaucoup plus agréable à lire ! Procédez de la même manière pour les fichiers de test des autres méthodes.

Lorsque tous les fichiers de test ont été nettoyés, parcourez-les, regardez les méthodes que vous avez créées pour gérer les sections arrange, act et assert, trouvez les méthodes qui semblent exactement les mêmes dans tous les fichiers, coupez-les et collez-les dans un tout nouveau fichier, nommé BankAccountSpecsBase (ou quelque chose comme ça). Devinez quoi ? Oui, vous pouvez réutiliser le code de vos fichiers de spécifications ! Si ceux-ci sont écrits dans un langage qui prend en charge l'héritage (C#, TypeScript, Java), vous venez d'obtenir une classe de base pour vos spécifications BankAccount. Dans les langages qui ne supportent pas l'héritage, vous avez juste un module, ou tout autre mécanisme à votre disposition pour réutiliser le code.

Continuez à parcourir ces fichiers et identifiez tout autre code pouvant être utilisé dans les spécifications. À la fin de ce processus, vous aurez une meilleure compréhension des choses. Par exemple, vous pouvez découvrir que la classe BankAccount est toujours instanciée de la même manière. toujours instanciée de la même manière. Ou peut-être est-elle instanciée de la même manière en fonction de la méthode (par exemple, elle est initialisée avec un solde initial de 0 $ lors des tests de la méthode Deposit, et avec un solde initial de 1000 $ lors des tests de la méthode Withdraw).

À ce stade, examinez à nouveau chaque fichier de spécification. Reprenons l'exemple de retraitpar exemple. Examinez ses tests et voyez s'il n'y a pas de code redondant entre eux. Pour l'instant, tout ce qui reste devrait être spécifique à retrait. Il y a peut-être encore une douzaine de tests dans le fichier. Pouvez-vous deviner ce qui va suivre ? Créez un dossier nommé retrait et y placer le fichier spec. Identifiez les tests qui ont des arranger similaires ; il s'agit de contextes spécifiques dans lesquels les retraits se produisent. Regroupez-les, déplacez-les dans des fichiers distincts nommés d'après le contexte (par exemple, "montant non valide", "fonds insuffisants", "ligne de crédit disponible", "victime de fraude signalée"). Examinez ces fichiers, identifiez tout code commun, extrayez-le et collez-le dans un nouveau fichier, nommé WithdrawingContext (ou quelque chose de ce genre).

Bank account specs 2

Qu'est-ce que cette approche nous apporte ?

  • Les fichiers de spécifications sont très petits et faciles à comprendre ;

  • L'organisation par contexte facilite la recherche des spécifications en cas de besoin (

    "hmm, un défaut a été trouvé lors du retrait d'argent d'un compte bancaire qui a été signalé comme victime d'une fraude. Je sais exactement comment trouver immédiatement les tests dans ce domaine !". ) ;

  • L'écriture de nouvelles spécifications devient beaucoup plus facile parce qu'il y a beaucoup de "code de test" qui peut être réutilisé ;

  • À partir de là, les nouvelles spécifications pour n'importe quel domaine sont rédigées en gardant à l'esprit ce processus de réflexion (

    "Quels sont les scénarios ? Quels sont les contextes ? En quoi sont-ils similaires ou différents ?") ;

  • Lorsque des changements sont apportés au code et que les tests échouent, il est désormais plus rapide de voir les caractéristiques et les scénarios touchés par les changements ;

  • L'approche fonctionne quel que soit le type de tests (unitaires, d'intégration, de bout en bout), la partie du logiciel (front-end, back-end), les frameworks de test et les runners (MS-Test, NUnit, JUnit, xUnit, Jest, Jasmine, Cypress.io...) ;

  • Les tests ne pourriront pas et ne seront pas abandonnés puisqu'ils sont maintenant propres, bien organisés et plus faciles à maintenir.

Après cette expérience d'illumination avec son mentor, Don décide d'abandonner son prénom et ne se fait plus appeler que M. Testa'lot !

Développement de logiciels

Dernières réflexions

Explorez nos articles de blog et laissez-vous inspirer par les leaders d'opinion de nos entreprises.
Asset - Lead with Purpose: A Guide to Delegation Image 1
LEADERSHIP

Diriger dans un but précis : un guide de la délégation

Un guide pour vous aider à déléguer lorsque vous ne savez pas par où commencer en tant que nouveau dirigeant.