Comment savoir quoi tester lors de la rédaction des tests unitaires?

En utilisant C #, j’ai besoin d’une classe appelée User qui a un nom d’utilisateur, un mot de passe, un drapeau actif, un prénom, un nom de famille, un nom complet, etc.

Il devrait y avoir des méthodes pour authentifier et enregistrer un utilisateur. Est-ce que je viens d’écrire un test pour les méthodes? Et dois-je même me soucier de tester les propriétés car ce sont les getter et les régleurs de .Net?

Beaucoup de bonnes réponses à cela sont également sur ma question: ” Débuter le TDD – Défis? Solutions? Recommandations? ”

Puis-je également consulter mon article sur le blog (inspiré en partie par ma question), j’ai eu de bons retours à ce sujet. À savoir:

Je ne sais pas où commencer?

  • Recommence. Ne pensez qu’à écrire des tests lorsque vous écrivez un nouveau code. Cela peut être de retravailler l’ancien code ou une fonctionnalité complètement nouvelle.
  • Commencez simple Ne partez pas en courant et essayez de vous familiariser avec un cadre de test et d’être un TDD-esque. Debug.Assert fonctionne bien. Utilisez-le comme sharepoint départ. Il ne perturbe pas votre projet et ne crée pas de dépendances.
  • Commencez positif. Vous essayez d’améliorer votre métier, vous vous sentez bien. J’ai vu beaucoup de développeurs qui sont heureux de stagner et de ne pas essayer de nouvelles choses pour s’améliorer. Vous faites ce qu’il faut, rappelez-vous ceci et cela vous aidera à ne pas baisser les arm.
  • Commencez à vous préparer à un défi. Il est assez difficile de commencer à tester. Attendez-vous à un défi, mais rappelez-vous que les défis peuvent être surmontés.

Test seulement pour ce à quoi vous vous attendez

J’ai eu de véritables problèmes lorsque j’ai commencé parce que j’étais constamment assis à essayer de trouver tous les problèmes possibles, puis à essayer de le tester et à le réparer. Ceci est un moyen rapide à un mal de tête. Les tests devraient être un véritable processus de YAGNI. Si vous savez qu’il y a un problème, écrivez un test pour cela. Sinon, ne vous en faites pas.

Seulement tester une chose

Chaque test ne doit tester qu’une seule chose. Si vous vous trouvez jamais en train de mettre «et» dans le nom du test élémentaire, vous faites quelque chose de mal.

J’espère que cela signifie que nous pouvons passer de “getters et setters” 🙂

Testez votre code, pas la langue.

Un test unitaire comme:

 Integer i = new Integer(7); assert (i.instanceOf(integer)); 

n’est utile que si vous écrivez un compilateur et qu’il y a une chance non nulle que votre méthode instanceof ne fonctionne pas.

Ne testez pas des choses sur lesquelles vous pouvez compter sur le langage à appliquer. Dans votre cas, je me concentrerais sur vos méthodes d’authentification et d’enregistrement – et j’écrirais des tests qui garantiraient qu’ils pourraient gérer les valeurs NULL dans n’importe lequel ou tous ces champs.

Cela m’a conduit à des tests unitaires et cela m’a rendu très heureux

Nous avons juste commencé à faire des tests unitaires. Pendant longtemps, j’ai su que ce serait bien de commencer à le faire, mais je ne savais pas du tout comment commencer et surtout quoi tester.

Ensuite, nous avons dû réécrire un morceau de code important dans notre programme de comptabilité. Cette partie était très complexe car elle impliquait beaucoup de scénarios différents. La partie dont je parle est une méthode de paiement des ventes et / ou des factures d’achat déjà entrées dans le système comptable.

Je ne savais pas comment commencer à le coder, car il y avait tellement d’options de paiement différentes. Une facture pourrait être de 100 $, mais le client a seulement transféré 99 $. Vous avez peut-être envoyé des factures à un client, mais vous avez également acheté ce client. Donc, vous l’avez vendu pour 300 $, mais vous avez acheté pour 100 $. Vous pouvez vous attendre à ce que votre client vous paie 200 $ pour régler le solde. Et si vous vendiez pour 500 $, mais que le client ne vous paye que 250 $?

