Vaut-il mieux avoir un
- Suite de tests déterministes, qui se traduit par la réussite des mêmes tests
- Suite de tests non déterministes, qui peut éventuellement couvrir plus de cas
?
Exemple: vous écrivez une suite de tests pour tester les fonctionnalités du contrôleur dans une application MVC. Le contrôleur requiert des données d'application d'une base de données en entrée pendant le test. Il existe deux options pour ce faire:
- Vous codez en dur la ou les lignes de la base de données de test qui sont sélectionnées en entrée (par exemple, la 10e et la 412e ligne)
- Vous utilisez un générateur de nombres aléatoires pour sélectionner de manière pseudo-aléatoire les données de la base de données (deux lignes sélectionnées par un générateur de nombres aléatoires)
La première est déterministe: chaque exécution du test pour la même révision de code devrait produire le même résultat. La seconde n'est pas déterministe: chaque exécution de la suite de tests a la possibilité de produire un résultat différent. Les données sélectionnées au hasard pourraient cependant être une meilleure représentation des cas de bord de données. Cela pourrait mieux simuler un utilisateur alimentant nos contrôleurs avec des données imprévisibles?
Quelles sont les raisons de choisir l'un plutôt que l'autre?
Réponses:
Lorsque chaque exécution de la suite de tests vous donne la possibilité de produire un résultat différent, le test est presque sans valeur - lorsque la suite vous montre un bogue, vous avez de grandes chances de ne pas pouvoir le reproduire, et lorsque vous essayez de corriger le bug, vous ne pouvez pas vérifier si votre correctif fonctionne.
Donc, lorsque vous pensez que vous devez utiliser une sorte de générateur de nombres aléatoires pour générer vos données de test, assurez-vous de toujours initialiser le générateur avec la même graine, ou de conserver vos données de test aléatoires dans un fichier avant de les alimenter dans votre test, de sorte que vous pouvez réexécuter le test avec exactement les mêmes données de l'exécution précédente. De cette façon, vous pouvez transformer tout test non déterministe en test déterministe.
EDIT: L'utilisation d'un générateur de nombres aléatoires pour sélectionner certaines données de test est à mon humble avis parfois un signe d'être trop paresseux pour choisir de bonnes données de test. Au lieu de lancer 100 000 valeurs de test choisies au hasard et espérons que ce sera suffisant pour découvrir tous les bugs graves par hasard, mieux utiliser votre cerveau, choisir 10 à 20 cas "intéressants" et les utiliser pour la suite de tests. Cela se traduira non seulement par une meilleure qualité de vos tests, mais également par des performances beaucoup plus élevées de la suite.
la source
Les deux déterministes et non déterministes ont une place
Je les diviserais comme suit:
Tests unitaires.
Ceux-ci devraient avoir des tests déterministes et reproductibles avec les mêmes données exactes à chaque fois. Les tests unitaires accompagnent des sections de code spécifiques et isolées et doivent les tester de manière déterministe.
Tests de stress fonctionnel et d'entrée.
Ceux-ci peuvent utiliser l'approche non déterministe avec les mises en garde suivantes:
la source
Tous les deux.
Les tests déterministes et non déterministes ont différents cas d'utilisation et différentes valeurs pour votre suite. En règle générale , les tests non déterministes ne peuvent pas fournir la même précision que les tests déterministes, qui sont progressivement devenus des «tests non déterministes qui n'ont aucune valeur». C'est faux. Ils peuvent être moins précis, mais ils peuvent également être beaucoup plus larges, ce qui a ses propres avantages.
Prenons un exemple: vous écrivez une fonction qui trie une liste d'entiers. Quels seraient certains des tests unitaires déterministes que vous jugeriez utiles?
NaN
,INT_MIN
etINT_MAX
Et ce n'est qu'une fonction de tri! Bien sûr, vous pourriez faire valoir que certains d'entre eux ne sont pas nécessaires, ou que certains d'entre eux peuvent être exclus par un raisonnement informel. Mais nous sommes des ingénieurs et nous avons vu un raisonnement informel exploser dans notre visage. Nous savons que nous ne sommes pas assez intelligents pour comprendre complètement les systèmes que nous avons construits ou pour garder complètement la complexité dans nos têtes. C'est pourquoi nous écrivons des tests en premier lieu. L'ajout de tests non déterministes signifie simplement que nous ne sommes pas nécessairement assez intelligents pour connaître tous les bons tests a priori. En lançant des données semi-aléatoires dans votre fonction, vous êtes beaucoup plus susceptible de trouver un cas de bord que vous avez manqué.
Bien sûr, cela n'exclut pas non plus les tests déterministes. Les tests non déterministes aident à trouver des bogues dans de vastes pans du programme. Une fois que vous avez trouvé les bogues, cependant, vous avez besoin d'un moyen reproductible pour montrer que vous les avez corrigés. Donc:
Notez que cela signifie que de nombreux conseils solides sur les tests unitaires ne s'appliquent pas nécessairement aux tests non déterministes. Par exemple, qu'ils doivent être rapides. Les tests de propriétés de bas niveau doivent être rapides, mais un test non déterministe comme "simuler un utilisateur en cliquant au hasard sur les boutons de votre site Web et vous assurer de ne jamais obtenir d'erreur 500" devrait favoriser l'exhaustivité par rapport à la vitesse. Faites simplement exécuter un test comme celui-ci indépendamment de votre processus de génération afin qu'il ne ralentisse pas le développement. Par exemple, exécutez-le sur sa propre boîte de transfert privée.
la source
Vous ne voulez pas vraiment déterministe vs non déterministe.
Ce que vous voudrez peut-être, c'est «toujours le même» vs «pas toujours le même».
Par exemple, vous pouvez avoir un numéro de build qui augmente avec chaque build, et lorsque vous voulez des nombres aléatoires, vous initialisez un générateur de nombres aléatoires avec le numéro de build comme graine. Donc, à chaque build, vous faites vos tests avec des valeurs différentes, vous donnant plus de chances de trouver des bugs.
Mais une fois qu'un bogue a été trouvé, il vous suffit d'exécuter le test avec le même numéro de build et il est reproductible.
la source