En quoi consistent les tests ?

Lorsque vous écrivez un logiciel, vous pouvez vérifier qu'il fonctionne correctement grâce à des tests. Le test peut être défini de manière générale comme le processus d'exécution d'un logiciel dans des moyens de s'assurer qu'il se comporte comme prévu.

Des tests réussis vous assurent que lorsque vous ajoutez du code, des fonctionnalités ou même mettre à niveau vos dépendances, le logiciel que vous avez déjà écrit continuent à fonctionner comme prévu. Les tests vous aident aussi à protéger des logiciels contre des scénarios improbables ou des entrées inattendues.

Voici quelques exemples de comportements à tester sur le Web:

  • S'assurer que la fonction d'un site web fonctionne correctement lorsqu'un utilisateur clique sur un bouton.
  • Vérifier qu'une fonction complexe produit les résultats corrects
  • Effectuer une action qui nécessite la connexion de l'utilisateur.
  • Vérifier qu'un formulaire signale correctement une erreur lors de la saisie de données incorrectes
  • S'assurer qu'une application Web complexe continue de fonctionner lorsqu'un utilisateur a extrêmement avec une bande passante faible ou hors connexion.

Tests automatisés ou manuels

Vous pouvez tester votre logiciel de deux manières générales: des tests automatisés et des tests manuels. tests.

Les tests manuels impliquent des humains exécutant directement le logiciel, comme le chargement d'un dans leur navigateur et en confirmant qu'il se comporte comme prévu. Manuel Les tests sont simples à créer ou à définir. Par exemple, votre site peut-il se charger ? Pouvez-vous d'effectuer ces actions ? Mais chaque exécution revient du temps des humains. Bien que les humains soient très créatifs, cela peut permettre une sorte de test connus sous le nom de tests exploratoires, il est encore difficile de repérer les échecs ou des incohérences, en particulier lorsqu’elles effectuent la même tâche plusieurs fois.

Les tests automatisés sont un processus qui permet de codifier et d'exécuter des tests à plusieurs reprises par un ordinateur pour confirmer le comportement souhaité de votre logiciel sans demander à une personne d’effectuer des étapes répétées, comme la configuration ou la vérification des résultats. Il est important de noter qu'une fois les tests automatisés configurés, vous pouvez les exécuter fréquemment. Il s'agit encore d'une définition très large, et il est important de noter que les tests prennent toutes sortes de formes et de formes. Ce cours concerne principalement avec des tests automatisés.

Les tests manuels ont leur place, souvent comme précurseur de l'écriture automatisée mais aussi lorsque les tests automatisés deviennent trop peu fiables, trop larges, ou difficiles à écrire.

Exemple : les principes de base

Pour nous, en tant que développeurs Web qui écrivent des langages JavaScript ou des langages associés, un test automatisé peut être un script comme celui-ci, exécuté tous les jours, via Node.js ou en le chargeant dans un navigateur:

import { fibonacci } from "../src/math.js";

if (fibonacci(0) !== 0) {
  throw new Error("Invalid 0th fibonacci result");
}
const fib13 = fibonacci(13);
if (fib13 !== 233) {
  throw new Error("Invalid 13th fibonacci result, was=${fib13} wanted=233");
}

Il s'agit d'un exemple simplifié qui fournit les informations suivantes:

  • Il s'agit d'un test, car il exécute un logiciel (le pipeline Fibonacci ) et garantit son bon fonctionnement fonctionne comme prévu en comparant ses résultats par rapport à les valeurs attendues. Si le comportement n'est pas correct, cela provoque une erreur, ce qui JavaScript exprime cette expression en générant une Error.

  • Même si vous exécutez ce script manuellement dans votre terminal ou dans un navigateur, il s'agit toujours d'un test automatisé, car il peut être exécuté plusieurs fois sans que vous ayez à effectuer des étapes individuelles. La page suivante, où de tests exécutés, explique plus en détail.

  • Même si ce test n'utilise aucune bibliothèque, fonctionner n'importe où : il s'agit toujours d'un test. De nombreux outils peuvent vous aider écrire des tests, y compris ceux qui seront abordés plus tard dans ce cours, mais ils continuent tous d'appliquer le principe fondamental de provoquer une erreur si quelque chose ne va pas.

Tester les bibliothèques en pratique

La plupart des bibliothèques ou des frameworks de test intégrés fournissent deux principales primitives qui facilitent l'écriture des tests: des assertions et un moyen de définir des tests indépendants. Ils seront abordés en détail dans la section suivante, assertions et autres primitives. Cependant, de manière générale, n'oubliez pas que presque tous les tests que vous voyez ou rédigez à l'aide de ces types de primitives.

Les assertions sont un moyen de combiner la vérification d'un résultat et l'apparition d'une erreur si quelque chose ne va pas. Par exemple, vous pouvez rendre le test précédent plus concis en introduisant assert:

import { fibonacci } from "../src/math.js";
import { assert } from "a-made-up-testing-library";

assert.equal(fibonacci(0), 0, "Invalid 0th fibonacci result");
assert.equal(fibonacci(13), 233, "Invalid 13th fibonacci result");

