Comment tester un lecteur de fichiers?

19

Je travaille sur un projet avec quelques formats de fichiers. Certains formats sont spécifiés par .xsds, d'autres par la documentation sur leurs sites Web respectifs, et certains sont des formats personnalisés personnalisés qui n'ont pas de documentation. Mwahahahaha.

Quel est le problème?

Je voudrais tester mes lecteurs de fichiers, mais je ne sais pas trop comment procéder. Le flux de l'application est en tant que tel:

file.___  ===> read by FileReader.java ===> which creates a Model object

où se trouve l' FileReaderinterface

public interface FileReader {
    public Model read(String filename);
}

Le Modelpossède un certain nombre d'attributs qui sont remplis lors de la lecture du fichier. Cela ressemble à quelque chose

public class Model {
    List<String> as;
    List<String> bs;
    boolean isAPain = true;
    // ...
}

Qu'est-ce que j'ai essayé?

Ma seule idée était de créer des "générateurs" de fichiers pour chaque format de fichier. Ces générateurs sont essentiellement des constructeurs qui acceptent quelques variables (par exemple, le nombre de commentaires à générer dans un fichier) et produisent un exemple de fichier que je lis ensuite et compare le résultat Modelavec les variables que j'ai utilisées pour générer initialement le fichier.

Cela a cependant quelques problèmes:

  • Les fichiers qu'il génère ne ressemblent pas à de vrais fichiers. Le générateur n'est en aucun cas conscient du contexte.
  • Il est difficile de reconnaître si le générateur a généré des cas de bord, car c'est moi qui définit manuellement les variables. Cette méthode est à peine meilleure que moi pour créer une douzaine de fichiers d'exemple.

Existe-t-il de meilleures façons de procéder?

EDIT: unité changée en intégration puisque c'est ce que je veux dire.

EDIT2: Voici un exemple des cas marginaux que j'ai mentionnés.

Chaque fichier représente un graphique composé de sommets et d'arêtes. Ces sommets et arêtes peuvent être attachés de différentes manières, donc:

v1 -- e1 --> v2 <-- e2 -- v3

est différent de

v1 -- e1 --> v2 -- e2 --> v3

en ce que la direction des bords importe. Je ne suis pas sûr que cela soit dans la portée de la question, mais il est difficile de trouver tous les cas d'arête pertinents lorsque je règle manuellement le nombre de sommets, le nombre d'arêtes et que je génère simplement les connexions de manière aléatoire.

sdasdadas
la source
1
Les tests basés sur les données viennent à l'esprit. Pouvez-vous donner des exemples concrets de cas marginaux (basés sur les cas marginaux qui pourraient éventuellement être déclenchés dans la FileReadermise en œuvre réelle )? Exemple: étant donné les cas marginaux trouvés dans les formats de fichier image , pour chaque entrée de table, si la combinaison de propriétés ligne / colonne est prise en charge, il devrait y avoir au moins un cas de test (un fichier de données) couvrant cette combinaison.
rwong
@rwong J'ai ajouté un exemple mais je ne sais pas si cela vous donne une idée. Je suppose que mon problème est commun avec les cas de bord, c'est-à-dire. En ai-je manqué? Cependant, les tests basés sur les données semblent intéressants. Merci!
sdasdadas
7
De plus, je viens de le remarquer, mais mes cas de bord sont littéralement des cas de bord .
sdasdadas
1
Pourquoi ne pas créer des fichiers de test à la main, puis les exécuter toujours contre les mêmes?
Bobson
@Bobson C'est un peu pire que d'utiliser un générateur. Dans ce cas, je risque de manquer des cas marginaux (car il me manque probablement maintenant), mais je peux également introduire des erreurs dans ma frappe. Et avec des fichiers énormes, les créer moi-même prendrait un certain temps.
sdasdadas

Réponses:

19

Tout d'abord, parlons de vos objectifs:

  • vous ne voulez évidemment pas tester les "formats de fichiers" - vous voulez tester vos différentes FileReaderimplémentations

  • vous voulez trouver autant de types d'erreurs que possible par des tests automatiques

Pour atteindre pleinement cet objectif, à mon humble avis, vous devez combiner différentes stratégies:

  • tout d'abord, des tests unitaires réels: vos FileReaderimplémentations comprendront de nombreuses parties et fonctions différentes. Écrivez de petits tests qui testent chacun d'eux isolément; Concevez vos fonctions de manière à ce qu'elles n'aient pas vraiment besoin de lire les données d'un fichier. Ce type de tests vous aidera à tester la plupart de vos cas de bord.
  • deuxièmement, les fichiers générés: ce sont ce que j'appellerais des tests d'intégration. Ces fichiers vous aideront à rechercher des échecs différents du point 1, par exemple, des combinaisons de paramètres spécifiques, des erreurs d'accès aux fichiers, etc. classes d'équivalence ou tests de valeurs limites. Obtenez une copie de ce livre de Glenford Myers pour en savoir plus à ce sujet. L' article de Wikipedia sur les tests de logiciels est également une bonne ressource.
  • Troisièmement, essayez d'obtenir des données du monde réel: il peut être difficile de vérifier que ces fichiers sont correctement évalués par les vôtres FileReader, mais cela peut valoir la peine car il trouve souvent des bogues non révélés par les deux premières stratégies. Certains appelleraient ces choses aimables aussi des «tests d'intégration», d'autres préfèrent des «tests d'acceptation», mais en fait le terme n'a pas vraiment d'importance.

À mon humble avis, il n'y a pas d'approche "raccourcie" qui vous apporterait l'avantage des trois stratégies "pour le prix d'une". Si vous voulez détecter les cas marginaux ainsi que les défaillances dans les cas standard ainsi que dans les cas réels, vous devez investir au moins un certain effort - plus probablement beaucoup -. Heureusement, toutes ces approches peuvent être utilisées pour créer des tests automatiques et reproductibles.

Au-delà de cela, vous devez vous assurer que vos FileReaders ne masquent aucune erreur lors de la lecture de ces données - créer des vérifications / assertions intégrées, lever des exceptions en cas de problème interne, etc. Cela donne à votre code de test une bien meilleure chance de détecter les erreurs , même lorsque vous ne disposez pas d'un fichier de test explicite ou d'un scénario de test pour une situation inattendue.

Doc Brown
la source
Réponse géniale, et je vais modifier le titre de ma question pour mieux réfléchir. Merci!
sdasdadas