Site icon Blog ARC Optimizer

Me forcer à écrire des tests unitaires


Les tests unitaires présentent de nombreux avantages. Mais vous devez d'abord les écrire. Voici comment je me suis forcé à le faire et à améliorer mon développement React.

"Les tests ressemblent à des légumes. Ils sont vraiment bons pour les autres."

Je sais que les tests unitaires ont une tonne d'avantages. Ils agissent comme un filet de sécurité vous permettant d’apporter des modifications à votre base de code et d’être certain de ne pas altérer les fonctionnalités existantes. Ils vous obligent à réfléchir à la conception de vos modules et à la manière dont ils vont être utilisés. Ils documentent comment votre système est censé fonctionner.

Mais, malgré tout, je me retrouve à tergiverser et à ne pas écrire ces tests unitaires. CHAQUE. TEMPS.

Ainsi, pour mes derniers projets, j’ai commencé à configurer les choses de manière à ne plus pouvoir tergiverser. Dans cet article, je vais expliquer comment j'ai configuré mes projets pour appliquer des seuils de couverture de code, générer des rapports utiles et exécuter des tests unitaires avant de valider et de transmettre à une télécommande.

Test unitaire avec Jest et Create React App [19659007] Lors de la création de nouveaux projets avec Create React App, tout sera déjà configuré pour utiliser Jest comme bibliothèque de test. Essayez ceci:
 npx create-react-app my-app
cd my-app
npm test 

Vous verrez quelque chose comme ceci:

Par défaut, Jest n’exécutera que des tests sur les fichiers modifiés depuis le dernier commit. Nous venons de créer le projet, donc rien n’a encore changé et c’est la raison pour laquelle Jest n’a rien lancé. Vous pouvez appuyer sur la touche a pour forcer Jest à exécuter tous les tests unitaires:

Nous pouvons également forcer ce comportement en passant le drapeau –watchAll: [19659008] npm test – –watchAll

Si nous introduisons à présent un changement radical comme celui-ci:

 class   App   extend   Component   {
   render  ( )   {
     lancer   nouveau   Erreur  ( 'OOPS' ) ; 
     // ... 
  } 
} 

Jest relancera immédiatement le test et nous alertera:

Cool, notre flux de tests de base fonctionne parfaitement!

Permettre la couverture de tests dans notre projet

La quantité de code qui est exercée par nos tests unitaires est appelée couverture de test. Il est très utile de savoir quelles parties de notre code ne sont pas couvertes par les tests unitaires. Nous pouvons dire à Jest de capturer et d'afficher cette information en passant le drapeau –coverage:

 npm test - --coverage 

Jest nous dit que notre application.js le composant est entièrement couvert par les tests unitaires, mais index.js et serviceWorker.js ne le sont pas, ce qui est une excellente information à avoir!

Il est également intéressant de noter que Jest n'a pas démarré en mode veille lorsque nous avons passé l'indicateur –coverage. . Je ne sais pas pourquoi cependant. ?‍

J'ai tendance à modifier la section des scripts de mon package.json comme suit:

 {
   // ... 
   "scripts" :   {[19659050] "start" :   "Réactivez les scripts" 
     "build" :   "Réactez les scripts build" 
     "regardez" :   "test des scripts - couverture --watch" 
     "test" :   "test des scripts - couverture - [19659050] "éjecter" :   "réagir-scripts éjecter" 
  } 
} 

Ainsi, je peux faire un test npm si je veux exécuter mes tests une fois et npm run surveiller si je veux les réexécuter à chaque fois que je modifie, mais je reçois des informations sur la couverture de code dans les deux cas.

Ok , modifions ce composant App pour afficher de manière conditionnelle le logo React en fonction des accessoires qui lui ont été transmis:

 class   App   extend   Component   {
   render  ( )   {
     const   { showLogo }   =   ce .  accessoires ; 

     retour [19659020] (
       < div className  =  "App" > 
         < en-tête className  =  "App-header" > 
           { showLogo ?   (
             < img src  =  { logo }  du nom de classe  = 19659029] "App-logo"  alt  =  "logo"   / > 
          )   :   (
             < h1 >  En savoir plus sur Réagir  < /  h1 > 
          ) } 
         <19659092].  /  en-tête > 
       < /  div > 
    ) ; 
   / 
} 
} 

