Étant donné quand-alors – Tests Python

By | avril 11, 2019

trouver un expert Python


La conception de vos méthodes de test à l’aide d’une structure simple telle que «quand-alors-ensuite» vous aidera à:

  • Communiquez plus clairement le but de votre test
  • Concentrez vos pensées tout en écrivant le test
  • Rendre le test d'écriture plus rapide
  • Facilitez la réutilisation de parties de votre test
  • Soulignez les hypothèses que vous faites sur les conditions préalables du test
  • Mettez en surbrillance les résultats auxquels vous vous attendez et que vous testez.

Dans cet article, je vais parler de la conception de vos cas de test / méthodes de test en utilisant donnés-quand-alors.

Peu importe que vous utilisiez pytest, unittest, votre nez ou quelque chose de complètement différent, cet article vous aidera à rédiger de meilleurs tests.


Remarque: il s’agissait à l’origine d’un article rédigé après l’épisode 10 de Python Test Podcast. Toutefois, je pense que c’est plutôt bon comme message.


Structurer votre test facilite non seulement la lecture, mais également l'écriture et la réutilisation.
Je suis vraiment excité pour entrer dans ceci.
Mais d’abord, je voudrais prendre un moment pour remercier les sponsors de l’émission.


Conception de vos cas de test en utilisant donnés-quand-alors.

Je parle ici des fonctions et méthodes de test.
Pas la structure de toute votre suite, mais les tests individuels.

Ceci s’applique à n’importe quel cadre de test. Mais je vais supposer que pytest pour le moment, donc je n’ai pas besoin de continuer à dire «pytest ou unittest ou nez ou autre chose».

Pytest ne se soucie pas de ce que vous mettez dans vos fonctions et méthodes de test.
Et peu importe ce qui entre dans les fonctions et méthodes d’installation et de démontage, ou dans les appareils de test.

La syntaxe et la mécanique de tout cela sont assez simples.
Si la syntaxe ou les mécanismes vous tracassent, ne vous sentez pas mal à l’aise.
Marquez simplement une bonne référence.
Bien sûr, je vous suggère de mettre en signet pythontesting.net/start-here et la page de référence de fixture pour le framework approprié qui se trouve sur la page de démarrage.

Mais une fois que vous avez maîtrisé la mécanique, vous pouvez y mettre ce que vous voulez.
Si un appareil réussit une assertion ou une exception, votre test se terminera par une erreur.

Si la fonction ou la méthode de test atteint une assertion, votre test échouera.

Génial. Il y a la mécanique.

Mais cela ressemble toujours à une toile vierge.
Une page vide
Que devriez-vous mettre là?

Bien. Tout comme les artistes et les écrivains sont fréquemment aidés dans leur créativité en suivant une structure familière, un écrivain de test peut également utiliser cette structure pour non seulement dépasser la page blanche, mais également en retirer quelques avantages.

Structure

Parlons d’abord de la structure. Nous couvrirons ensuite certains des avantages.

Beaucoup de structures ou de schémas différents ont été proposés comme bons modèles pour écrire des tests.
Les modèles que je connais bien ressemblent tous à la même chose avec des noms différents.

Étant donné quand

Le modèle que j'utilise maintenant et que j'aime le plus est donné quand.
C’est tellement facile à retenir.
Et cela me met dans le bon état d'esprit pour réfléchir à mes tests, élargir les tests et réutiliser des pièces.

C'est assez basique.
Compte tenu du contexte dans lequel votre test se déroulera.
Quand quelque action se passe.
Ensuite, certaines conséquences sont attendues. Sortie de l'action ou effets secondaires pouvant être testés.

Une façon simpliste de commencer consiste à séparer le code dans le corps de vos fonctions de test en 3 blocs distincts.
Je sépare généralement les sections avec une ligne vide.
Vous pouvez également mettre un commentaire en haut des sections avec ces mêmes mots clés.
Si vous écrivez des phrases entières dans le commentaire, mettez-les peut-être, quand et ensuite en majuscule.

Cette structure donnée à tout moment est empruntée à BDD: Behavior Driven Development.
Je pense que c’est la seule chose que j’ai tirée de BDD.
BDD a beaucoup de bagages que je ne suis pas encore prêt à gérer.

Mais j'aime donner quand-alors.

Cela devient particulièrement puissant si vous ne placez même pas GIVEN dans la fonction / méthode de test proprement dite.
Mettez-le dans un appareil.
Mettez-le en configuration pour une classe ou un module.
Ou mieux encore, mettez-le dans un appareil nommé pytest.

Le pouvoir de placer GIVEN dans un appareil est que, si vous ne pouvez pas accéder à la partie GIVEN (par exemple, une assertion est touchée), le test ne se termine pas par Failure, il se termine par Error.

Et aussi maintenant que votre corps d’essai proprement dit ne contient que deux moitiés, le QUAND et le QUAND.

