Emplacement d'exécution des tests

Les tests automatisés peuvent généralement être exécutés en exécutant un script manuellement ou à l'aide d'un outil d'aide d'un framework de test, souvent appelé exécuteur de test, pour rechercher et exécuter des tests. Cependant, vous n'aurez peut-être pas toujours besoin d'exécuter vos scripts manuellement. Il existe plusieurs façons d'exécuter vos tests. Elles peuvent vous apporter des commentaires et vous donner plus de confiance à différents stades du cycle de développement.

Script prérequis

Les projets Web disposent généralement d'un fichier de configuration (leur fichier package.json) configuré par npm, pnpm, Bun ou un fichier similaire. Ce fichier de configuration contient les dépendances de votre projet, ainsi que d'autres informations, ainsi que des scripts d'aide. Ces scripts d'aide peuvent indiquer comment compiler, exécuter ou tester votre projet.

Dans package.json, vous devez ajouter un script appelé test qui décrit comment exécuter vos tests. C'est important, car lorsque vous utilisez npm ou un outil similaire, le script "test" a une signification particulière. Ce script peut simplement pointer vers un seul fichier qui génère une exception (par exemple, node tests.js), mais nous vous recommandons de l'utiliser pour pointer vers un lanceur de test établi.

Si vous utilisez Vitest comme lanceur de test, le fichier package.json se présentera comme suit:

{
  "name": "example-project",
  "scripts": {
    "start": "node server.js",
    "test": "vitest --run"
  }
}

L'exécution de npm test avec ce fichier exécute une fois l'ensemble de tests par défaut de Vitest. Dans Vitest, la valeur par défaut consiste à rechercher tous les fichiers se terminant par ".test.js" ou à une adresse similaire, puis à les exécuter. Selon le lanceur de test que vous avez choisi, la commande peut être légèrement différente.

Nous avons choisi d'utiliser Vitest, un framework de test de plus en plus populaire, comme exemple tout au long de ce cours. Pour en savoir plus sur cette décision, consultez la page Vitest as a test runner. Cependant, il est important de garder à l'esprit que les frameworks de test et les exécuteurs, même dans plusieurs langues, ont tendance à avoir un langage vernaculaire commun.

Appel de test manuel

Le déclenchement manuel de vos tests automatisés (comme l'utilisation de npm test dans l'exemple précédent) peut être pratique lorsque vous travaillez activement sur un codebase. Écrire des tests pour une fonctionnalité lors du développement de cette fonctionnalité peut vous aider à vous faire une idée de son fonctionnement. Cela revient au concept de développement piloté par les tests (TDD, Test-driven development).

Les exécuteurs de test proposent généralement une commande courte que vous pouvez appeler pour exécuter une partie ou la totalité de vos tests, et éventuellement un mode d'observation qui réexécute les tests à mesure que vous les enregistrez. Toutes ces options sont utiles lors du développement d'une nouvelle fonctionnalité. Elles sont conçues pour faciliter l'écriture d'une nouvelle fonctionnalité, de ses tests ou des deux, le tout avec des retours rapides. Vitest, par exemple, fonctionne en mode observateur par défaut : la commande vitest surveille les modifications et réexécute les tests qu'elle trouve. Nous vous recommandons de laisser cette fenêtre ouverte dans une autre fenêtre pendant que vous écrivez des tests. Vous pourrez ainsi recevoir rapidement des commentaires sur vos tests au fur et à mesure que vous les développez.

Certains exécuteurs vous permettent également de marquer les tests comme only dans votre code. Si votre code inclut des tests only, seuls ces tests se déclenchent lorsque vous exécutez les tests, ce qui accélère le développement des tests et facilite le dépannage. Même si tous vos tests se terminent rapidement, l'utilisation de only peut réduire les frais généraux et éviter les distractions liées à l'exécution de tests sans rapport avec la fonctionnalité ou le test sur lequel vous travaillez.

Pour les petits projets, en particulier ceux avec un seul développeur, vous pouvez également prendre l'habitude d'exécuter régulièrement l'ensemble de la suite de tests de votre codebase. Cela est particulièrement utile si vos tests sont petits et se terminent rapidement (en quelques secondes pour tous vos tests), ce qui vous permet de vous assurer que tout fonctionne avant de continuer.

Exécuter des tests lors d'un pré-envoi ou d'un examen

De nombreux projets choisissent de confirmer qu'un codebase fonctionne correctement lorsque le code doit être fusionné à nouveau dans sa branche main. Si vous débutez dans les tests, mais que vous avez déjà contribué à des projets Open Source par le passé, vous avez probablement remarqué qu'une partie du processus de demande d'extraction confirme que tous les tests du projet sont concluants. Cela signifie que votre nouvelle contribution n'a pas eu d'impact négatif sur le projet existant.

