Comment savez-vous ce qu'il faut tester lors de l'écriture des tests unitaires?
À l'aide de C#, j'ai besoin d'une classe appelée User
qui a un nom d'utilisateur, mot de passe, un indicateur actif, prénom, nom de famille, prénom, nom, etc.
Il devrait y avoir des méthodes pour authentifier et enregistrer un utilisateur. Dois-je viens d'écrire un test pour les méthodes? Et dois-je encore besoin de vous soucier de tester les propriétés depuis qu'ils sont .Net des accesseurs et des mutateurs?
- Ce post aidera avec le rétrécissement de l'ensemble de la question: earnestengineer.blogspot.com/2018/03/... Vous pouvez prendre ces lignes directrices à concentrer votre question
- Gardez à l'esprit les mots de passe ne doit pas être stocké en clair.
Vous devez vous connecter pour publier un commentaire.
Beaucoup de grandes réponses à ce sont également sur ma question: "Début TDD - Défis? Des Solutions? Recommandations?"
Permettez-moi aussi de vous recommander de jeter un oeil à mon post de blog (qui a été en partie inspiré par ma question), j'ai eu quelques bons retours sur ce point. À savoir:
J'espère que cela signifie que nous pouvons nous passer de "getters et les setters" 🙂
Tester votre code, pas la langue.
Un test unitaire comme:
est utile seulement si vous êtes l'écriture d'un compilateur et il y a zéro chance que votre
instanceof
méthode ne fonctionne pas.Ne pas tester des trucs que vous pouvez compter sur la langue pour la faire respecter. Dans votre cas, je souhaitez vous concentrer sur votre authentifier et enregistrer des méthodes - et j'aimerais écrire des tests qui faisait en sorte qu'ils pourraient traiter les valeurs nulles dans tout ou partie de ces champs gracieusement.
Cela m'a fait les tests unitaires et il m'a fait très plaisir
Nous avons juste commencé à faire des tests unitaires.
Pendant longtemps, je savais qu'il serait bon de commencer à le faire, mais je n'avais aucune idée de comment commencer, et surtout, quoi de test.
Ensuite, nous avons dû réécrire un important morceau de code dans notre programme de comptabilité.
Cette partie a été très complexe, car il a impliqué un grand nombre de scénarios différents.
La partie dont je parle est une méthode pour payer des ventes et/ou factures d'achat déjà entré dans le système de comptabilité.
Je ne savais pas comment commencer à coder, car il y avait tellement de différentes options de paiement.
Une facture qui pourrait être de 100$, mais les clients ne sont transférées à 99$.
Peut-être que vous avez envoyé la facture de vente à un client, mais vous avez aussi acheté de ce client.
Donc vous l'a vendu pour $300, mais que vous avez acheté pour $100. Vous pouvez vous attendre à votre client de vous payer $200 pour régler le solde.
Et si vous avez vendu pour 500$, mais le client vous paie seulement $250?
Donc j'ai eu un problème très complexe à résoudre avec de nombreuses possibilités que l'un scénario fonctionne parfaitement mais il serait erroné sur un autre type de invocie/paiement combinaison.
C'est là que les tests unitaires sont venus à la rescousse.
J'ai commencé à écrire (à l'intérieur du code de test) une méthode pour créer une liste de factures, à la fois pour les ventes et les achats.
Ensuite, j'ai écrit une deuxième méthode pour créer du paiement effectif.
Normalement, un utilisateur d'entrer les informations via une interface utilisateur.
Puis j'ai créé la première TestMethod, le test d'une très simple paiement d'une seule facture, sans paiement des réductions.
Toute l'action dans le système qui allait se passer quand un bankpayment serait enregistré dans la base de données.
Comme vous pouvez le voir, j'ai créé une facture, créé un paiement (une opération de banque) et l'enregistrement de la transaction sur le disque.
Dans mon affirme j'ai mis ce que devrait être le nombre correct de se retrouver dans la Banque de transaction et dans la Facture.
J'ai vérifier le nombre de paiements, les montants de paiement, le montant de l'escompte et le solde de la facture, après la transaction.
Après le test a je voudrais aller à la base de données et vérifier si ce que j'attendais était là.
Après j'ai écrit le test, j'ai commencé à coder la méthode de paiement (faisant partie de la BankHeader classe).
Dans le codage je ne dérangeait avec un code pour faire le test de la première passe. Je n'ai pas encore penser aux autres, plus complexes, des scénarios.
J'ai couru le premier test, correction d'un petit bug jusqu'à ce que mon test de passage.
Puis j'ai commencé à écrire le deuxième essai, cette fois-ci avec un escompte de paiement.
Après, j'ai écrit le test, j'ai modifié la méthode de paiement à l'appui des réductions.
Alors que les tests de justesse avec un escompte de paiement, j'ai aussi testé le simple paiement.
Les deux tests doivent passer bien sûr.
Ensuite, j'ai travaillé mon chemin vers la des scénarios plus complexes.
1) Penser à un nouveau scénario
2) Écrire un test pour que le scénario
3) Exécuter ce test simple pour voir si elle allait passer
4) Si ce n'était pas que j'avais de débogage et de modifier le code jusqu'à ce qu'il puisse passer.
5) lors de la modification de code, je l'ai gardé sur l'exécution de tous les tests
C'est comment j'ai réussi à créer mon très complexe de la méthode de paiement.
Sans tests unitaires, je ne sais pas comment commencer à coder, le problème semblait insurmontable.
Avec les tests que je pourrais commencer avec une méthode simple et de l'étendre, étape par étape, avec l'assurance que le plus simple des scénarios encore du travail.
Je suis sûr que l'utilisation de tests unitaires m'a sauvé quelques jours (ou semaines) de codage et est plus ou moins garantir l'exactitude de ma méthode.
Si plus tard, je pense à un nouveau scénario, je peux juste ajouter à la teste pour voir si cela fonctionne ou pas.
Si non, je peux modifier le code, mais être sûr que les autres scénarios sont encore à travailler correctement.
Cela permettra d'économiser des jours et des jours dans l'entretien et la phase de correction.
Oui, même testé le code peut encore avoir des bugs si un utilisateur fait des choses que vous ne pensiez pas ou empêché de faire
Ci-dessous sont quelques-uns des tests que j'ai créé pour tester ma méthode de paiement.
Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].InvoiceHeader.Balance);
Si ils sont vraiment trivial, alors n'ayez pas pris la peine de tester. Par exemple, si elles sont mises en œuvre comme cela;
Si, d'autre part, vous faites quelque chose d'intelligent, (comme le cryptage et le décryptage du mot de passe dans les getter/setter), puis lui donner un essai.
La règle est que vous devez tester chaque pièce de la logique de l'écriture. Si vous avez mis en œuvre certaines des fonctionnalités spécifiques dans les getters et setters je pense qu'ils valent. Si seulement ils attribuent des valeurs de certains champs privés, ne vous embêtez pas.
Cette question semble être une question de savoir où tracer la ligne sur quelles méthodes testées et qui ne le sont pas.
Les setters et getters pour l'affectation de la valeur ont été créés avec la cohérence et la croissance future, et de prévoir que certains de temps en bas de la route le setter/getter peut évoluer vers des opérations plus complexes. Il serait judicieux de mettre les tests unitaires de ces méthodes en place, également par souci de cohérence et de croissance future.
Code de la fiabilité, en particulier, tout en subissant le changement d'ajouter des fonctionnalités supplémentaires, est l'objectif principal. Je ne suis pas au courant de toute personne jamais avoir été licencié, y compris pour les setters/getters dans la méthodologie de test, mais je suis certain qu'il y existe des gens qui voulaient qu'ils avaient testé des méthodes dont la dernière ils étaient au courant ou peut-rappel simple set/get wrappers, mais qui n'était plus le cas.
Peut-être un autre membre de l'équipe a élargi, les méthodes set/get pour inclure une logique qui doit maintenant testé mais n'a pas alors de créer les tests. Mais maintenant, votre code est l'appel de ces méthodes, et vous n'êtes pas au courant, ils ont changé et ont besoin de test de profondeur, et les tests que vous faites dans le développement et l'assurance qualité ne déclenchent pas le défaut, mais réel les données d'entreprise sur le premier jour de la libération ne se déclenchent.
Les deux coéquipiers maintenant le débat sur qui a laissé tomber la balle et n'a pas à mettre dans les tests unitaires lorsque l'obtient transformé pour inclure une logique qui peut échouer, mais qui n'est pas couvert par un test unitaire. Le coéquipier qui a écrit à l'origine de l'obtient aurez un temps plus facile de sortir de ce propre si les tests ont été mis en œuvre dès le premier jour, sur le simple jeu/obtient.
Mon avis est que quelques minutes de "perdu" du temps couvrant TOUTES les méthodes avec les tests unitaires, même insignifiants, peut enregistrer des jours de maux de tête en bas de la route et la perte d'argent et de la réputation de l'entreprise et de la perte d'un emploi.
Et le fait que vous n'avez envelopper méthodes triviales avec les tests unitaires peuvent être vus par l'équipe junior partenaire quand ils changent les méthodes triviales dans le non-trivial et l'invite à mettre à jour le test, et maintenant personne n'est en difficulté parce que le défaut a été contenu à partir d'atteindre une production.
La façon dont nous le code, et la discipline, qui peut être vu à partir de notre code, peut aider les autres.
Une autre réponse canonique. C'est, je crois, de Ron Jeffries:
Tests de code réutilisable est une perte de temps, mais comme Slavo dit, si vous ajoutez un effet secondaire à votre getters/setters, alors vous devriez écrire un test pour accompagner cette fonctionnalité.
Si vous êtes en train de faire de test-driven development, vous devez écrire le contrat (par exemple, l'interface) d'abord, puis d'écrire le test(s) pour l'exercice de cette interface qui documentent les résultats attendus et/ou du comportement. Puis écrire vos méthodes elles-mêmes, sans toucher le code dans vos tests unitaires. Enfin, prenez un outil de couverture du code et assurez-vous que vos tests à l'exercice de la logique des chemins dans votre code.
Vraiment trivial code comme les getters et les setters qui n'ont pas d'extra comportement que la configuration d'un domaine privé sont beaucoup trop lourds pour tester. Dans la version 3.0 C# a même quelques sucre syntaxique où le compilateur prend en charge le domaine privé de sorte que vous n'avez pas de programme.
J'ai l'habitude d'écrire beaucoup de très simples tests de vérification de comportement j'attends de mes cours. Même si c'est des choses simples comme l'ajout de deux nombres. J'ai passer beaucoup de choses entre l'écriture d'un test simple et l'écriture de quelques lignes de code. La raison pour cela est que je peux changer autour de code sans avoir peur, je me suis cassé des choses, je ne pensais pas.
Vous devez tout tester. Maintenant vous avez des getters et setters, mais un jour, vous pourriez changer un peu, peut-être pour faire de la validation ou de quelque chose d'autre. Les tests de vous écrire aujourd'hui seront utilisés demain pour s'assurer que tout continue à travailler comme d'habitude.
Lorsque vous écrivez un essai, vous devriez oublier les considérations comme "droit maintenant il est trivial". Dans un agile ou test driven contexte, vous devez tester en supposant refactoring.
Aussi, avez-vous essayer de mettre en vraiment bizarre valeurs comme de très longues chaînes ou d'autres "mauvais" contenu? Eh bien, vous devriez... ne présumez jamais à quel point votre code peuvent être victimes de violence dans l'avenir.
En général, je trouve que l'écriture de vastes tests utilisateur est sur un côté, épuisant. De l'autre côté, si elle vous donne toujours de précieux conseils sur la façon dont votre application devrait fonctionner et vous aide à jeter facile (et faux) hypothèses (par exemple: le nom d'utilisateur sera toujours moins de 1000 caractères maximum).
Pour de simples modules qui peuvent se retrouver dans une boîte à outils, ou dans un open source type de projet, vous devez le tester, autant que possible, y compris le trivial getters et setters. La chose que vous voulez garder à l'esprit est que la génération d'un test de l'unité que vous écrivez un module particulier est assez simple et direct. L'ajout de getters et setters est un code minimal et peut être manipulé sans beaucoup de réflexion. Cependant, une fois que votre code est placé dans un système plus vaste, cet effort supplémentaire peut vous protéger contre les changements dans le système sous-jacent, tels que les changements de type dans une classe de base. Les tests de everthing est le meilleur moyen d'avoir une régression qui est complet.
Il ne fait pas de mal d'écrire des tests unitaires pour votre getters et setters. Maintenant, ils vont peut-être faire domaine/jeux sous le capot, mais dans le futur, vous pourriez avoir de la logique de validation, ou inter-propriété dépendances qui doivent être testés. Il est plus facile de l'écrire maintenant, pendant que vous êtes en train de penser à ce sujet alors se souvenir de rénovation si ce temps ne vient jamais.
en général, lorsqu'une méthode est définie uniquement pour certaines valeurs de test pour les valeurs sur et plus la frontière de ce qui est acceptable. En d'autres termes, assurez-vous que votre méthode n'est ce qu'il est censé faire, mais rien de plus. Ceci est important, parce que quand vous allez échouer, vous voulez à l'échec tôt.
Dans des hiérarchies d'héritage, assurez-vous de tester pour LSP de la conformité.
De test par défaut getters et setters ne semble pas très utile pour moi, sauf si vous avez l'intention de faire la validation de certains plus tard.
Comme je comprends les tests unitaires dans le contexte de développement agile, Mike, oui, vous avez besoin de tester les getters et les setters (en supposant qu'ils sont visibles). L'ensemble du concept de l'unité de test est de tester le logiciel de l'unité, qui est une classe dans ce cas, comme un la boîte noire. Depuis les getters et les setters sont visibles de l'extérieur vous avez besoin de les tester avec de l'authentification et de l'Enregistrer.
Si l'Authentifier et Enregistrer des méthodes utiliser les propriétés, puis vos tests indirectement toucher les propriétés. Tant que les propriétés sont juste fournir l'accès aux données, puis explicite de test ne devrait pas être nécessaire (sauf si vous allez pour une couverture de 100%).
Je voudrais tester votre getters et setters. En fonction de celui qui écrit le code, certaines personnes changent le sens du getter/setter. J'ai vu l'initialisation d'une variable et d'autres de validation dans le cadre de méthodes de lecture. Afin de tester ce genre de chose, vous voulez des tests unitaires portant code explicitement.
Personnellement, je "test de tout ce qui peut casser" et simple de lecture (ou encore mieux de l'auto de propriétés) ne se cassera pas. Je n'ai jamais eu un retour simple déclaration de l'échec et donc de ne jamais avoir de test pour eux. Si les méthodes de calcul ont en leur sein ou à une autre forme de déclarations, je serais certainement ajouter des tests pour eux.
Personnellement, j'utilise Moq comme un objet fantaisie cadre et vérifiez que mon objet appels objets qui l'entourent comme il le devrait.
Vous avez à couvrir l'exécution de chaque méthode de la classe avec l'UT et vérifier la valeur de retour de méthode. Cela inclut les getters et les setters, surtout dans le cas où les membres(propriétés) sont des classes complexes, ce qui nécessite de gros d'allocation de mémoire lors de leur initialisation. L'appel au setter avec quelques très grande chaîne par exemple (ou quelque chose avec des symboles grecs) et de vérifier le résultat est correct (pas tronqué, l'encodage est bon e.t.c.)
En cause pour de simples entiers qui s'applique également - ce qui arrive si vous passez de long au lieu d'un entier? C'est la raison pour laquelle vous écrivez UT pour 🙂
Je n'aurais pas fait de test, le réglage actuel de propriétés. Je serais plus préoccupé par la façon dont ces propriétés sont remplies par le consommateur, et ce qu'ils les remplir avec des. Avec tous les tests, vous devez peser les risques avec le temps et le coût de l'essai.
Vous devez tester "tous les non-trivial bloc de code" à l'aide de tests unitaires autant que possible.
Si vos biens sont triviales et son peu probable que quelqu'un va introduire un bug, alors il doit être sûr de ne pas l'unité de tester.
Votre Authenticate() et Save (), méthodes de ressembler à de bons candidats pour les tests.
Idéalement, vous avez fait vos tests unitaires que vous écriviez la classe. C'est la façon dont vous êtes censé le faire lors de l'utilisation de Développement Piloté par les tests. Vous ajoutez les tests en œuvre de chaque point de fonction, assurez-vous de couvrir le bord-cas avec le test de trop.
Écrire les tests par la suite est beaucoup plus douloureux, mais c'est faisable.
Voici ce que je ferais dans votre position:
Cela devrait vous donner une belle travailler ensemble de tests unitaires qui va agir comme un tampon contre les régressions.
Le seul problème avec cette approche est que le code doit être conçu pour être testées dans ce mode. Si vous avez fait un couplage des erreurs au début, vous ne serez pas en mesure d'obtenir une couverture élevée très facilement.
C'est pourquoi il est vraiment important d'écrire les tests avant d'écrire le code. Il vous oblige à écrire du code qui est faiblement couplé.
Ne testez pas évidemment de travail (standard) code. Donc, si votre setters et getters sont juste "propertyvalue = valeur" et "retour propertyvalue" il ne fait aucun sens pour le tester.
Même get /set peut avoir impair conséquences, selon la façon dont elles ont été mises en œuvre, de sorte qu'ils doivent être traités comme des méthodes.
Chacun de ces aura besoin de spécifier des ensembles de paramètres pour les propriétés, de définir à la fois acceptables et inacceptables propriétés pour assurer les appels de retour /d'échec dans la manière attendue.
Vous devez également être conscients des problèmes de sécurité, comme un exemple de l'injection SQL, et l'essai de ces.
Donc, oui, vous ne devez pas vous inquiéter au sujet de tester les propriétés.
Je crois que c'est idiot de tester les méthodes de lecture & setters quand elles ne font qu'une simple opération. Personnellement, je ne suis pas d'écrire des tests unitaires complexes pour couvrir tout type d'utilisation. J'essaie d'écrire assez de tests pour s'assurer que j'ai manipulé l'exécution normale du comportement et autant de cas d'erreur je pense. Je vais écrire plus de tests unitaires comme une réponse aux rapports de bogues. J'utilise de l'unité de test pour s'assurer que le code est conforme aux exigences et à l'avenir de modification plus facile. Je me sens beaucoup plus disposé à modifier le code quand je sais que si je casse quelque chose d'un test échouera.
Je voudrais écrire un test pour tout ce que vous écrivez du code pour est testable en dehors de l'interface graphique.
Généralement, à toute logique que j'écris qui a toute la logique métier je place à l'intérieur d'un autre niveau ou de la couche logique métier.
Puis écrire des tests pour tout ce qui n'quelque chose est facile à faire.
Premier passage, écrire un test unitaire pour chaque méthode publique dans votre "Business Logic Layer".
Si j'avais une classe comme ceci:
La première chose que je faisais avant, j'ai écrit le code en sachant que j'ai eu ces actions à réaliser serait de commencer à écrire des tests unitaires.
Écrire vos tests pour valider le code que vous avez écrit pour faire quelque chose. Si vous itération sur une collection de choses, et de changer quelque chose à propos de chacun d'eux, écrire un test qui fait la même chose et Affirmer qu'il s'est réellement passé.
Il ya beaucoup d'autres approches que vous pouvez prendre, à savoir le Comportement Driven Development (BDD), c'est plus impliqué et pas un excellent endroit pour commencer avec votre appareil de tests de compétences.
Donc, la morale de l'histoire est, de tester tout ce qui n'a rien que vous pourriez être inquiet, garder les tests unitaires, les tests de choses spécifiques qui sont de petite taille, beaucoup de tests sont bons.
Garder votre logique métier à l'extérieur de la couche d'Interface Utilisateur, de sorte que vous pouvez facilement écrire des tests pour eux, et vous serez bon.
Je recommande TestDriven.Net ou ReSharper comme à la fois facile à intégrer dans Visual Studio.
eh bien, si vous pensez qu'il peut se casser, écrire un test pour elle. J'ai l'habitude de ne pas tester setter/getter, mais permet de dit vous faites l'un pour l'Utilisateur.Nom, qui concaténer nom et prénom, je voudrais écrire un test, donc si quelqu'un changement de l'ordre pour le prénom et le nom, au moins, il sait qu'il a changé, quelque chose qui a été testé.
La réponse canonique est "test de tout ce qui peut casser." Si vous êtes sûr que les propriétés ne va pas casser, ne pas les tester.
Et une fois que quelque chose est trouvé coupable d'avoir brisé (vous trouvez un bug), évidemment cela signifie que vous devez le tester. Écrire un test pour reproduire le bug, il le montre l'échec, puis corriger le bug, puis de regarder le test pass.
Je recommanderais l'écriture de plusieurs tests pour votre Authentifier et Enregistrer des méthodes. Outre les cas de réussite (où tous les paramètres sont fournis, tout est correctement orthographié, etc), il est bon d'avoir des tests pour les différents cas (erronée ou manquante, paramètres, indisponible connexions de base de données le cas échéant, etc). Je recommande Pragmatique de Tests Unitaires en C# avec NUnit comme une référence.
Comme d'autres l'ont dit, les tests unitaires pour les getters et les setters sont exagéré, à moins qu'il y a une logique conditionnelle dans votre getters et setters.
S'il est possible de deviner l'endroit où votre code de besoins de tests, en général, je pense que vous avez besoin de paramètres pour sauvegarder cette supposition. Les tests unitaires, à mon avis, va de pair avec le code-les mesures de couverture.
Code avec beaucoup de tests, mais une petite couverture n'a pas été testés. Cela dit, le code avec une couverture de 100%, mais ne pas tester les boundry et en cas d'erreur est également pas très grande.
Vous voulez un équilibre entre d'une couverture élevée (90% minimum) et d'une variable d'entrée de données.
N'oubliez pas de test pour le "garbage in"!
Aussi, un test unitaire n'est pas un test unitaire à moins qu'il vérifie un échec. Unité-tests qui n'ont pas d'affirmations ou sont marqués avec des exceptions connues aurez simplement à vérifier que le code n'est pas mort lors de la course!
Vous avez besoin pour concevoir vos tests de sorte qu'ils ont toujours le rapport des échecs inattendus ou indésirables de données!
, Il est de notre code mieux... période de!
Une chose que nous, développeurs de logiciels oublier quand on fait le test driven development est le but derrière nos actions. Si une unité de test est écrit d'après le code de production est déjà en place, la valeur du test va vers le bas (mais n'est pas complètement perdu).
Dans le véritable esprit de l'unité de test, ces tests sont pas principalement pour "tester" les plus de notre code du travail; ou pour obtenir de 90% à 100% d'amélioration de la couverture du code. Ce sont tous des avantages sociaux de l'écriture, les premiers tests. Le grand profit, c'est que notre code de production extrémités être écrit beaucoup mieux en raison du processus naturel de TDD.
Pour aider à mieux communiquer cette idée, les éléments suivants peuvent être utiles dans la lecture:
Les défauts de la Théorie des Tests Unitaires
Volontariste De Développement De Logiciels
Si nous avons le sentiment que l'acte d'écrire plus de tests unitaires est ce qui nous aide à gagner un produit de meilleure qualité, alors nous avons peut-être atteint d'une Culte Du Cargo de Développement Piloté par les tests.
Tests d'une classe doit vérifier que:
Bien sûr, si les getters et setters ont aucune logique, les tests de la Authentifier andSave méthodes devraient couvrir, mais sinon, un explicit essai doit être écrit
J'deuxième tester tout ce qui peut briser et n'écris pas idiot tests. Mais le plus important principe est tester tout ce que vous trouverez est cassé: si une méthode se comporte bizarrement écrire un test pour décrire le jeu de données qui rend l'échec, puis corriger le bug et de regarder la barre de passer au vert. Aussi test de la "frontière" des valeurs de données (null, 0, MAX_INT, vide listes, peu importe).
Lors de l'écriture de tests unitaires, ou vraiment tout tester, vous déterminez ce que pour tester en regardant les conditions aux limites de ce que vous faites des tests. Par exemple, vous avez une fonction appelée is_prime. Heureusement, il fait ce que son nom l'indique et vous indique si l'objet entier est premier ou non. Pour cela, je suis en supposant que vous êtes à l'aide d'objets. Maintenant, nous devons vérifier que des résultats valides eu lieu pendant une aire de répartition connue de premier et non le premier des objets. C'est votre point de départ.
Fondamentalement, regardez ce qui doit arriver avec une fonction, une méthode, un programme ou un script, puis à ce qui ne doit certainement pas se produire avec le même code. C'est la base de votre test. Juste être prêt à modifier vos tests que vous devenez plus compétent sur ce devrait qui se passe avec votre code.
D'écrire du code qui n'a pas de valeur est toujours une mauvaise idée. Depuis le test proposé n'ajoute aucune valeur à votre projet (ou très près). Alors vous êtes la perte de temps précieux que vous pourriez passer à l'écriture de code qui apporte réellement de la valeur.
La meilleure règle que j'ai vu, c'est de tester tout ce que vous ne pouvez pas dire à un coup d'œil, pour certains, de fonctionner correctement. Rien de plus et vous vous retrouvez les tests de la langue et de l'environnement.
Je ne peux pas parler pour C# en particulier, mais quand je écrire des tests unitaires j'ai tester TOUTES les entrées, même celles que l'utilisateur ne le faites pas, je sais comment faire pour éviter que mes propres erreurs.