Pour certains tests, le GIVEN établira des données de test.
Mais il pourrait aussi s'agir de mettre le système dans le bon état.
Pour moi, lors du test du code d'instrument électronique intégré, GIVEN ou de configuration, vous configurez des ports RF, définissez des pertes de câbles, chargez des générateurs de signaux arbitraires ou bien d'autres choses amusantes comme celle-ci.

Ou il pourrait être vide.
Si l’action que vous entreprenez devrait avoir le même effet quel que soit l’état du système testé, il n’ya rien à ajouter.
Je suggère d’être explicite et de mettre un commentaire comme

avant de passer aux sections suivantes, et pour vous assurer que les futurs responsables du test savent que vous avez bien pensé aux conditions préalables.

La partie QUAND est vraiment ce que nous testons avec ce test.
La section WHEN doit être très lisible et très claire sur ce qui se passe.
C’est la section à laquelle les gens se réfèrent (ou devraient se référer) quand ils disent «un test devrait tester une et une seule chose».
La section WHEN devrait faire une chose.

Même si cette "chose" est complexe. Ce devrait être quelque chose qu'un utilisateur penserait comme faisant une chose.

La section THEN est où vous:

  • vérifier les conditions de poste.
  • rechercher les effets secondaires observables
  • et où toutes les affirmations sont

Certaines personnes vous diront de n’avoir qu’une seule affirmation par test.
C'est n'importe quoi.
Ils parlent d’une définition très étroite du TDD, une définition qui n’inclut pas tous les niveaux de test qui me préoccupent.

Si votre action de la section WHEN a 15 effets secondaires observables et une sortie de fonction, alors foncez et mettez 16 affirmations.

Je n'en ai généralement que quelques-uns vraiment.
Mais cela dépend totalement du test, de ce que vous testez, de votre domaine et de nombreux autres facteurs.

Faisons une pause dans Given-When-Then et commentons les autres noms de la structure de conception de test.


Configuration-Test-Démontage (ou aussi Setup-Exercise-Verify-Teardown)

Pour la plupart, cela revient à donner, quand, puis avec une étape supplémentaire de démontage.

  • Configuration == donnée
  • Exercice == Quand
  • Vérifier == alors

Lorsqu'elle est écrite en tant que configuration, test et démontage, la partie test correspond à la fois à WHEN et à THEN.

Alors, qu’est-ce que Teardown?

Eh bien, pour beaucoup d’entre vous, ce n’est rien. Vide. Rien à faire.
Ce sera quelque chose d'important lorsque vous devez vraiment annuler ce que vous avez fait lors de la configuration ou de la partie de l'exercice.
Disons que vous testez un système transactionnel.
Vous pouvez utiliser le démontage pour restaurer les transactions à l'état antérieur au démarrage du test.
Dans mon cas, je pourrais rompre une connexion de données avec un appareil mobile, ou bien vérifier que les niveaux de puissance dans le système sont à des niveaux sécurisés, ou réinitialiser une matrice de commutation sur des chemins sécurisés dans le système.

L’étape de démontage est présente dans le moment où je l’utilise. Ce n’est tout simplement pas la partie la plus difficile, alors cela ne me dérange pas de ne pas l'avoir explicitement dans le nom.

Lorsque vous utilisez des appareils nommés pytest, vous écrivez le démontage dans l’appareil lui-même. Eh bien, d'accord avec ça quand même, sous la forme d'une fonction de finaliseur, le test proprement dit n'a pas à penser au démontage.

Bien sûr, si le test proprement dit, dans la section Quand dit, nécessite quelque chose de défait dans le démontage, nous devons nous assurer que cela se produit même si une exception ou une assertion empêche la fonction de test de se terminer.
Un excellent moyen de le faire est d’avoir un appareil qui n’a pas vraiment d’action de configuration, mais seulement un finaliseur.


Arrange-Act-Assert

Un autre nom commun pour cette structure est Arrange-Act-Assert

Maintenant, cela devrait être vraiment évident comment ça se passe.

  • Organiser == Compte tenu
  • Act == Quand
  • Assert == Alors

À bien y penser, j'aime mieux agir que quand.
Peut-être «donné-acte-alors»? non. peut-être «donné-acte-affirmer». Eh bien, nous perdons l’allitération et je ne m'en souviendrai pas.
Mais il semble que je n’ai aucun mal à me souvenir de ce qui est donné quand.
Donc je suppose que je vais rester avec ça.


preconditions-trigger-postconditions

Voyons voir. D'autres noms?
Un ancien est préconditions-déclencheurs-post-conditions.
C'est pas mal.

Encore:

  • donné == préconditions
  • quand == déclencher
  • alors == postconditions

C’est plutôt bien, en fait.
Mais je ne les écris pas dans les commentaires.
Trop de dactylographie.
Et je ne peux pas en faire une phrase.

Faites-moi savoir si vous rencontrez des variations.
Un bon endroit à faire serait la section commentaires de la note de spectacle sur pythontesting.net/10


Avantages

D'accord. J'ai promis de parler des avantages de l'utilisation d'un modèle tel que «quand-quand-alors» ou quelle que soit la variante dont nous avons discuté et qui a le plus de sens pour vous.