Si nous relançons nos tests avec npm test, certains chiffres vont changer:

Avez-vous vu comment% Branch est tombé à 50% pour App.js? C’est parce que notre test unitaire existant ne couvre qu’une branche de la déclaration ternaire que nous avons introduite, mais pas l’autre. La colonne Uncovered Line #s nous indique les lignes qui ne sont pas entièrement couvertes.

Il existe un meilleur moyen de visualiser ce qui est couvert et ce qui ne l’est pas,

Afficher la couverture de test au format HTML

Jest s’appuie sur un projet appelé Istanbul pour générer ses rapports de couverture de code. Par défaut, Jest génère des rapports dans une multitude de formats (json, lcov, texte, trèfle), mais nous pouvons le configurer pour utiliser tout journaliste valide à Istanbul via l'option couvertureReporteurs. Nous avons juste besoin d'ajouter une nouvelle section “plaisanterie” à notre package.json avec la liste des journalistes:

 {
   // ... 
   "plaisanterie" :   {[19659050] "couvertureReporters" :   [ "texte"   "html" ] 
  } 
} 

Jest est maintenant configuré pour produire des rapports de couverture de code au format texte et html. Le premier est celui qui imprime les résultats sur la console, tandis que le second génère un fichier index.html dans un dossier appelé couverture / à la racine de notre projet. Si nous l’ouvrons dans un navigateur, nous verrons un résumé de tous les fichiers et de leurs valeurs de couverture. Nous pouvons cliquer sur chacun de ces fichiers et voir notre code annoté dans des zones non entièrement couvertes. Il est beaucoup plus facile d'identifier où nous devons améliorer nos tests.

Essayons cela en exécutant nos tests avec npm test et en ouvrant le fichier cover / index.html:

[1945]. 19659004] Si nous cliquons sur App.js, nous verrons le fichier avec les annotations de couverture:

Cette ligne jaune est celle qui n'est pas utilisée par nos tests unitaires. 19659004] La tâche de test npm s'est bien déroulée, car une couverture de 100% des tests n'est pas requise pour la réussite de nos tests unitaires. Mais si je voulais me forcer à atteindre une couverture de test de 100% dans certaines zones?

Assurer une couverture de test complète

Nous pouvons configurer Jest pour qu'il échoue à nos tests s'ils n'atteignent pas un certain seuil de couverture grâce à l'option couvertureThreshold . Les seuils peuvent être spécifiés comme «globaux» si nous voulons qu’ils soient appliqués à chaque fichier de notre projet, ou comme un chemin ou un objet global si nous voulons seulement les appliquer à certains fichiers.

Par exemple, avec la configuration suivante, Jest échouera s'il y a moins de 100% de couverture de branche, de fonction, de ligne et d'instruction, mais uniquement pour les fichiers contenus dans un dossier appelé components /:

 {
   // ... 
   "jest" :   {
     "couvertureReporters" :   [ "texte"   "html" ] 
     " couvertureThreshold ":   {
      " src / components / ** ":   {
        " branches ":   100 
         "fonctions" :   100 
         "lignes" :   100 
         "déclarations" :   100 
       } 
    } 
  } 
} 

Si nous déplaçons notre composant App.js sous un dossier components /, puis exécutons npm test, nous obtiendrons ceci:

La tâche a échoué et Jest a expliqué pourquoi. :

 Commentaire: Le seuil de couverture des branches (100%) "my-app / src / components / App.js" n'est pas atteint: 50% 

Bien, je suis maintenant obligé de remédier à cela!

Réalisation Couverture complète du test

Nous devrons modifier le test unitaire existant pour obtenir une couverture complète du code. Je suis plus habitué à écrire des tests avec enzyme, aussi installons-le vite avant de faire autre chose:

 npm install  -  save  -  dev enzyme  -  adaptateur  -  réagissez  -16  