J’ai donc eu un problème très complexe à résoudre avec de nombreuses possibilités, à savoir qu’un scénario fonctionnerait parfaitement, mais que ce serait faux avec un autre type de combinaison de société / de paiement.

C’est là que les tests unitaires sont venus à la rescousse.

J’ai commencé à écrire (dans le code de test) une méthode pour créer une liste de factures, tant pour les ventes que pour les achats. Ensuite, j’ai écrit une deuxième méthode pour créer le paiement réel. Normalement, un utilisateur entrerait ces informations via une interface utilisateur.

Ensuite, j’ai créé le premier TestMethod, en testant un paiement très simple d’une facture unique sans aucun escompte de paiement. Toutes les actions du système se produiraient lorsqu’un paiement bancaire serait enregistré dans la firebase database. Comme vous pouvez le voir, j’ai créé une facture, créé un paiement (une transaction bancaire) et enregistré la transaction sur le disque. Dans mes affirmations, je mets ce que devraient être les bons numéros qui se retrouveraient dans la transaction bancaire et dans la facture liée. Je vérifie le nombre de paiements, les montants de paiement, le montant de la remise et le solde de la facture après la transaction.

Après le test, j’allais dans la firebase database et vérifiais si ce que j’attendais était là.

Après avoir écrit le test, j’ai commencé à coder le mode de paiement (partie de la classe BankHeader). Dans le codage, je me suis contenté du code pour faire le premier test. Je ne pensais pas encore aux autres scénarios plus complexes.

J’ai couru le premier test, corrigé un petit bug jusqu’à ce que mon test réussisse.

Ensuite, j’ai commencé à écrire le deuxième test, cette fois-ci avec un rabais de paiement. Après avoir écrit le test, j’ai modifié le mode de paiement pour prendre en charge les remises.

Tout en testant l’exactitude avec une remise de paiement, j’ai également testé le paiement simple. Les deux tests devraient bien sûr passer.

Ensuite, je suis passé aux scénarios plus complexes.

1) Pensez à un nouveau scénario

2) Rédiger un test pour ce scénario

3) Exécuter ce test unique pour voir si cela passerait

4) Si ce n’était pas le cas, je déboguerais et modifierais le code jusqu’à ce qu’il passe.

5) En modifiant le code, j’ai continué à exécuter tous les tests

C’est ainsi que j’ai réussi à créer mon mode de paiement très complexe. Sans les tests unitaires, je ne savais pas comment commencer à coder, le problème semblait insurmontable. Avec les tests, je pouvais commencer par une méthode simple et l’étendre pas à pas avec l’assurance que les scénarios les plus simples fonctionneraient toujours.

Je suis sûr que l’utilisation des tests unitaires m’a sauvé quelques jours (ou semaines) de codage et garantit plus ou moins l’exactitude de ma méthode.

Si je pense plus tard à un nouveau scénario, je peux simplement l’append aux tests pour voir si cela fonctionne ou non. Sinon, je peux modifier le code mais toujours être sûr que les autres scénarios fonctionnent toujours correctement. Cela permettra d’économiser des jours et des jours dans la phase de maintenance et de correction des bogues.

Oui, même un code testé peut toujours avoir des bogues si un utilisateur fait des choses auxquelles vous n’avez pas pensé ou que vous ne l’avez pas empêché

