5 votes

Fichier de données externes pour les tests unitaires

Je suis novice en matière de tests unitaires et j'ai besoin de conseils sur les meilleures pratiques. Je code en Cocoa avec Xcode.

J'ai une méthode qui valide une URL qu'un utilisateur entre. Je veux qu'elle n'accepte que le protocole http:// et que les URL ne contiennent que des caractères valides.

Est-il acceptable d'avoir un seul test pour cela et d'utiliser un fichier de données de test ? Le fichier de données fournit des exemples d'URL valides/invalides et indique si l'URL doit être validée ou non. Je l'utilise également pour vérifier la description et le domaine du message d'erreur.

Pourquoi je fais cela

J'ai lu Pragmatic Unit Testing in Java with JUnit, qui donne un exemple avec un fichier de données externe, ce qui me fait penser que c'est correct. De plus, cela signifie que je n'ai pas besoin d'écrire beaucoup de tests unitaires avec un code très similaire juste pour tester des données différentes.

Mais d'un autre côté...

Si je fais un test pour :

  • caractères non valides
  • y un protocole invalide
  • y URLs valides

tous dans le même fichier de données de test (et donc dans le même test) cela me posera-t-il des problèmes par la suite ? J'ai lu qu'un test ne devait échouer que pour une seule raison.

Est-ce que ce que je fais est bien ?

Comment les autres personnes utilisent-elles les données de test dans leurs tests unitaires, si elles le font ?

7voto

NamshubWriter Points 7238

En général, n'utilisez un fichier de données de test que lorsque c'est nécessaire. L'utilisation d'un fichier de données de test présente un certain nombre d'inconvénients :

  • Le code de votre test est réparti entre le code de test et le fichier de données de test. Cela rend le test plus difficile à comprendre et à maintenir.
  • Vous voulez que vos tests unitaires soient aussi rapides que possible. Avoir des tests qui lisent inutilement des fichiers de données peut ralentir vos tests.

Il y a quelques cas où j'utilise des fichiers de données :

  • L'entrée est volumineuse (par exemple, un document XML). Bien que vous puissiez utiliser la concaténation de chaînes de caractères pour créer une grande entrée, cela peut rendre le code de test difficile à lire.
  • Le test teste en fait le code qui lit un fichier. Même dans ce cas, vous pouvez demander au test d'écrire un fichier d'exemple dans un répertoire temporaire afin que tout le code du test se trouve au même endroit.

Au lieu de coder les URLs valides et invalides dans le fichier, je suggère d'écrire les tests dans le code. Je suggère de créer un test pour les caractères invalides, un test pour les protocoles invalides, un test pour les domaines invalides et un test pour une URL valide. Si vous pensez que la couverture n'est pas suffisante, vous pouvez créer un mini test d'intégration pour tester plusieurs URL valides et invalides. Voici un exemple en Java et JUnit :

public void testManyValidUrls() {
  UrlValidator validator = new UrlValidator();
  assertValidUrl(validator, "http://foo.com");
  assertValidUrl(validator, "http://foo.com/home");
  // more asserts here
}

private static void assertValidUrl(UrlValidator validator, String url) {
  assertTrue(url + " should be considered valid", validator.isValid(url);
}

2voto

Mark Seemann Points 102767

Bien que je pense qu'il soit parfaitement raisonnable de se poser cette question, je ne pense pas que vous deviez vous en inquiéter outre mesure. À proprement parler, vous avez raison de dire que chaque test ne doit tester qu'une seule chose, mais cela ne vous empêche pas d'utiliser un fichier de données.

Si votre système sous test (SUT) est un simple analyseur/validateur d'URL, je suppose qu'il prend une seule URL comme paramètre. En tant que tel, il y a une limite à la quantité de données simultanément invalides que vous pouvez lui fournir. Même si vous introduisez une URL contenant à la fois des caractères invalides et un protocole invalide, vous n'obtiendrez qu'un seul résultat (l'URL est invalide).

Ce que vous décrivez est un test piloté par les données (également appelé test paramétré). Si le test lui-même reste simple, le fait de l'alimenter avec des données différentes ne pose pas de problème en soi.

Ce que vous faire La seule chose dont vous devez vous préoccuper est que vous voulez être en mesure de localiser rapidement la raison de l'échec d'un test lorsque/si cela se produit dans quelques mois. Si la sortie de votre test pointe vers une ligne spécifique de votre fichier de données de test, vous devriez être en mesure de comprendre rapidement ce qui n'a pas fonctionné. D'un autre côté, si le seul message que vous obtenez est que le test a échoué et que n'importe quelle ligne du fichier pourrait être en cause, vous commencerez à voir les contours d'un cauchemar de maintenabilité des tests.

Personnellement, je penche légèrement pour que les données d'essai soient associées le plus étroitement possible aux essais. C'est parce que je considère le concept de tests comme des spécifications exécutables comme très important. Lorsque les données de test sont codées en dur dans chaque test, elles peuvent spécifier très clairement la relation entre l'entrée et la sortie attendue. Plus vous retirez les données du test lui-même, plus il devient difficile de lire cette "spécification".

Cela signifie que j'ai tendance à définir les valeurs des données d'entrée dans chaque test. Si je dois écrire un grand nombre de tests très similaires où la seule variation est l'entrée et/ou la sortie attendue, j'écris un test paramétré, mais j'invoque toujours ce test paramétré à partir de tests codés en dur (qui ne représentent chacun qu'une seule ligne de code). Je ne pense pas avoir jamais utilisé de fichier de données externe.

Mais encore une fois, ces jours-ci, je n'ai même pas connaître quelle est mon entrée, puisque j'utilise Non-déterminisme contraint . Au lieu de cela, je travaille avec des classes d'équivalence et des Valeurs dérivées .

1voto

Ray Tayek Points 4635

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X