0% ont trouvé ce document utile (0 vote)
17 vues39 pages

Zoom Sur Les Tests

Transféré par

suon
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
17 vues39 pages

Zoom Sur Les Tests

Transféré par

suon
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Jérémy Sorant

Zoom sur

Les tests
Jérémy Sorant

définition
Un test consiste à jouer une portion de code dans un
contexte donné puis vérifier son comportement via
des assertions.

Il permet de savoir si le code fonctionne tel qu’on le


souhaite, c’est à dire tel que cela est spécifié dans le
test. Ce retour est appelé par la suite “feedback”.
Jérémy Sorant

Bénéfices
Les tests me donnent un feedback rapide tout au long
de mon développement sur le fait que mon code
respecte l’ensemble de mes assertions. Ce qui
engendre de la confiance pour délivrer du code et de la
flexibilité car le filet de sécurité qu’ils constituent
facilite la modification de code existant.

Ils me servent aussi de documentation vivante.

Ils m’aident à conserver une productivité haute.


Jérémy Sorant

Automatisés
Parce que je veux un grand nombre de tests et que je
souhaite pouvoir les rejouer facilement et rapidement,
il est primordial que ces tests soient automatisés.

Il m’arrive de faire des tests manuels pour explorer un


comportement, mais dès que possible, je bascule sur
l’écriture d’un test automatisé.
Jérémy Sorant

F.I.R.S.T.
FIRST est un acronyme désignant cinq propriétés que
je respecte lorsque je rédige un test :

Fast, Independant, Repeatable,


Self-validating et Thorough
Jérémy Sorant

fast
Un test devrait être aussi rapide que possible.

A titre d’exemple, pour un test unitaire, je souhaite un


feedback de l’ordre de la milliseconde.

Pour cela, j’évite les timers/sleep, je ne teste pas la


même chose plusieurs fois, et j’évite de dépendre de
l’infrastructure réelle (base de données, API tierce...).
Jérémy Sorant

independant
Un test devrait être indépendant des autres tests et de
l’environnement dans lequel on le lance.

Je m’assure d’isoler mes tests de manière à pouvoir


les lancer en parallèle, sans que cela n’ai d’impact sur
le résultat de chacun d’entre eux.
Jérémy Sorant

reapetable

Un test devrait être répétable.

On devrait pouvoir répéter un test autant de fois


qu’on le souhaite sans que cela n’ai d’impact sur le
résultat du test.
Jérémy Sorant

self-validating
Un test devrait indiquer lui-même si il est en réussite
ou en échec. Pour cela, je m’assure d’écrire au
minimum une assertion par test.

On ne devrait pas avoir à faire d’opération manuelle


pour vérifier un test (par exemple regarder des logs
ou le contenu d’une base de données).
Jérémy Sorant

thorough
Les tests devraient couvrir une fonctionnalité
dans son ensemble.

Je teste en premier lieu le cas nominal, mais aussi les


cas aux limites, les cas d’erreur, les comportements
inattendus (undefined / null) et les cas relatifs
à la sécurité.
Jérémy Sorant

Doublures de test
Ce terme vient du cinéma où l’on utilise des doublures
lors de scènes d’acrobatie dangereuses qui ne sont
alors pas effectuées par les “vrais” acteurs.

Dans le monde du dev, il existe plusieurs types de


doublures de tests : dummy, stub, spy, mock et fake.
Jérémy Sorant

dummy
Un dummy est une implémentation minimaliste d’une
doublure de test.

Je l’utilise quand un objet est nécessaire pour créer un


test mais que cet objet ne sera pas utilisé.
Jérémy Sorant

stub
Le stub est un dummy qui permet en plus de pouvoir
définir le comportement de la doublure de test.

On peut indiquer le retour d’une fonction doublée,


exécuter une portion de code à la place de la fonction
originale ou encore lever des exceptions.

Il m’est très utile pour améliorer les performances de


mes tests et réduire leur complexité.
Jérémy Sorant

spy
Le spy est un stub qui permet en plus d’observer
l’utilisation de la doublure de test.

On peut savoir combien de fois une fonction doublée


a été appelée et avec quels arguments.

Je m’en sers pour vérifier que j’agis correctement sur