Voici quelques exemples de tests que j’ai créés pour tester mon mode de paiement.

 public class TestPayments { InvoiceDiaryHeader invoiceHeader = null; InvoiceDiaryDetail invoiceDetail = null; BankCashDiaryHeader bankHeader = null; BankCashDiaryDetail bankDetail = null; public InvoiceDiaryHeader CreateSales(ssortingng amountIncVat, bool sales, int invoiceNumber, ssortingng date) { ...... ...... } public BankCashDiaryHeader CreateMultiplePayments(IList invoices, int headerNumber, decimal amount, decimal discount) { ...... ...... ...... } [TestMethod] public void TestSingleSalesPaymentNoDiscount() { IList list = new List(); list.Add(CreateSales("119", true, 1, "01-09-2008")); bankHeader = CreateMultiplePayments(list, 1, 119.00M, 0); bankHeader.Save(); Assert.AreEqual(1, bankHeader.BankCashDetails.Count); Assert.AreEqual(1, bankHeader.BankCashDetails[0].Payments.Count); Assert.AreEqual(119M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount); Assert.AreEqual(0M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance); } [TestMethod] public void TestSingleSalesPaymentDiscount() { IList list = new List(); list.Add(CreateSales("119", true, 2, "01-09-2008")); bankHeader = CreateMultiplePayments(list, 2, 118.00M, 1M); bankHeader.Save(); Assert.AreEqual(1, bankHeader.BankCashDetails.Count); Assert.AreEqual(1, bankHeader.BankCashDetails[0].Payments.Count); Assert.AreEqual(118M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount); Assert.AreEqual(1M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance); } [TestMethod] [ExpectedException(typeof(ApplicationException))] public void TestDuplicateInvoiceNumber() { IList list = new List(); list.Add(CreateSales("100", true, 2, "01-09-2008")); list.Add(CreateSales("200", true, 2, "01-09-2008")); bankHeader = CreateMultiplePayments(list, 3, 300, 0); bankHeader.Save(); Assert.Fail("expected an ApplicationException"); } [TestMethod] public void TestMultipleSalesPaymentWithPaymentDiscount() { IList list = new List(); list.Add(CreateSales("119", true, 11, "01-09-2008")); list.Add(CreateSales("400", true, 12, "02-09-2008")); list.Add(CreateSales("600", true, 13, "03-09-2008")); list.Add(CreateSales("25,40", true, 14, "04-09-2008")); bankHeader = CreateMultiplePayments(list, 5, 1144.00M, 0.40M); bankHeader.Save(); Assert.AreEqual(1, bankHeader.BankCashDetails.Count); Assert.AreEqual(4, bankHeader.BankCashDetails[0].Payments.Count); Assert.AreEqual(118.60M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount); Assert.AreEqual(400, bankHeader.BankCashDetails[0].Payments[1].PaymentAmount); Assert.AreEqual(600, bankHeader.BankCashDetails[0].Payments[2].PaymentAmount); Assert.AreEqual(25.40M, bankHeader.BankCashDetails[0].Payments[3].PaymentAmount); Assert.AreEqual(0.40M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].PaymentDiscount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[2].PaymentDiscount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].PaymentDiscount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].InvoiceHeader.Balance); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[2].InvoiceHeader.Balance); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].InvoiceHeader.Balance); } [TestMethod] public void TestSettlement() { IList list = new List(); list.Add(CreateSales("300", true, 43, "01-09-2008")); //Sales list.Add(CreateSales("100", false, 6453, "02-09-2008")); //Purchase bankHeader = CreateMultiplePayments(list, 22, 200, 0); bankHeader.Save(); Assert.AreEqual(1, bankHeader.BankCashDetails.Count); Assert.AreEqual(2, bankHeader.BankCashDetails[0].Payments.Count); Assert.AreEqual(300, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount); Assert.AreEqual(-100, bankHeader.BankCashDetails[0].Payments[1].PaymentAmount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].InvoiceHeader.Balance); } 

Si elles sont vraiment sortingviales, alors ne vous inquiétez pas des tests. Par exemple, si elles sont implémentées comme ceci;

 public class User { public ssortingng Username { get; set; } public ssortingng Password { get; set; } } 

Si, par contre, vous faites quelque chose d’intelligent (comme le cryptage et le décryptage du mot de passe dans getter / setter), testez-le.

La règle est que vous devez tester chaque élément logique que vous écrivez. Si vous avez implémenté des fonctionnalités spécifiques dans les getters et les setters, je pense qu’ils valent la peine d’être testés. S’ils n’atsortingbuent que des valeurs à certains champs privés, ne vous en faites pas.

Cette question semble être une question de savoir où tracer la ligne sur les méthodes testées et celles qui ne le sont pas.

Les formateurs et les destinataires de l’affectation des valeurs ont été créés en gardant à l’esprit la cohérence et la croissance future, et en prévoyant que, quelque temps après, le setter / getter pourrait évoluer vers des opérations plus complexes. Il serait judicieux de mettre en place des tests unitaires de ces méthodes, également dans un souci de cohérence et de croissance future.

L’objective principal est la fiabilité du code, en particulier lorsqu’il subit des modifications pour append des fonctionnalités supplémentaires. Je ne suis au courant de personne ayant été licencié pour avoir inclus des «seters / getters» dans la méthodologie de test, mais je suis certain qu’il existe des personnes qui souhaitaient avoir testé des méthodes dont plus le cas.

Peut-être qu’un autre membre de l’équipe a élargi les méthodes set / get pour inclure la logique qui doit maintenant être testée, mais n’a pas ensuite créé les tests. Mais maintenant, votre code appelle ces méthodes et vous ne savez pas qu’elles ont changé et ont besoin de tests approfondis, et les tests que vous effectuez en développement et en assurance qualité ne déclenchent pas le défaut. déclencher

Les deux coéquipiers vont maintenant se disputer pour savoir qui a laissé tomber le ballon et ne pas avoir réussi à passer des tests unitaires lorsque le set / se transforme pour inclure une logique qui peut échouer mais qui n’est pas couverte par un test unitaire. Le coéquipier qui a écrit le set / get aura plus de facilité à sortir de ce clean si les tests ont été mis en place dès le premier jour sur le simple set / get.

Mon opinion est que quelques minutes de “perte” de temps pour couvrir TOUTES les méthodes avec des tests unitaires, même sortingviaux, pourraient sauver des jours de maux de tête sur la route et une perte d’argent ou de réputation.

Et le fait que vous ayez enroulé des méthodes sortingviales avec des tests unitaires peut être vu par ce coéquipier junior quand il change les méthodes sortingviales en méthodes non sortingviales et les invite à mettre à jour le test, et maintenant personne n’est en difficulté parce que le défaut est contenu d’atteindre la production.

La façon dont nous codons et la discipline que nous pouvons voir dans notre code peuvent aider les autres.

Une autre réponse canonique. Ceci, je crois, de Ron Jeffries:

Ne testez que le code que vous souhaitez utiliser.

Tester le code passe-partout est une perte de temps, mais comme le dit Slavo, si vous ajoutez un effet secondaire à vos getters / setters, alors vous devriez écrire un test pour accompagner cette fonctionnalité.

Si vous effectuez un développement piloté par les tests, vous devez d’abord rédiger le contrat (par exemple, l’interface), puis rédiger le ou les tests pour utiliser cette interface qui documente les résultats / comportements attendus. Ensuite, écrivez vos méthodes elles-mêmes, sans toucher au code dans vos tests unitaires. Enfin, prenez un outil de couverture de code et assurez-vous que vos tests exercent tous les chemins logiques de votre code.

Un code vraiment sortingvial, comme les getters et les setters qui n’ont pas de comportement supplémentaire que la définition d’un champ privé, est trop compliqué à tester. En 3.0 C # a même un peu de sucre syntaxique où le compilateur prend en charge le champ privé de sorte que vous n’avez pas à programmer cela.

J’écris habituellement beaucoup de tests très simples pour vérifier le comportement que j’attends de mes cours. Même si c’est simple comme append deux nombres. Je passe beaucoup de temps entre écrire un test simple et écrire des lignes de code. La raison en est que je peux alors changer de code sans craindre d’avoir brisé des choses auxquelles je n’avais pas pensé.

Vous devriez tout tester. En ce moment, vous avez des getters et des setters, mais un jour vous pourriez les changer quelque peu, peut-être pour faire de la validation ou autre chose. Les tests que vous écrivez aujourd’hui seront utilisés demain pour que tout fonctionne comme d’habitude. Lorsque vous écrivez un test, vous devez oublier des considérations comme “en ce moment, c’est sortingvial”. Dans un contexte agile ou axé sur les tests, vous devez tester en supposant une refactorisation future. Aussi, avez-vous essayé de mettre des valeurs vraiment étranges comme des cordes extrêmement longues ou d’autres “mauvais” contenus? Eh bien, vous devriez … ne jamais supposer à quel point votre code peut être maltraité à l’avenir.

En général, je trouve que l’écriture de tests d’utilisateur approfondis est d’un côté, épuisante. D’un autre côté, bien que cela vous donne toujours un aperçu inestimable du fonctionnement de votre application et vous aide à jeter des hypothèses simples (et fausses) (comme: le nom d’utilisateur aura toujours moins de 1000 caractères).

Pour les modules simples qui peuvent se retrouver dans une boîte à outils, ou dans un type de projet open source, vous devez tester autant que possible, y compris les outils et parameters simples. La chose que vous devez garder à l’esprit est que la génération d’un test unitaire lorsque vous écrivez un module particulier est assez simple et directe. Ajouter des getters et des setters est un code minimal et peut être manipulé sans trop y penser. Cependant, une fois que votre code est placé dans un système plus grand, cet effort supplémentaire peut vous protéger contre les modifications du système sous-jacent, telles que les modifications de type dans une classe de base. Tester tout est le meilleur moyen d’avoir une régression complète.

Il n’est pas difficile d’écrire des tests unitaires pour vos getters et vos préparateurs. En ce moment, ils peuvent juste faire des get / sets de champs sous le capot, mais à l’avenir, il se peut que vous ayez à tester une logique de validation ou des dépendances inter-propriétés. Il est plus facile de l’écrire maintenant pendant que vous y réfléchissez, puis de vous rappeler de le remplacer si cela arrivait.

en général, lorsqu’une méthode est uniquement définie pour certaines valeurs, testez les valeurs sur et au -delà de ce qui est acceptable. En d’autres termes, assurez-vous que votre méthode fait ce qu’elle est censée faire, mais rien de plus . Ceci est important car lorsque vous échouez, vous voulez échouer tôt.

Dans les hiérarchies d’inheritance, assurez-vous de tester la conformité au LSP .

Tester les getters et setters par défaut ne me semble pas très utile, à moins que vous ne souhaitiez le faire ultérieurement.

Comme je comprends les tests unitaires dans le contexte du développement agile, Mike, oui, vous devez tester les getters et les setters (en supposant qu’ils soient publiquement visibles). Le concept de test unitaire consiste à tester l’unité de logiciel, qui est une classe dans ce cas, comme une boîte noire . Puisque les getters et les setters sont visibles de l’extérieur, vous devez les tester avec Authenticate and Save.

Si les méthodes Authenticate et Save utilisent les propriétés, vos tests toucheront indirectement les propriétés. Tant que les propriétés ne font que fournir un access aux données, un test explicite ne devrait pas être nécessaire (sauf si vous visez une couverture à 100%).

Je testerais tes getters et mes préparateurs. Selon qui écrit le code, certaines personnes changent la signification des méthodes getter / setter. J’ai vu l’initialisation des variables et d’autres validations dans le cadre des méthodes getter. Afin de tester ce genre de chose, vous voudriez des tests unitaires couvrant ce code explicitement.

Personnellement, je “teste tout ce qui peut casser” et un simple getter (ou même de meilleures propriétés auto) ne se cassera pas. Je n’ai jamais eu de simple déclaration de retour et je n’ai donc jamais pu les tester. Si les getters ont des calculs à l’intérieur d’eux ou d’autres formes de déclarations, j’appendais certainement des tests pour eux.

Personnellement, j’utilise Moq comme structure d’object simulée, puis vérifie que mon object appelle les objects environnants comme il se doit.

Vous devez couvrir l’exécution de chaque méthode de la classe avec UT et vérifier la valeur de retour de la méthode. Cela inclut les getters et les setters, en particulier si les membres (propriétés) sont des classes complexes, ce qui nécessite une grande allocation de mémoire lors de leur initialisation. Appelez le setter avec une très grande chaîne par exemple (ou quelque chose avec des symboles grecs) et vérifiez que le résultat est correct (non tronqué, l’encodage est bon, etc.)

Dans le cas d’entiers simples qui s’appliquent également, que se passe-t-il si vous passez longtemps au lieu d’un entier? C’est la raison pour laquelle vous écrivez UT pour 🙂

Je ne testerais pas la configuration réelle des propriétés. Je serais plus préoccupé par la façon dont ces biens sont peuplés par le consommateur et par quoi ils les peuplent. Avec tout test, vous devez peser les risques avec le temps / coût des tests.

Vous devriez tester “chaque bloc de code non sortingvial” en utilisant autant que possible des tests unitaires.

Si vos propriétés sont sortingviales et qu’il est peu probable que quelqu’un y introduise un bogue, il ne devrait pas être dangereux de les tester.

Vos méthodes Authenticate () et Save () ressemblent à de bons candidats pour les tests.

Idéalement, vous auriez fait vos tests unitaires en écrivant la classe. C’est ce que vous êtes censé faire lorsque vous utilisez le développement piloté par les tests. Vous ajoutez les tests au fur et à mesure que vous implémentez chaque sharepoint fonction, en veillant à couvrir également les bords de test avec le test.

Ecrire les tests après est beaucoup plus douloureux, mais faisable.

Voici ce que je ferais dans votre position:

  1. Écrivez un ensemble de tests de base pour tester la fonction principale.
  2. Obtenez NCover et lancez-le sur vos tests. Votre couverture de test sera probablement autour de 50% à ce stade.
  3. Continuez à append des tests qui couvrent vos limites jusqu’à ce que vous obteniez une couverture d’environ 80% à 90%.

Cela devrait vous donner un bon ensemble de tests unitaires qui agiront comme un bon tampon contre les régressions.

Le seul problème avec cette approche est que le code doit être conçu pour pouvoir être testé de cette manière. Si vous avez commis des erreurs de couplage dès le début, vous ne pourrez pas obtenir une couverture élevée très facilement.

C’est pourquoi il est très important d’écrire les tests avant d’écrire le code. Cela vous oblige à écrire du code qui est faiblement couplé.

Ne testez évidemment pas le code de travail (standard). Donc, si vos setters et getters sont juste “propertyvalue = value” et “return propertyvalue”, cela n’a aucun sens de le tester.

Même get / set peut avoir des conséquences étranges, en fonction de la manière dont elles ont été implémentées. Elles doivent donc être traitées comme des méthodes.

Chaque test de ces derniers devra spécifier des ensembles de parameters pour les propriétés, définissant les propriétés à la fois acceptables et inacceptables pour garantir que les appels renvoient / échouent de la manière attendue.

Vous devez également connaître les pièges de la sécurité, comme exemple d’injection SQL, et les tester.

Donc oui, vous devez vous soucier de tester les propriétés.

Je pense qu’il est idiot d’essayer les getters et les setters lorsqu’ils ne font qu’une opération simple. Personnellement, je n’écris pas de tests unitaires complexes pour couvrir un modèle d’utilisation. J’essaie d’écrire suffisamment de tests pour m’assurer que j’ai bien géré le comportement d’exécution normal et autant de cas d’erreurs auxquels je peux penser. J’écrirai plus de tests unitaires en réponse aux rapports de bogues. J’utilise le test unitaire pour vérifier que le code répond aux exigences et faciliter les modifications futures. Je me sens beaucoup plus enclin à changer de code quand je sais que si je casse quelque chose, un test échouera.

J’écrirais un test pour tout ce que vous écrivez du code car celui-ci est testable en dehors de l’interface graphique.

En règle générale, toute logique que j’écris qui comporte une logique métier que je place dans un autre niveau ou une autre couche de logique métier.

Ensuite, écrire des tests pour tout ce qui fait quelque chose est facile à faire.

Premier passage, écrivez un test unitaire pour chaque méthode publique dans votre “couche logique de gestion”.

Si j’avais un cours comme celui-ci:

  public class AccountService { public void DebitAccount(int accountNumber, double amount) { } public void CreditAccount(int accountNumber, double amount) { } public void CloseAccount(int accountNumber) { } } 

La première chose que je ferais avant d’écrire un code en sachant que je devais réaliser ces actions serait de commencer à écrire des tests unitaires.

  [TestFixture] public class AccountServiceTests { [Test] public void DebitAccountTest() { } [Test] public void CreditAccountTest() { } [Test] public void CloseAccountTest() { } } 

Écrivez vos tests pour valider le code que vous avez écrit pour faire quelque chose. Si vous parcourez une collection de choses et modifiez quelque chose à propos de chacune d’elles, écrivez un test qui fait la même chose et assert que cela s’est produit.

Il y a beaucoup d’autres approches que vous pouvez adopter, à savoir le développement axé sur les comportements (BDD), qui est plus complexe et ne constitue pas un excellent sharepoint départ pour vos compétences en matière de tests unitaires.

Donc, la morale de l’histoire est de tester tout ce qui vous inquiète, de faire en sorte que les tests unitaires testent des choses spécifiques de petite taille, de nombreux tests sont bons.

Gardez votre logique métier en dehors de la couche d’interface utilisateur afin de pouvoir facilement leur écrire des tests, et vous serez bon.

Je recommande TestDriven.Net ou ReSharper car les deux s’intègrent facilement dans Visual Studio.

Eh bien, si vous pensez que cela peut casser, écrivez un test pour cela. Je ne teste généralement pas setter / getter, mais disons que vous en créez un pour User.Name, qui concatène le prénom et le nom, j’écrirais un test, donc si quelqu’un change l’ordre pour le prénom et le nom, au moins il le saurait il a changé quelque chose qui a été testé.

La réponse canonique est “testez tout ce qui peut éventuellement casser”. Si vous êtes certain que les propriétés ne se casseront pas, ne les testez pas.

Et une fois que quelque chose est trouvé cassé (vous trouvez un bug), cela signifie évidemment que vous devez le tester. Ecrivez un test pour reproduire le bogue, regardez-le échouer, puis corrigez le bogue, puis regardez le test réussi.

Je vous recommande d’écrire plusieurs tests pour vos méthodes Authenticate and Save. En plus du cas de succès (où tous les parameters sont fournis, tout est correctement orthographié, etc.), il est bon d’avoir des tests pour différents cas de défaillance (parameters incorrects ou manquants, connexions de firebase database indisponibles, etc.). Je recommande les tests unitaires pragmatiques en C # avec NUnit comme référence.

Comme d’autres l’ont déclaré, les tests unitaires pour les receveurs et les attaquants sont excessifs, à moins qu’il y ait une logique conditionnelle dans vos getters et vos adversaires.

Bien qu’il soit possible de deviner correctement où votre code doit être testé, je pense généralement que vous avez besoin de mésortingques pour sauvegarder cette hypothèse. Selon moi, les tests unitaires vont de pair avec les mésortingques de couverture de code.

Code avec beaucoup de tests mais une petite couverture n’a pas été bien testée. Cela dit, le code avec une couverture de 100%, mais sans tester les limites et les cas d’erreur, n’est pas non plus génial.

Vous voulez un équilibre entre une couverture élevée (90% minimum) et des données d’entrée variables.

N’oubliez pas de tester “Garbage In”!

De plus, un test unitaire n’est pas un test unitaire sauf s’il détecte une défaillance. Les tests unitaires qui n’ont pas d’affirmations ou sont marqués avec des exceptions connues testeront simplement que le code ne meurt pas lorsqu’il est exécuté!

Vous devez concevoir vos tests pour qu’ils signalent toujours les pannes ou les données inattendues / indésirables!

Cela rend notre code meilleur … période!

Une chose que les développeurs de logiciels oublient lors du développement piloté par les tests est l’objective de nos actions. Si un test unitaire est en cours d’écriture après que le code de production est déjà en place, la valeur du test diminue (mais n’est pas complètement perdue).

In the true spirit for unit testing, these tests are not primarily there to “test” more of our code; or to get 90%-100% better code coverage. These are all fringe benefits of writing the tests first. The big payoff is that our production code ends be be written much better due to the natural process of TDD.

To help better communicate this idea, the following may be helpful in reading:

The Flawed Theory of Unit Tests
Purposeful Software Development

If we feel that the act of writing more unit tests is what helps us gain a higher quality product, then we may be suffering from a Cargo Cult of Test Driven Development.