Répartir vos fonctions de test de la manière suivante (supposons que l’on donne à l’heure et bien sûr les démoulages ou finaliseurs en option) présente de nombreux avantages.

Espérons que cela aura un sens.

Communiquez plus clairement le but de votre test

Avoir la section WHEN simple et séparée par des espaces mettra en évidence pour vous et pour les autres lecteurs ce que vous testez.

Surtout si le nom de la méthode de test est directement lié à l'action dans la section WHEN, cela aide vraiment à clarifier ce que vous essayez de tester.

Si le nom semble trop long ou si la section WHEN contient trop de code, relisez-le.
Cela devrait-il vraiment être un test? Ou devriez-vous le diviser en plus d'un.
Je ne vous dis pas quelle est la bonne réponse.
J’ai passé de nombreux tests très compliqués qui font sens comme ils sont.

Assurez-vous simplement que ce qui se passe est clair.

Concentrez vos pensées tout en écrivant le test

Penser seulement à une section à la fois aide vraiment à clarifier la pensée et le codage. Un peu difficile à mettre en mots. Mais cela aide vraiment, il est plus facile de savoir quoi écrire.

Rendre le test d'écriture plus rapide

Travailler avec les contraintes de «quand-alors-alors» et de l’objectif que vous gagnez le rend vraiment plus rapide.
Vous pouvez également consulter l'ensemble des tests avec la même section GIVEN ou en utilisant la même configuration, et décider si vous avez testé toutes les actions disponibles pour l'utilisateur avec cet état GIVEN.
Sinon, écrivez plus de tests avec le même GIVEN, mais avec des actions différentes.
Et bien sûr, les conditions postérieures THEN devront être réexaminées.

Ceci est également lié au prochain avantage.

Facilitez la réutilisation de parties de votre test

Vous pouvez maintenant regarder vos tests et vous demander si GIVEN représente réellement les seuls états de votre système où l’action WHEN peut avoir lieu.
Sinon, vous pouvez ajouter plus de tests avec la même action, mais avec différents états GIVEN.
Et bien sûr, les conditions postérieures THEN devront probablement également être modifiées.
Sinon, vous devez vérifier si les deux tests représentent réellement deux tests ou si vous pouvez simplifier la section GIVEN.

Couverture du comportement

Ces deux types de réutilisation pour créer de nouveaux tests font partie de ce que l’on appelle la couverture comportementale. Plus précisément, je parle de la couverture des états et de la couverture de transition.
Je vais parler de la couverture du comportement, de la couverture des états et de la couverture de la transition dans les prochains articles.

Pour l'instant, il suffit de réaliser que la séparation des sections données et chronologiques aide à mettre en évidence les états testés (GIVEN) et les modifications apportées à l'état (WHEN).
Et cette séparation vous permet de revoir vos tests et de voir si vous avez oublié des actions évidentes ou des états de départ.

Soulignez les hypothèses que vous faites sur les conditions préalables du test

Je pense avoir déjà couvert cela.
Avez-vous tous les GIVEN raisonnables pour la fonctionnalité que vous testez dans la section WHEN?

Mettez en surbrillance les résultats auxquels vous vous attendez et que vous testez.

Mettez en surbrillance les tests manquants.

Mettez en surbrillance les fonctionnalités manquantes.

C'est un peu plus difficile à comprendre.
Examinez les sections THEN associées aux tests associés, celles comportant des sections communes GIVEN ou WHEN. Ou les états de départ et les transitions de ces états.

Les sections THEN, les contrôles d’état de postcondition, représentent les états finaux du système après les actions.

Si vous êtes vraiment sûr qu'il existe un état final qui n'est pas représenté dans les tests:

  • vous pourriez avoir un test manquant
  • il se peut qu'il manque des fonctionnalités dans le système

Laissez-moi vous donner un exemple simple:

En regardant cette série de tests:

  • J'ai deux tests avec la même action (inscription)
  • Venant de deux états de départ différents (souscrit ou non souscrit).
  • Mais je n’ai pas de postcondition où l’utilisateur n’est pas abonné.

S'il n'y a pas de fonctionnalité de désinscription, alors je viens de remarquer une fonctionnalité manquante du système.
S'il existe déjà une action de désinscription, j'ai tout simplement oublié d'écrire des tests pour cette action.

  • La réutilisation peut être facilitée par le paramétrage du luminaire ou le paramétrage du test.

C’est un cas si courant que vous avez beaucoup de tests avec des parties partagées.
Pytest peut gérer ces deux cas pour vous permettre d'écrire moins de tests tout en couvrant tous les états de départ et toutes les fonctionnalités dont vous avez besoin.
Je parlerai également du paramétrage dans un prochain article.

J'y touche dans la section Params d'un article appelé écrous et boulons de fixations Pytest.


Je pense que cela suffit dans la liste des avantages.

Structurer votre test facilite non seulement la lecture, mais également l'écriture et la réutilisation.

Mais wow, j’ai mis l’accent sur de nombreux domaines que je dois aborder plus en détail dans les prochains articles.