Si vous exécutez vos tests localement, le dépôt en ligne de votre projet (par exemple, GitHub ou un autre service d'hébergement de code) ne saura pas que vos tests réussissent. Par conséquent, l'exécution des tests en tant que tâche de pré-envoi indique à tous les contributeurs que tout fonctionne correctement.

GitHub, par exemple, les appelle des "vérifications de l'état" que vous pouvez ajouter via GitHub Actions. Les actions GitHub sont fondamentalement un type de test: chaque étape doit réussir (elle ne doit pas échouer ni générer une erreur Error) pour que l'action aboutisse. Vous pouvez appliquer des actions à toutes les demandes d'extraction d'un projet. Un projet peut exiger que les actions soient transmises avant que vous puissiez contribuer au code. L'action Node.js par défaut de GitHub exécute npm test.

Capture d'écran d'un processus de test des actions sur GitHub.
Capture d'écran d'un processus de test GitHub Actions

Cette approche de test tente de s'assurer que votre codebase est toujours "vert" en n'acceptant pas le code qui n'exécute pas correctement ses tests.

Exécuter des tests dans le cadre de l'intégration continue

Une fois que votre demande d'extraction verte a été acceptée, la plupart des codebases réexécutent des tests en fonction de la branche main de votre projet, plutôt que sur la base du PR précédent. Cela peut se produire immédiatement ou de manière régulière (par exemple, toutes les heures ou la nuit). Ces résultats sont souvent affichés dans un tableau de bord d'intégration continue (CI) qui indique l'état général du projet.

Cette étape d'intégration continue peut sembler redondante, en particulier pour les projets dont le codebase est de petite taille. Ces tests ont été réussis lors de l'examen. Ils doivent donc être validés une fois la modification effectuée. Cependant, ce n'est pas toujours vrai. Vos tests peuvent échouer soudainement, même après avoir réussi à produire des résultats verts. Voici quelques-unes des raisons à cela:

  • Plusieurs modifications ont été acceptées "en même temps", parfois appelées condition de concurrence, et elles s'affectent les unes les autres de manière subtile et non testée.
  • Vos tests ne sont pas reproductibles ou testent un code "irrégulier" : ils peuvent à la fois réussir et échouer sans modification du code.
    • Cela peut se produire si vous dépendez de systèmes externes à votre codebase. Pour un proxy, imaginez un test si Math.random() > 0.05. Cela entraînerait un échec aléatoire de 5 % du temps.
  • Certains tests sont trop coûteux ou coûteux à exécuter sur chaque PR, tels que les tests de bout en bout (plus d'informations à ce sujet dans les types de tests automatisés). Ils peuvent s'interrompre au fil du temps sans qu'aucune alerte ne soit requise.

Aucun de ces problèmes n'est impossible à surmonter, mais il est utile de réaliser que les tests, et le développement logiciel en général, ne seront jamais une science exacte.

Intermédiaire sur le rollback

Lorsque les tests sont exécutés dans le cadre de l'intégration continue, et même dans le cadre d'une vérification de l'état, il est possible que la compilation finisse dans un état "rouge" ou dans un autre état indiquant que les tests échouent. Comme indiqué précédemment, cela peut se produire pour plusieurs raisons, y compris des conditions de concurrence lors de l'envoi des tests ou des tests irréguliers.

Pour les petits projets, votre instinct pourrait être de traiter cela comme une crise ! Arrêtez tout, effectuez un rollback ou annulez la modification incriminée, puis revenez à un état correct connu. Même si cette approche peut être valide, n'oubliez pas que les tests (et les logiciels en général) sont un moyen d'atteindre une fin, et non un objectif en soi. Votre objectif est probablement d'écrire des logiciels, et non de réussir tous les tests. À la place, vous pouvez effectuer un rollback en effectuant le suivi de la modification destructive par une autre modification qui corrige les tests ayant échoué.

D'autre part, vous avez peut-être vu ou travaillé sur de grands projets qui existent dans un état perpétuellement défaillant. Pire encore, le projet de grande envergure comporte un test irrégulier qui plante suffisamment souvent pour provoquer une fatigue de l'alarme chez les développeurs. Il s'agit souvent d'un problème existentiel que les responsables doivent résoudre: ces tests peuvent même être désactivés parce qu'ils sont perçus comme un "obstacle au développement".

Il n'existe pas de solution rapide à ce problème, mais cela peut aider à gagner en confiance en écriture de tests (upskilling) et à réduire la portée des tests (simplification) afin d'identifier plus facilement les échecs. Une augmentation du nombre de tests de composants ou de tests d'intégration (plus d'informations sur les types dans la section Types de tests automatisés) peut être plus fiable qu'un test de bout en bout énorme difficile à gérer et qui tente de tout faire en même temps.

Ressources

Testez vos connaissances

Quel est le nom du script spécial que npm et des programmes similaires recherchent lors des tests ?

cocher
test
pré-envoyer
verify