Les résultats attendus d'un test unitaire doivent-ils être codés en dur, ou peuvent-ils dépendre de variables initialisées? Les résultats codés en dur ou calculés augmentent-ils le risque d'introduire des erreurs dans le test unitaire? Y a-t-il d'autres facteurs que je n'ai pas pris en compte?
Par exemple, lequel de ces deux est un format plus fiable?
[TestMethod]
public void GetPath_Hardcoded()
{
MyClass target = new MyClass("fields", "that later", "determine", "a folder");
string expected = "C:\\Output Folder\\fields\\that later\\determine\\a folder";
string actual = target.GetPath();
Assert.AreEqual(expected, actual,
"GetPath should return a full directory path based on its fields.");
}
[TestMethod]
public void GetPath_Softcoded()
{
MyClass target = new MyClass("fields", "that later", "determine", "a folder");
string expected = "C:\\Output Folder\\" + string.Join("\\", target.Field1, target.Field2, target.Field3, target.Field4);
string actual = target.GetPath();
Assert.AreEqual(expected, actual,
"GetPath should return a full directory path based on its fields.");
}
EDIT 1: En réponse à la réponse de DXM, l'option 3 est-elle une solution préférée?
[TestMethod]
public void GetPath_Option3()
{
string field1 = "fields";
string field2 = "that later";
string field3 = "determine";
string field4 = "a folder";
MyClass target = new MyClass(field1, field2, field3, field4);
string expected = "C:\\Output Folder\\" + string.Join("\\", field1, field2, field3, field4);
string actual = target.GetPath();
Assert.AreEqual(expected, actual,
"GetPath should return a full directory path based on its fields.");
}
c#
unit-testing
Hand-E-Food
la source
la source
Réponses:
Je pense que la valeur attendue calculée donne des cas de test plus robustes et flexibles. De plus, en utilisant de bons noms de variables dans l'expression qui calculent le résultat attendu, il est beaucoup plus clair d'où le résultat attendu provient en premier lieu.
Cela dit, dans votre exemple spécifique, je ne ferais PAS confiance à la méthode "Softcoded" car elle utilise votre SUT (système sous test) comme entrée pour vos calculs. S'il y a un bogue dans MyClass où les champs ne sont pas correctement stockés, votre test passera réellement car votre calcul de valeur attendue utilisera la mauvaise chaîne, tout comme target.GetPath ().
Ma suggestion serait de calculer la valeur attendue là où cela a du sens, mais assurez-vous que le calcul ne dépend d'aucun code du SUT lui-même.
En réponse à la mise à jour du PO à ma réponse:
Oui, en fonction de mes connaissances mais de mon expérience quelque peu limitée en TDD, je choisirais l'option # 3.
la source
Et si le code était le suivant:
Votre deuxième exemple n'attraperait pas le bogue, mais le premier exemple le ferait.
En général, je déconseille le codage logiciel car il peut masquer les bogues. Par exemple:
Pouvez-vous repérer le problème? Vous ne feriez pas la même erreur dans une version codée en dur. Il est plus difficile d'obtenir des calculs corrects que des valeurs codées en dur. C'est pourquoi je préfère travailler avec des valeurs codées en dur que celles codées en soft.
Mais il y a des exceptions. Et si votre code doit s'exécuter sur Windows et Linux? Non seulement le chemin devra être différent, il devra utiliser des séparateurs de chemin différents! Calculer le chemin à l'aide de fonctions qui font abstraction de la différence entre peut avoir un sens dans ce contexte.
la source
À mon avis, vos deux suggestions sont loin d'être idéales. La façon idéale de le faire est celle-ci:
En d'autres termes, le test doit fonctionner exclusivement en fonction de l'entrée et de la sortie de l'objet, et non en fonction de l'état interne de l'objet. L'objet doit être traité comme une boîte noire. (J'ignore d'autres problèmes, comme le caractère inapproprié de l'utilisation de string.Join au lieu de Path.Combine, car ce n'est qu'un exemple.)
la source
target.Dispose(); Assert.IsTrue(target.IsDisposed);
(un exemple très simple.)Il y a deux aspects dans la discussion:
1. Utilisation de la cible elle-même pour le cas de test
La première question est: devez-vous / pouvez-vous utiliser la classe elle-même pour compter et obtenir une partie du travail dans le talon de test? - La réponse est NON car, en général, vous ne devez jamais faire d'hypothèse sur le code que vous testez. Si cela n'est pas fait correctement, au fil du temps, les bogues deviennent immunisés contre certains tests unitaires.
2. Le codage en dur
doit-il être codé en dur ? Encore une fois, la réponse est non . parce que comme tout logiciel - le codage en dur des informations devient difficile lorsque les choses évoluent. Par exemple, lorsque vous souhaitez que le chemin ci-dessus soit à nouveau modifié, vous devez soit écrire une unité supplémentaire, soit continuer à modifier. Une meilleure méthode consiste à conserver la date d'entrée et d'évaluation dérivée de la configuration séparée qui peut être facilement adaptée.
par exemple, voici comment je corrigerais le talon de test.
la source
Il y a beaucoup de concepts possibles, fait quelques exemples pour voir la différence
Pour résumer: en général, votre premier test juste codé en dur a plus de sens pour moi car il est simple, direct, etc. Si vous commencez à coder en dur un chemin trop de fois, mettez-le simplement dans la méthode de configuration.
Pour plus de tests structurés futurs, j'irais vérifier les sources de données afin que vous puissiez simplement ajouter plus de lignes de données si vous avez besoin de plus de situations de test.
la source
Les frameworks de test modernes vous permettent de fournir des paramètres à votre méthode. Je les exploiterais:
À mon avis, cela présente plusieurs avantages:
la source