Vous pouvez améliorer encore ce test en définissant des tests indépendants, si vous le souhaitez regroupées dans des suites. La suite suivante teste indépendamment le modèle de Fibonacci et la fonction catalan:

import { fibonacci, catalan } from "../src/math.js";
import { assert, test, suite } from "a-made-up-testing-library";

suite("math tests", () => {
  test("fibonacci function", () => {
    assert.equal(fibonacci(0), 0, "Invalid 0th fibonacci result");
    assert.equal(fibonacci(13), 233, "Invalid 13th fibonacci result");
  });
  test("relationship between sequences", () => {
    const numberToCheck = 4;
    const fib = fibonacci(numberToCheck);
    const cat = catalan(numberToCheck);
    assert.isAbove(fib, cat);
  });
});

Dans ce contexte de tests logiciels, le nom test désigne un scénario test : scénario unique, indépendant et adressable, tel que la « relation entre séquences" dans l'exemple précédent.

Les tests nommés individuellement sont utiles pour les tâches suivantes, entre autres:

  • Déterminer comment un test réussit ou échoue au fil du temps
  • Mettez en avant un bug ou un scénario par son nom afin de pouvoir vérifier plus facilement scénario est résolu.
  • Exécuter certains tests indépendamment des autres (à l'aide d'un filtre glob, par exemple)

Une façon de considérer les scénarios de test consiste à utiliser les « trois A » des tests unitaires: organiser, agir et affirmer. À la base, chaque scénario de test:

  • Disposer des valeurs ou des états (il peut s'agir de données d'entrée codées en dur).
  • Effectuer une action, telle que l'appel d'une méthode.
  • Effectuez l'assertion des valeurs de sortie ou de l'état mis à jour (à l'aide de assert).

L'ampleur des tests

Les exemples de code de la section précédente décrivent un test unitaire, car ils pour tester des parties mineures de votre logiciel, souvent en vous concentrant sur un seul fichier. c'est-à-dire la sortie d'une seule fonction. La complexité des tests augmente au fur et à mesure d'envisager le code provenant de plusieurs fichiers ou composants, voire de différents systèmes (parfois hors de votre contrôle, tels qu'un service réseau ou le le comportement d'une dépendance externe). Pour cette raison, les types de test sont souvent nommés en fonction de leur champ d'application ou de leur échelle.

Outre les tests unitaires, voici quelques exemples d'autres types de tests : tests de composants, tests, tests visuels et tests d'intégration. Aucun de ces noms n’a des définitions rigoureuses et peuvent avoir différentes significations selon votre codebase. N'oubliez donc pas de vous en servir comme guide et de trouver des définitions pour vous. Par exemple, qu'est-ce qu'un composant testé dans votre système ? Pour pour les développeurs React, cela peut littéralement correspondre à un "composant React", mais il peut ont une signification différente pour les développeurs dans d'autres contextes.

L'échelle d'un test individuel peut le placer à l'intérieur d'un concept souvent appelé comme la "pyramide de test", qui peut être une bonne règle de base pour déterminer et comment il s'exécute.

<ph type="x-smartling-placeholder">
</ph> La pyramide des tests,
    avec des tests de bout en bout (E2E) en haut, des tests d&#39;intégration au milieu et
    les tests unitaires en bas de la page.
La pyramide des tests.

Cette idée a fait l'objet d'itérations, et d'autres formes ont maintenant été popularisées, comme le losange d'essai testant le cornet de glace. Vos priorités en termes d'écriture de test seront probablement propres à votre de votre codebase. Cependant, une fonctionnalité courante est que les tests plus simples, comme les tests unitaires, ont tendance à être plus rapides à exécuter, plus faciles à écrire (vous aurez donc plus d'exemples) et pour tester un champ d'application limité, alors que les tests complexes, comme les tests de bout en bout, difficile à écrire, mais vous pouvez tester un champ d’application plus large. En fait, la couche supérieure de nombreuses tester des formes est en général un test manuel, car certaines interactions des utilisateurs trop complexes pour être codifiées en test automatisé.

Ces types seront développés dans les types tests.

Testez vos connaissances

Quelles primitives la plupart des bibliothèques et des frameworks de test fournissent-ils ?

Un service d'exécution qui utilise un fournisseur de services cloud.
Certains exécuteurs intégrés au navigateur permettent d'externaliser vos tests, mais ce n'est pas une fonctionnalité normale de tester les bibliothèques.
Assertions qui entraînent des exceptions si elles ne sont pas satisfaites.
Bien que vous puissiez générer une erreur pour faire échouer un test, assert() et ses variantes ont tendance à être incluses, car elles facilitent la vérification à écrire.
Un moyen de catégoriser les tests dans la pyramide des tests.
Il n’y a pas vraiment de méthode standard pour le faire. Vous pouvez ajouter le préfixe noms de vos tests ou les placer dans des fichiers différents, mais la catégorisation n’est pas vraiment intégrée à la plupart des frameworks de test.
Possibilité de définir des tests indépendants par fonction
La méthode test() est incluse dans presque tous les tests des exécuteurs. C'est important, car le code de test ne s'exécute pas au niveau racine d'un fichier, ce qui permet au lanceur de test de traiter chaque scénario de test une unité indépendante.