Nous devrons également créer un fichier setupTests.js sous src / avec le contenu suivant:

 import  Enzyme  de   "enzyme" ; 
 import  Adaptateur  de   de "1965-adaptateur-réagir-16" ; 

Enzyme .  configure  ( { adaptateur :   new   Adaptateur  ()  } ) ). 19659022]; 

Bien, nous sommes prêts à partir. Remplaçons le test unitaire existant par quelque chose comme ceci:

 import  Réagissez  à partir de   "réagissez" ; 
 import   { peu profond } 19659018] de   "enzyme" ; 
 import  App  de   "./ App" ; 

 décrit  ( "App "  ()   =>   {
   let  wrapper ; 

   décrivent  (" lorsque "showLogo" est vrai "  ()   =>   {
     beforeEach  ( ()   =>   {
      wrapper  =   peu profonde  ( < App showLogo  =  { true }   / > ) ; 
    } ) ; 

     it  ( "restitue une image"   ()   => [19659020] {
       expect  ( wrapper .  find  ( "img" ) ) . .  pour une plus grande longueur [19659022] ( 1 ) ; 
    } ) ; 
  } ) ; 

   décrivez  ( "lorsque` showLogo` est faux "  ()   =>   {
     beforeEach  ( ()   =>   {
      wrapper  =   peu profonde  ( < App showLogo  =  { false }   / > ) ; 
    } ) ; 

     it  ( 'rend un en-tête'   ()   => [19659020] {
       expect  ( wrapper .  find  ( "h1" ) .  texte  ([19659022]) ) .  toEqual  ( "Learn React" ) ; 
    } ) ; 
  } ) ; 
} ) ; 

Si nous relançons nos tests avec le test npm, nous verrons quelque chose comme:

Salut,% Branch est de retour à 100% et les tests passent! 1965

Empêcher l'utilisation de code non testé à l'aide de Husky

Maintenant que nous savons comment assurer une couverture complète des tests dans les zones de notre projet, je souhaite aller plus loin et m'empêcher de commettre ou de pousser à mon référentiel si des tests sont effectués. t passants ou si les seuils de couverture ne sont pas atteints.

Pour ce faire, utilisez les crochets Git, qui relient ensemble les actions Git, telles que commettre ou pousser, avec l'exécution de tâches personnalisées (dans notre cas, npm test ). Il existe un projet appelé Husky qui facilite la configuration des crochets.

Nous devons d’abord installer le package:

 npm install  -  save  -  dev husky [19659009] Ensuite, nous allons configurer les hooks que nous voulons utiliser dans notre projet. Nous ajouterons une section intitulée «husky» dans notre package.json et expliquerons comment nous allons mapper les crochets aux tâches. 

Dans notre exemple d'application, nous allons utiliser les crochets pre-commit et pre- faites en sorte que tous nos tests soient exécutés avant de valider et de pousser le code, respectivement:

 {
   // ... 
   "husky" :   {
     "hooks"  :   {
       "pre-commit" :   "test npm" 
       "pre-push" :   "test npm" 
     } 
  } 
} 

Si nous essayons de nous engager maintenant en faisant git commit -m “Ajouter un accessoire showLogo à App”, nous verrons Husky exécuter nos tests avant la création de la validation. Si les tests échouaient, la validation ne serait pas créée. Dans ce cas, ils ont passé, nous avons donc pu nous engager bien:

Super boulot, Husky! 1965

Conclusion

Tester notre code est l’une des meilleures choses que nous puissions faire pour nous assurer de ne pas introduire de régression à chaque fois que nous apportons un changement. Avec les outils et astuces décrits ici, nous pouvons appliquer une couverture de test complète dans les zones de notre projet, afficher les rapports de couverture de code dans de nombreux formats et utiliser des points d'ancrage pour garantir que tout va bien avant de valider et de transférer du code dans notre référentiel. Maintenant, je n’aurai pas d’autre choix que de manger mes légumes! ?


Les commentaires sont désactivés en mode Prévisualisation.




Source link
Quitter la version mobile