Concepts : Liste des idées de test
Rubriques
Les informations utilisées dans la conception des tests sont rassemblées à partir de nombreux endroits : modèles de conception, interfaces de classificateur, diagrammes d'état-transition et le code lui-même. A un moment donné, ces informations de document source doivent être transformées en tests exécutables :
- entrées spécifiques données au logiciel testé
- dans une configuration matérielle ou logicielle particulière
- initialisées à un état connu
- avec des résultats spécifiques attendus
Il est possible de passer directement d'informations de document source à des tests exécutables mais il est souvent utile d'ajouter une étape intermédiaire. Dans cette étape, les idées de test sont écrites dans une Liste d'idées de test, qui sert à créer des tests exécutables.
Une idée de test (parfois appelée exigence de test) est une brève description d'un test qui pourrait être réalisé.
Comme exemple simple, considérons une fonction qui calcule une racine carrée et trouvons quelques idées de test :
- donner un nombre qui est à peine inférieur à zéro en tant qu'entrée
- donner un zéro en tant qu'entrée
- tester un nombre qui est une racine parfaite, comme 4 ou 16 (le résultat est-il exactement 2 ou 4?)
Chacune de ces idées peut être facilement convertie en test exécutable avec des descriptions exactes des entrées et résultats attendus.
Cette forme intermédiaire moins spécifique présente deux avantages :
- les idées de test sont davantage révisables et compréhensibles que des tests complets ; il est plus facile d'en comprendre le raisonnement
- les idées de test soutiennent des tests plus puissants, comme décrit plus bas sous la rubrique Conception de test à l'aide de la liste
Les exemples de racine carrée décrivent tous les entrées, mais les idées de test peuvent décrire n'importe lequel des éléments d'un test exécutable. Par exemple, "impression vers une LaserJet
IIIp" décrit un aspect de l'environnement de test à utiliser pour un test, que le fait le "test avec base de données complète", toutefois, ces idées de test ultérieures sont très incomplètes en soi :
Imprimer quoi sur l'imprimante ? Faire quoi avec cette base de données complète ? Toutefois, elles assurent que les idées importantes ne soient pas oubliées ; des idées qui seront décrites de façon plus détaillée plus en avant dans la conception du test.
Les idées de test sont souvent basées sur des modèles de faute ; notions de quelles fautes sont plausibles dans un logiciel et comment ces fautes peuvent être le mieux mises à jour. Par exemple, considérons les frontières. Il est prudent de penser que la fonction racine carrée peut être implémentée comme suit :
double sqrt(double x) {
if (x < 0)
// signal error
...
Il est également plausible que le < peut être mal saisi comme <=. Les gens font souvent ce genre d'erreur, cela vaut donc la peine de vérifier. La faute ne peut pas être détectée avec X avec la valeur 2, car l'expression erronée (x<=0) et l'expression correcte (x<0) prendront la même branche de l'instruction si. De même, la faute ne sera pas trouvée si on donne à X la valeur -5. La seule façon de la trouver est de donner à X la valeur 0, qui justifie la deuxième idée de test.
Dans ce cas, le modèle de faute est explicite. Dans d'autres cas, il est implicite. Par exemple, chaque fois qu'un programme manipule une structure liée, il est bon de la tester par rapport à une structure circulaire. Il est possible que de nombreuses fautes puissent mener à une mauvaise gestion de la structure circulaire. Pour les besoins du test, il n'y a pas besoin de les énumérer, il suffit de savoir qu'un certain nombre de fautes sont suffisamment probables pour que le test vaille la peine d'être exécuté.
Les liens suivants fournissent des informations sur comment trouver des idées de test à partir de différents types de modèles de faute. Les deux premiers sont des modèles de faute explicites ; le dernier utilise les implicites.
Ces modèles de faute peuvent s'appliquer à de nombreux artefacts différents. Par exemple, le premier décrit que faire des expressions booléennes. De telles expressions peuvent être trouvées dans le code, dans des conditions de garde, dans des diagrammes d'état-transition et diagrammes de séquence, et dans des descriptions en langue naturelle de comportements de méthode (comme vous pouvez trouver dans une API publiée).
Il est parfois également utile d'avoir des conseils pour des artefacts spécifiques. Voir
Principes et conseils : Idées de test pour diagrammes d'état-transition et organigrammes.
Une liste d'idée de test particulière peut contenir des idées de test de nombreux modèles de faute, et ces modèles de faute peuvent être dérivés de plusieurs artefacts.
Supposons que vous concevez des tests pour une méthode qui recherche une chaîne dans un ensemble séquentiel. Elle peut respecter ou ignorer la casse dans sa recherche, et elle renvoie l'index des premiers résultats trouvés ou -1 s'il n'y a aucun résultat.
int Collection.find(String string,
Boolean ignoreCase);
Voici quelques idées de test pour cette méthode :
- résultat trouvé en première position
- résultat trouvé en dernière position
- aucun résultat
- deux résultats ou plus trouvés dans l'ensemble
- la casse est ignorée ; résultat trouvé mais ne correspondrait pas si la casse était respectée
- la casse est respectée ; une correspondance parfaite a été trouvée
- la casse est respectée ; une chaîne qui aurait correspondu si la casse était ignorée est laissée de côté
Il serait simple d'implémenter ces sept tests, un pour chaque idée de test.
Toutefois, des idées de test différentes peuvent être combinée dans un seul test. Par exemple,
le test suivant satisfait les idées de test 2, 6, et 7 :
Création : ensemble initialisé à ["dawn", "Dawn"]
Invocation : ensemble.trouver("Dawn", faux)
Résultat attendu : la valeur renvoyée est 1 (serait 0 si "dawn"
n'avait pas été laissé de côté)
Faire des idées de test non spécifiques facilite leur combinaison.
Il est possible de satisfaire toutes les idées de test en trois tests. Pourquoi trois tests qui satisfont sept idées de test seraient meilleurs que sept tests séparés ?
- Lorsque vous créez un grand nombre de tests simples, il est courant de créer un test N+1 en copiant le test N et de le peaufiner juste ce qu'il faut pour satisfaire la nouvelle idée de test. Le résultat, notamment dans des logiciels plus complexes, est que le test N+1 mettra le programme à l'épreuve pratiquement de la même façon que le test N. Il prend presque exactement le même chemin d'accès à travers le code.
Un plus petit nombre de tests, chacun satisfaisant plusieurs idées de test, ne permet pas une approche "copier et peaufiner". Chaque test sera d'une certaine façon différent du dernier, mettant le code à l'épreuve de façons différentes et prenant différents chemins d'accès.
Pourquoi cela est-il mieux ? Si la liste d'idées de test était complète, avec une idée de test pour chaque faute du programme, peu importerait votre façon de rédiger le test. La liste oublie toujours des idées de test qui pourraient trouver des bogues.
En faisant faire à chaque test des choses différentes du dernier (en ajoutant une variété en apparence inutile), vous augmentez la possibilité qu'un des tests tombe sur un bogue par hasard. En effet, des tests plus petits et complexes augmentent la chance que le test satisfasse une idée de test dont vous ignoriez avoir besoin.
- Parfois lorsque vous créez des tests plus complexes, des nouvelles idées de test vous viennent à l'esprit. Cela se produit moins souvent avec des tests simples, parce qu'une grande partie de ce que vous faites est exactement comme le dernier test, ce qui vous rend moins perspicace.
Toutefois, il y a des raisons pour ne pas créer des tests complexes.
- Si chaque test satisfait une seule idée de test et le test pour la deuxième idée échoue, vous savez immédiatement quelle en est la cause la plus probable : le programme ne gère pas une correspondance dans la dernière position. Si un test satisfait les idées 2, 6, et 7, isoler l'anomalie est plus difficile.
- Des tests complexes sont plus difficiles à comprendre et entretenir. L'objet du test est moins évident.
- Les tests complexes sont plus difficiles à créer. Elaborer un test qui satisfait à cinq idées de test prend souvent plus de temps que d'élaborer cinq tests satisfaisant chacun une idée. De plus, il est plus facile de faire des erreurs, de pense que vous satisfaites les cinq alors que vous n'en satisfaites que quatre.
Dans la pratique, vous devez trouver un équilibre raisonnable entre la complexité et la simplicité.
Par exemple, les premiers tests auxquels vous soumettez le logiciel (généralement les tests de fumée) doivent être simples, faciles à comprendre et entretenir, et visant à déceler les problèmes les plus évidents. Les tests qui interviennent plus tard doivent être plus complexes sans pour autant devenir impossible à entretenir.
Quand vous avez fini un ensemble de tests, il est bon de les vérifier par rapport aux erreurs caractéristiques de la conception de test abordées dans Concepts : Tests développeur.
Une liste d'idées de test est utile pour réviser et inspecter les artefacts de conception.
Par exemple, considérons cette partie d'un modèle de conception montant l'association entre les classes Service et Employé.

Figure 1 : Association entre les classes Service et Employé
Les règles de création d'idées de test d'un tel modèle vous demanderaient de considérer le cas où un service compte beaucoup d'employés. En parcourant une conception et en se demandant "que se passerait-il, à ce point, si le service avait beaucoup d'employés ?", vous pourriez découvrir des erreurs de conception ou d'analyse. Par exemple, vous pourriez vous rendre compte que seule un employé peut être transféré à la fois d'un service à un autre. Cela peut poser un problème si l'entreprise a tendance à réaliser des réorganisations où de nombreux employés doivent être transférés.
De telles fautes, cas où une possibilité est omise, s'appellent des fautes
d'omission. Tout comme les fautes, vous avez probablement omis des tests qui détectent ces fautes dans votre effort de test. Par exemple, voir [GLA81],
[OST84], [BAS87],
[MAR00], et d'autres études qui montrent la fréquence à laquelle les fautes d'omission échappent dans le déploiement.
Le rôle des tests dans les activités de conception est abordé de façon plus approfondie dans Concepts : Conception pilotée par le test.
La Traçabilité est une question de compromis. Sa valeur vaut-elle le coût de son entretien ? Cette
question doit être envisagée pendant l' Activité :
Définir les besoins d'évaluation et de traçabilité.
Lorsque la traçabilité en vaut la peine, les tests sont conventionnellement tracés jusqu'aux artefacts qui les ont inspirés. Par exemple, vous pouvez avoir une traçabilité entre une API et ses tests. Si l'API change, vous savez quels tests changent. Si le code (qui implémente l'API) change, vous savez quels tests exécuter. Si un test vous étonne, vous pouvez trouver l'API qu'il doit tester.
La liste des idées de test ajoute un autre niveau de traçabilité. Vous pouvez remonter d'un test jusqu'aux idées de test qu'il satisfait, et puis des idées de test jusqu'à l'artefact d'origine.
|