Le seul type de test que j'écris

Dec 04 2022
Il y a une conversation presque constante au niveau de fond dans le monde de l'ingénierie sur les types de tests qui sont les meilleurs ; tests unitaires, tests d'intégration, tests de bout en bout, etc. Il y a quelque temps, j'ai décidé que je n'allais écrire qu'un seul type de test.

Il y a une conversation presque constante au niveau de fond dans le monde de l'ingénierie sur les types de tests qui sont les meilleurs ; tests unitaires, tests d'intégration, tests de bout en bout, etc.

Il y a quelque temps, j'ai décidé que je n'allais écrire qu'un seul type de test.

Je ne suis pas vraiment sûr qu'il s'intègre parfaitement dans l'une des catégories ci-dessus. Peut-être que "test d'intégration" est le plus correct, mais cela ne le couvre pas tout à fait - notamment parce que personne ne peut vraiment s'entendre sur la façon de définir réellement ce que signifient ces différentes étiquettes.

Voici les principes que j'applique :

  1. Je n'écris pas un seul test tant que je n'ai pas défini une interface publique claire.
  2. Mes tests doivent reproduire le plus fidèlement possible le comportement d'un utilisateur réel . Cela signifie appeler uniquement les API publiques, ou s'il s'agit d'une interface frontale conçue pour un utilisateur final, ne faire que ce qu'un utilisateur final ferait.
  3. Si une fonction ou un composant ne fait pas partie de l'interface publique, je ne le teste pas directement. S'il n'est pas possible de l'invoquer indirectement via un chemin public, quel est exactement son but de toute façon ?
  4. Aucun appel réseau à distance. S'il ne s'agit pas d'un appel à localhost (par exemple, une base de données de test locale), il doit être simulé. Mes tests doivent réussir de manière cohérente sans réseau ni connexion Internet.
  5. Pas de moquerie des chemins de code internes. Se moquer de la limite du réseau est génial, mais se moquer des fonctions ou des apis qui existent dans la base de code que je teste est interdit.
  6. Aucun état porté à travers différents tests. Si un test repose sur l'état d'un test précédent, ou pourrait être affecté par cet état de quelque manière que ce soit, quelque chose s'est mal passé. Cela ne signifie pas nécessairement "effacer tous les états après chaque test".
  7. Pas de test d'état interne. Si je dois initialiser ou modifier manuellement un état interne dans mon test (sans utiliser une autre interface publique existante), mon test n'est probablement pas bon.
  8. Aucun test des détails de mise en œuvre interne. Si la refactorisation de mon code fait échouer le test, ce n'est probablement pas un bon test.
  9. Pas de "tests unitaires" qui invoquent des fonctions internes. Si je ressens le fort désir de tester des fonctions comme celle-ci, elles devraient probablement être divisées en leur propre module ou package autonome au préalable, avec une interface claire qui est complètement découplée de toute logique métier.
  10. Pas de tests de style "de bout en bout" qui nécessitent de faire tourner un serveur et une base de données complets et plusieurs services et de les exécuter tous ensemble, à moins qu'il ne soit extrêmement opportun de le faire sur mon hôte local.
  11. Je me concentre sur la "couverture des cas d'utilisation" plutôt que sur la "couverture des lignes de code".
  12. Écrivez d'abord un test s'il est très clair à quoi ressemblera l'interface publique à l'avance. Sinon, écrivez d'abord le code, puis testez-le.
  13. J'enfreins l'une des règles ci-dessus lorsqu'il vaut mieux le faire que de ne pas écrire de test ou de laisser un cas d'utilisation non testé.