une autre couche applicative dont dépend le bout de
code que je teste.
Jérémy Sorant

mock
Le mock est un spy qui produit implicitement des
assertions sur les comportements qui lui ont été
définis.

À la fin de l’exécution d’un test, si un une fonction


“mockée” n’a pas été appelée, le test sera en échec.

Je n’utilise que très rarement cette doublure car elle


est un antipattern du GWT/AAA (voir plus loin).
Jérémy Sorant

fake
Implémentation manuelle d’une doublure de test.

Il s’agit de la première forme de doublure de test, avant


l’apparition de ces nombreuses librairies qui nous offrent
aujourd’hui les stubs, spies et mocks.

Le fake me permet de réaliser une implémentation très


basique et rapide d’un composant lourd pour simplifier
certains tests. Par exemple, je peux créer une base de
données “in memory” plutôt qu’utiliser un vrai connecteur.
Jérémy Sorant

Types de tests
Selon ce qu’ils permettent de tester, il est possible de
classer les tests par type ou par catégorie.

Attention : les nommages qui vont suivre sont ceux


que je suis habitué à employer. Mais ces noms
peuvent être utilisés par d’autres personnes pour
désigner d’autres types de tests.
Jérémy Sorant

Tests unitaires
Les tests unitaires me permettent de tester une unité
fonctionnelle. Ils n’ont pas de dépendance lourde et
sont donc très rapides à exécuter.

Comme ils sont simple à écrire et qu’ils me donnent


un feedback de l’ordre de la milliseconde, je vise à
maximiser leur nombre. Il me permettent de détecter
la majorité des problèmes rapidement.
Jérémy Sorant

Unité fonctionnelle
Je teste le comportement d’une unité fonctionnelle.

Je n’écris pas nécessairement un test par fonction ou


méthode publique.

De plus, mon test peut faire appel à plusieurs


fonctions ou méthodes pour vérifier le comportement
de cette unité fonctionnelle.
Jérémy Sorant

Tests Traversants
J’extrais parfois une classe ou une fonction pendant un
refactoring. Cette nouvelle entité ne nécessite pas de test
dédié puisque son code est déjà couvert par un test
existant, au travers du code dont elle est extraite.

En ne couplant pas mes tests aux détails


d’implémentation, je me laisse la possibilité de refactorer
le code sans risquer de devoir réécrire mes tests.
Jérémy Sorant

Comportement
Je m’assure de tester un comportement plutôt qu’une
implémentation. Cela me permet d’avoir des tests
plus solides.

Je n’ai pas avoir besoin de savoir comment est/sera


implémentée une fonctionnalité pour pouvoir rédiger
un test.
Jérémy Sorant

Dépendances

J’utilise des doublures de tests lorsque le code testé


dépend d’implémentations lourdes qui ne sont pas
l’objet du test ou lorsque je souhaite découpler le code
de ces implémentations.
Jérémy Sorant

usages et outils
Dans un contexte d’architecture hexagonale ou de
clean architecture, les tests unitaires me permettent
de valider le “domain” et les transformations
effectuées dans les “adapters”.

Pour les patterns MVP et MVVM, ils me permettent de


tester tout ce qui n’est pas de l’UI (la couche “V”).

Outils : JUnit, Vitest, Jest, Mockito, Sinon...


Jérémy Sorant

Tests d’intégration
Les tests d’intégrations me permettent de vérifier les
interactions avec du code externe à mon système, par
exemple un connecteur de base de données, une
librairie tierce ou l’appel à un service tiers.

Je ne teste pas ce code externe car je suppose que je


peux lui faire confiance. Par contre, je teste que je
l’utilise correctement dans le cadre de mes besoins.
Jérémy Sorant

Tests d’intégration
Ils peuvent aussi me permettre de découvrir le
fonctionnement de ce code externe avec une boucle de
feedback bien plus courte que si je devais démarrer le
produit dans son ensemble.

Ces tests peuvent être relativement coûteux, j’essaie donc


de restreindre le code au strict minimum et de m’assurer
de ne pas lier de logique métier ou d’adaptation.
Jérémy Sorant

usages et outils

Dans un contexte d’architecture hexagonale ou de


