Supposons que vous ayez une méthode: écririez-vous un test unitaire? strong> p> public void Save(Entity data)
{
if (this.repositoryIocInstance.Exists(data))
{
this.repositoryIocInstance.Update(data);
}
else
{
this.repositoryIocInstance.Create(data);
}
}
8 Réponses :
La règle générale du pouce est que vous testez toutes choses, cela pourrait probablement casser. Si vous êtes sûr, que la méthode est assez simple (et reste assez simple) pour ne pas être un problème, qui le laissent sortir avec des tests. P>
La deuxième chose est que vous devez tester le contrat de la méthode, pas la mise en œuvre. Si le test échoue après un changement, mais pas l'application, votre test ne teste pas la bonne chose. Le test devrait couvrir des cas importants pour votre application. Cela devrait s'assurer que chaque passage à la méthode qui ne casse pas l'application n'échoue pas également le test. P>
Dans ce cas, cette méthode n'a pas besoin d'un test de l'unité, puisque ne casse pas l'application, testez la pause. Je teste une immense dans ce cas, pas le contrat qui n'est pas présent dans la portée de la méthode.
Une méthode qui ne renvoie aucun résultat change toujours l'état de votre application. Le test de votre unité, dans ce cas, devrait vérifier si le nouvel état est comme prévu. P>
Un nouvel état au sein du test de l'unité dépend uniquement de la maquette ... C'est pourquoi j'ai une deuxième pensée. Si toute ma méthode est colorée dans le référentiel et que l'on est moquée dans un test, il aura un résultat prévisible basé sur une situation de vie nette et non réelle. Ça passera toujours.
Vous ne devriez pas tester le simulacre, mais plutôt l'opération qui interagit avec la simulation. Dis, vous avez un objet x code> avec une méthode m () code> qui appelle le référentiel. Vous souhaitez tester que l'appel au référentiel est réellement effectué, vous écrivez donc une maquette du référentiel, puis appelez votre méthode x.m () code>. Le test doit déclencher un changement dans la simulation, ce qui prouverait que votre méthode m () code> fonctionne selon les besoins. Lorsque vous avez une réelle implémentation du référentiel, vous testez cette implémentation (pas la simulation) - vous seriez alors en train de tester le référentiel.
@Jeyoung: Mais c'est un test d'unité distinct. C'est un test unitaire du référentiel et non la classe qui appelle le référentiel selon le code ci-dessus ... mais oui. La chose est que je ne teste pas dal depuis son code généré. Et devrait fonctionner comme il se doit. Et je n'ai pas l'intention de le tester.
Je vois ... Le test de l'unité est toujours valide, car il pourrait y avoir d'autres modifications susceptibles de casser votre application.
"Votre test de l'unité échouerait mais cela ne briserait probablement pas votre application" p>
Ceci est - en fait - vraiment important de savoir. Cela peut sembler gênant et trivial, mais lorsque quelqu'un d'autre commence à maintenir votre code, ils ont peut-être fait une très mauvaise modification pour économiser et (improbable) cassée l'application. P>
Le truc est de hiérarchiser. p>
Testez d'abord les choses importantes. Quand les choses sont lentes, ajoutez des tests pour des trucs triviaux. P>
Vous avez peut-être raison dans la dernière phrase (+1 pour cela). Le problème principal ici est que le test deviendra invalide, pas le code, qui évoluera dans une meilleure version.
N'oubliez pas que les tests d'unités ne concernent pas seulement le code de test. Il s'agit de vous permettre de déterminer lorsque le comportement change em>. P>
Vous pouvez donc avoir quelque chose qui est trivial. Cependant, vos changements de mise en œuvre et vous pouvez avoir un effet secondaire. Vous voulez que votre suite de test de régression vous dise. p>
E.g. Souvent, les gens disent que vous ne devriez pas tester des ensembles / getters puisqu'ils sont triviaux. Je ne suis pas d'accord, pas parce que sont des méthodes compliquées, mais quelqu'un peut les changer par inadvertance par l'ignorance, les scénarios de doigt gras, etc. P>
Compte tenu de tout ce que je viens de dire, je voudrais définitivement mettre en œuvre des tests pour ce qui précède (via une moqueur et / ou peut-être que cela vaut la peine de concevoir vos classes avec la vérification de la véracité et de les disposer du statut de rapport, etc.) P>
Je suis d'accord avec ce que vous avez dit sur les tests de régression. Et je dirais également que les tests d'intégration montreraient également des pièces non fonctionnelles. Mais puisque je ne crée pas de tests d'unité pour mon dal (il est généré), je suppose que je ne devrais pas créer de tests d'unités à moins que je ne change de méthode pour avoir un type de retour (comme Bool) pour signaler le statut.
Je dirais que «la régression» couvre à la fois une unité et une intégration - cela indique qu'ils courent continuellement (disons sur chaque construction). Pour tester le code généré automatiquement, je pense que c'est une décision qui pourrait aller de toute façon, en fonction de votre foi dans le processus de génération, à quel point il est complexe, etc.
C'est vrai que votre test dépend de votre mise en œuvre, ce qui est quelque chose que vous devez éviter (bien que ce ne soit pas vraiment aussi simple ...) et n'est pas nécessairement mauvais. mais ce type de test devraient se casser même si votre changement ne casse pas le code fort>. p>
Vous pourriez avoir de nombreuses approches à ce sujet: p>
Votre réponse est si loin la plus proche de ce que je voulais savoir. Mais votre deuxième balle serait dans ce cas le référentiel de test et non la méthode elle-même, n'est-ce pas?
Je ne le pense pas. Cela pourrait être un objet qui contient une liste
Votre mise en œuvre de votre objet serait plus coûteuse, comme mentionné, mais IMHO C'est la meilleure façon de voir si l'appel a été effectué de manière cohérente.
Eh bien, je suppose que cela serait couvert dans des tests d'intégration car il n'y aurait pas de cours moqués.
C'est exact. Les tests d'intégration obtiendraient un bogue dans cela. Mais il serait plus difficile de détecter où est le bug. Le test de l'appareil est de trouver un bug Cause rapide. En outre, ils fonctionnent généralement plus rapidement (et plus fréquemment). Un changement de rupture serait détecté et corrigé plus rapidement. Vous décidez simplement si cela vaut le prix;)
Lorsqu'il n'y a pas d'affirmation dans une méthode, vous affirmez essentiellement que les exceptions ne sont pas lancées.
Je suis aussi en difficulté avec la question de savoir comment tester le vide public MyMethod (). Je suppose que si vous décidez d'ajouter une valeur de retour pour la testabilité, la valeur de retour doit représenter tous les faits saillants nécessaires pour voir ce qui a changé à propos de l'état de l'application. P>
public bool myMethod() DoLotsOfSideEffects() return true;
Les modifications apportées à l'état d'un objet sont finalement réfléchies à l'extérieur, soit par le résultat différent d'un comportement de l'objet, soit par le résultat différent de son retour lorsque ses connaissances sont interrogées. C'est également à ces points que l'état de l'objet devient pertinent. Par conséquent, la manière de tester des méthodes qui modifient l'état interne consiste à tester ces changements de comportement ou de connaissances aux points où ils deviennent visibles.
@Jeyoung: Si je vous comprends correctement, ces types de tests vont au-delà des tests unitaires ... ils vont plus profond que l'unité testée, n'est-ce pas?
@Jeyoung. Vous dites que vous dites de tester "Public Void Saverow ()", vous devez invoquer "Datarow publique Loarrow ()"?
C'est exactement ce que je veux dire. Il peut sembler de sauter le pistolet en testant deux méthodes à la fois, mais vous testez vraiment que la responsabilité de la classe (enregistrer une ligne et le chargement) est mise en œuvre correctement.
La réponse courte à votre question est la suivante: oui em>, vous devez certainement tester des méthodes comme celle-là. P>
Je suppose que c'est important em> que la méthode de sauvegarde enregistre em> les données. Si vous n'écrivez pas un test de l'unité pour cela, alors comment savez-vous? P>
Quelqu'un d'autre peut venir et supprimer cette ligne de code qui invoque la méthode d'entité de l'entité et aucun des tests de l'unité échouera. Plus tard, vous vous demandez pourquoi les articles ne sont jamais persistés ... P>
Dans votre méthode, vous pourriez dire que toute personne supprime cette ligne ne ferait que si elles n'auraient que des intentions malignes, mais la chose est la suivante: les choses simples ne restent pas nécessairement simples, et vous feriez mieux d'écrire les tests de l'unité avant que les choses ne reçoivent pas compliqué. p>
Il est pas em> un détail de mise en œuvre que la méthode de sauvegarde invoque l'entité d'entité sur le référentiel - elle fait partie du comportement attendu et une partie assez cruciale, si je peux le dire. Vous voulez vous assurer que les données sont réellement enregistrées. P>
Juste parce qu'une méthode ne renvoie pas une valeur ne signifie pas que cela ne vaut pas la peine d'être testé. En général, si vous observez une bonne séparation de commande / requête (CQS), toute méthode de vide devrait être censée modifier l'état de quelque chose em>. P>
Parfois, quelque chose est la classe elle-même, mais d'autres fois, cela peut être l'état de quelque chose d'autre. Dans ce cas, cela change l'état du référentiel et c'est ce que vous devriez tester. P>
Ceci s'appelle Test Sorties Inderect em>, au lieu des sorties directes les plus normales em> (valeurs de retour). P>
L'astuce consiste à écrire des tests de l'unité afin qu'ils ne cassent pas trop souvent. Lorsque vous utilisez des moqueurs, il est facile d'écrire accidentellement tests surpiqué em>, c'est pourquoi la plupart des simulacres dynamiques (comme MOQ) par défaut sont les paramètres Stub em> mode, où il n'a pas vraiment d'importance plusieurs fois, vous invoquez une méthode donnée. P>
Tout cela, et bien plus encore, est expliqué dans l'excellent Modèles de test Xunit . P>
Je ne pense pas que vous ayez l'idée des tests unitaires et de la moqueur. Si une méthode d'annulation ne modifie que l'état interne d'un autre objet et que vous écrivez un test d'unité pour cela, vous écrirez une simule pour cet objet interne. Vous devrez écrire son comportement. Donc, votre méthode ne changera aucun état. Cela utilisera simplement votre comportement préprogrammé. Les appels à peine vérifiant peuvent être problématiques de la manière dont j'ai expliqué dans ma question. Ce qui signifie qu'un test n'est pas valide, pas le code des tests de test unitaire.
@ROBERT KORITNIK: Je pense que c'est la première première fois que quelqu'un a affirmé que je ne comprends pas les tests d'unité et les tests de test ... Je conviens que si une méthode seulement i> change interne i> interne i> State, il n'y a aucune raison d'écrire un test de l'unité pour cela, mais encore une fois, quelle raison pourrait-il y avoir un tel code? J'ai peut-être pu sauter à des conclusions de votre question, mais j'ai supposé que la variable membre en question représentait un référentiel et qu'un référentiel représente beaucoup externe i> État dans mon livre.
>> Si vous n'écrivez pas un test d'unité pour cela, comment savez-vous? << En regardant le code qui est trivial? Sinon, on ne peut même pas être sûr que le test est correct - il semble plus compliqué que le code sous test.
>> Il est important que la méthode de sauvegarde enregistre réellement les données << vraiment testées ici est que l'exécution prend un certain chemin, plus ni moins.
Demandez-vous deux questions. "Quel est l'équivalent manuel de ce test d'unité?" et "vaut-il la peine d'automatiser?". Dans votre cas, ce serait quelque chose comme: p>
Qu'est-ce que l'équivalent manuel? - Démarrer le débogueur - Étape dans la méthode "Enregistrer" - Entrez dans la prochaine étape, assurez-vous que vous êtes à l'intérieur IREPOSITORY.EntitySave Mise en œuvre P>
Cela vaut-il la peine d'automatiser? Ma réponse est non". Il est 100% évident du code. De centaines de tests de déchets similaires, je n'ai pas vu un seul qui serait utile. P>