clean architecture, les tests d’intégration me
permettent de valider tout appel direct à de
“l’infrastructure”.

Outils : JUnit, Vitest, Jest, TestContainers...


Jérémy Sorant

Tests de Contrat
Les tests de contrat sont utiles dès lors que j’expose
une API publique.

Ils me permettent de m’assurer que je n’apporte pas


de régression dans les contrats d’API définis lorsque
je modifie la base de code.
Jérémy Sorant

Tests de composant
Les tests de composant me permettent, moyennant
des cas d’usage, de tester l’application dans son
ensemble mais isolée de tout lien vers l’extérieur.

Pour cela, j’utilise soit des doublures de tests pour des


tests en boîte blanche, soit de l’interception de flux
sortant ou des faux composants externes pour des
tests en boîte noire.
Jérémy Sorant

Tests de composant
Ces tests sont assez coûteux et n’ont pas vocation à
couvrir tous les cas, ceux-ci seront couvert par
d’autres types de tests. Je les utilise pour valider les
cas les plus important du métier.

Je sollicite le métier pour définir ensemble les


scénarios qui seront traduits en tests de ce type.
Jérémy Sorant

usages et outils
Mes tests de composant manipulent “l’api” pour
l’architecture hexagonale et “l’infrastructure” pour la
clean architecture. J’utilise des stubs ou de
l’interception de flux pour isoler mon application.

Outils : Gherkin, Cucumber, Karate, Supertest,


Cypress, Mockito, Sinon, Nock...
Jérémy Sorant

Tests end-to-end
Les tests end-to-end sont des tests en conditions
réelles. Je teste mon produit déployé en pré-prod et
connecté à l’ensemble de ses dépendances externes.

Ces tests sont très lourds, coûteux et fragiles. C’est


pourquoi je me limite à ne tester que les cas les plus
critiques définis avec le métier.
Jérémy Sorant

usages et outils
Mes tests end-to-end manipulent le produit via
“l’api” pour l’architecture hexagonale et via
“l’infrastructure” pour la clean architecture.

Outils : Gherkin, Cucumber, Karate, Cypress,


TestContainers, Docker
Jérémy Sorant

Tests non fonctionnels


Ces tests me permettent de vérifier des aspects
non fonctionnels du produit mais nécessaires à
son bon fonctionnement.

Je peux tester par exemple le temps de réponse, la


disponibilité, la résilience ou encore la sécurité
d’un produit.
Jérémy Sorant

usages et outils

Les tests à mettre en œuvre sont grandement


dépendants du type d’application développé.

Outils : JMeter, Gatling, Burp, SonarQube,


SAST/DAST/IAST...
Jérémy Sorant

Stratégie de test
Pour plus d’efficacité, j’adopte une stratégie de tests.

J’utilise depuis de nombreuses années la “pyramide de


tests” et le “diamant”. Combinée à une architecture
centrée métier, l’implémentation de ces stratégies est
simple et limpide.

Il existe d’autres stratégies de tests comme le nid


d’abeilles, le trophée, le cône de glace ou encore le crabe.
Jérémy Sorant

Qualité du code
Le code relatif aux tests est pour moi aussi important
que le code de prod.

Il doit être bien organisé, lisible et facile à retravailler.

En d’autres termes, il doit bénéficier des mêmes


attentions que celles portées au code de prod.
Jérémy Sorant

Gwt & AAA


GWT = Given / When / Then
AAA = Arrange / Act / Assert

Ces deux façons d’organiser le code d’un test reposent


sur le même principe : je commence par établir un
contexte, je déclenche ensuite un comportement, puis
je vérifie le résultat de ce comportement.
Jérémy Sorant

Couverture de tests
La couverture de tests est une métrique qui m’indique
le taux de code couvert par les tests. Elle me permet
de révéler des manquements dans les tests.

Elle peut toutefois être erronée si un test ne fait pas


d’assertion ou de “mauvaises” assertions.
L’utilisation de cet outil ne remplace donc pas le soin
que j’apporte lors de l’écriture des tests.
Jérémy Sorant
ingénieur logiciel sénior
chez SHODO LYON

l’ESN craft militante


#justicesociale

Vous aimerez peut-être aussi