web-dev-qa-db-fra.com

Devez-vous tester des propriétés simples?

Devez-vous tester les propriétés simples d’une classe en affirmant qu’une valeur est définie et extraite? Ou est-ce vraiment juste l'unité qui teste la langue?

Exemple

public string ConnectionString { get; set; }

Test

public void TestConnectionString()
{
    var c = new MyClass();
    c.ConnectionString = "value";

    Assert.Equal(c.ConnectionString, "value");
}

Je suppose que je ne vois pas la valeur en cela.

42
Sam

Je suggérerais que vous devriez absolument. 

  • Qu'est-ce qu'une auto-propriété aujourd'hui peut finir par avoir un champ de support contre elle demain, et pas par vous ...

  • L'argument selon lequel "vous ne testez que le compilateur ou le framework" est un peu un imbécile; ce que vous faites lorsque vous testez une propriété automatique, c'est, du point de vue de l'appelant, de tester "l'interface" publique de votre classe. L'appelant n'a aucune idée s'il s'agit d'une propriété auto avec un magasin de support généré par la structure ou s'il existe un million de lignes de code complexe dans le getter/setter. Par conséquent, l'appelant teste le contrat impliqué par la propriété _ que si vous mettez X dans la boîte, vous pourrez le récupérer ultérieurement.

  • Par conséquent, il nous incombe d'inclure un test puisque nous testons le comportement de notre propre code et non celui du compilateur.

  • Un test comme celui-ci prend peut-être une minute à écrire, donc ce n’est pas vraiment fastidieux; et vous pouvez facilement créer un modèle T4 qui générera automatiquement ces tests avec un peu de réflexion. Je travaille actuellement sur un tel outil pour sauver notre équipe des travaux fastidieux

  • Si vous utilisez du TDD pur, cela vous oblige à vous arrêter un instant et à vous demander si le fait d'avoir une propriété publique auto est même la meilleure chose à faire (indice: ce n'est souvent pas le cas!)

  • Ne préféreriez-vous pas avoir un test de régression initial afin que, lorsque le FNG effectue quelque chose comme ceci:


//24-SEP-2013::FNG - put backing field for ConnectionString as we're now doing constructor injection of it
public string ConnectionString
{
   {get { return _connectionString; } }
   {set {_connectionString="foo"; } }//FNG: I'll change this later on, I'm in a hurry
}

///snip

public MyDBClass(string connectionString)
{
   ConnectionString=connectionString;
}

Vous instantanément savez qu'ils ont cassé quelque chose?

Si ce qui précède semble être conçu pour une propriété de chaîne simple, j'ai personnellement vu une situation où une propriété automatique était refactorisée par quelqu'un qui pensait être si intelligent et qui voulait le changer d'un membre d'instance à un wrapper autour d'un membre statique de la classe. (représentant une connexion de base de données au fur et à mesure, les conséquences du changement ne sont pas importantes).

Bien sûr, cette même personne très intelligente complètement oublié pour dire à quelqu'un d'autre qu'il lui fallait appeler une fonction magique pour initialiser ce membre statique. 

Cela a entraîné la compilation de l'application et son envoi à un client, après quoi elle a rapidement échoué. Ce n'est pas une grosse affaire, mais cela a coûté plusieurs heures de support à == l'argent .... Ce muppet, c'était moi!

EDIT: comme dans diverses conversations sur ce fil, je voulais souligner qu'un test pour une propriété en lecture-écriture est ridiculement simple:

[TestMethod]
public void PropertyFoo_StoresCorrectly()
{
   var sut = new MyClass();
   sut.Foo = "hello";
   Assert.AreEqual("hello", sut.Foo, "Oops...");
}

edit: Et vous pouvez même le faire en une seule ligne selon Mark Seeman/ Autofixture

Je soutiendrais que si vous trouvez que vous avez un nombre de propriétés publiques tel que l’écriture de 3 lignes comme celle ci-dessus devienne une corvée pour chacune d’elles, vous devriez alors remettre en question votre conception; Si vous utilisez un autre test pour indiquer un problème avec cette propriété,

  • Le test teste réellement cette propriété, ou
  • Vous passerez plus de temps à vérifier que cet autre test échoue car la propriété est incorrecte (via le débogueur, etc.) par rapport à la saisie du code ci-dessus.
  • Si un autre test vous permet de dire instantanément que la propriété est en faute, ce n'est pas un test unitaire!

edit (encore!): Comme indiqué dans les commentaires, et à juste titre, des éléments tels que les modèles DTO générés et similaires sont probablement des exceptions à ce qui précède, car ils ne sont que de vieux seaux stupides pour déplacer des données ailleurs, plus depuis qu'un outil les a créés , il est généralement inutile de les tester.

/MODIFIER

En fin de compte, "ça dépend" est probablement la vraie réponse, à condition toutefois que la meilleure solution "par défaut" soit l'approche "toujours fais-le", avec des exceptions à celle prise de manière éclairée, au cas par cas.

40
Stephen Byrne

Généralement non. Un test unitaire doit être utilisé pour tester la fonctionnalité d'une unité. Vous devez utiliser des méthodes de test unitaires sur une classe et non des propriétés automatiques individuelles (à moins que vous ne surchargiez le getter ou le setter avec un comportement personnalisé). 

Vous savez que l'affectation d'une valeur de chaîne à une propriété de chaîne automatique fonctionnera si vous obtenez la syntaxe et la valeur de définition correctes, car elles font partie de la spécification de langue. Si vous ne le faites pas, vous obtiendrez une erreur d'exécution pour signaler votre faille.

Les tests unitaires doivent être conçus pour rechercher les erreurs logiques dans le code plutôt que quelque chose que le compilateur attraperait de toute façon. 

EDIT: Selon ma conversation avec l'auteur de la réponse acceptée pour cette question, je voudrais ajouter ce qui suit.

Je peux comprendre que les puristes de TDD diraient que vous devez tester les propriétés automatiques. Mais en tant que développeur d’applications d’affaires, j’ai besoin de peser raisonnablement le temps que je pourrais consacrer à l’écriture et à la réalisation de tests de code «trivial», tels que des propriétés automatiques, par rapport au temps qu'il faudrait raisonnablement pour résoudre un problème pouvant découler pas de test. D'après l'expérience personnelle, la plupart des bogues générés par la modification d'un code trivial sont faciles à résoudre 99% du temps. Pour cette raison, je dirais que les avantages de la fonctionnalité de spécification non langagière testée à l’unité par les tests unitaires dépassent les inconvénients.

Si vous travaillez dans un environnement professionnel au rythme rapide qui utilise une approche TDD, une partie du flux de travail de cette équipe doit consister à ne tester que le code qui doit être testé, essentiellement tout code personnalisé. Si quelqu'un entre dans votre classe et modifie le comportement d'une propriété automatique, il lui incombe de configurer un test unitaire à ce moment-là.

37
BenM

Adhérez-vous à des pratiques strictes de TDD ou pas? 

Si oui, alors vous absolument devriez écrire des tests sur les getters et les setters publics, sinon, comment saurez-vous si vous les avez correctement implémentés?

Si non, vous devriez probablement encore écrire les tests. Bien que l’implémentation soit aujourd’hui triviale, il n’est pas garanti de le rester, et sans test couvrant les fonctionnalités d’une simple opération get/set, lorsqu’une modification ultérieure de l’implémentation annule une invariante de "la propriété Foo avec une valeur Bar a pour résultat le getter de la propriété Foo renvoyant la valeur Bar "les tests unitaires continueront de réussir. Le test lui-même est est également implémenté de manière triviale, tout en protégeant contre les changements futurs.

3
Preston Guillot

Je devrais dire non. Si cela ne fonctionne pas, vous avez de plus gros problèmes. Je sais que non. Certains diront maintenant que le code seul suffirait à faire échouer le test si la propriété était supprimée, par exemple. Mais je mettrais de l'argent sur le fait que si la propriété était supprimée, le code de test unitaire serait supprimé dans le refactor, donc cela n'aurait aucune importance.

3
Mike Perrenoud

La façon dont je vois les choses, c’est que le nombre de tests unitaires (ou de tests en général) dépend du degré de confiance que le code fonctionne comme prévu et des chances de rupture dans le futur.

Si vous avez une confiance moindre en la rupture de code (peut-être en raison de la sous-traitance du code et du coût élevé du contrôle ligne par ligne), alors les propriétés de test unitaire sont appropriées. 

Une fois que vous pouvez faire est d’écrire une classe auxiliaire qui peut passer en revue toutes les propriétés get/set d’une classe afin de vérifier qu’elles se comportent toujours comme prévu.

2
aqwert

Selon le livre L'art du test unitaire Avec des exemples dans .NET , un test unitaire ne couvre aucun type de code, il se concentre sur code logique. Alors, qu'est-ce que code logique?

Le code logique est tout morceau de code contenant une sorte de logique, aussi petit qu'il puisse être. C'est un code logique s'il comporte un ou plusieurs des éléments suivants instructions de cas, calculs, ou tout autre type de code décisionnel.

Un simple getter/setter encapsule-t-il une quelconque logique? La réponse est:

Les propriétés (getters/setters en Java) sont de bons exemples de code qui ne contient généralement pas de logique et ne nécessite donc pas de test. Mais faites attention: une fois que vous aurez ajouté un chèque à l’intérieur de la propriété, vous voudrez assurez-vous que cette logique est testée.

1
Alireza

Sauf si les propriétés exécutent une autre sorte de logique, alors non. 

Oui, c'est comme si l'unité testait la langue. Sinon, il serait totalement inutile de tester des propriétés simples implémentées automatiquement. 

1
Ciaran Gallagher

Ma réponse, qui provient du point de vue de l'ancien responsable du test et actuellement responsable du développement (responsable de la livraison du logiciel en temps et en qualité) Je vois des gens parler de pragmatisme. Le pragmatisme n'est pas un bon conseiller car il peut être associé à la paresse et/ou à la pression du temps. Cela peut vous conduire sur le mauvais chemin. Si vous parlez de pragmatisme, vous devez veiller à maintenir vos intentions sur la voie du professionnalisme et du bon sens. Il faut de l'humilité pour accepter les réponses, car elles ne sont peut-être pas ce que vous voulez entendre.

De mon point de vue, ce qui est important sont les suivants:

  • vous devriez trouver le défaut le plus tôt possible. Pour ce faire, vous devez appliquer la stratégie de test appropriée. S'il teste les propriétés, vous devez alors tester les propriétés. Si non, alors ne le faites pas. Les deux ont un prix.
  • vos tests devraient être faciles et rapides. La plus grande partie (unité, intégration, etc.) du code testé lors de la compilation est la meilleure.
  • vous devez effectuer une analyse des causes profondes pour répondre aux questions ci-dessous et protéger votre organisation du type d'erreur actuel. Ne vous inquiétez pas, un autre type de défaut se présentera et il y aura toujours des leçons à apprendre .
    • quelle est la cause première?
    • comment l'éviter la prochaine fois?
  • un autre aspect est le coût de création/maintenance des tests. Ne pas tester les propriétés parce qu'elles sont ennuyeuses à maintenir et/ou si vous avez des centaines de propriétés, c'est ridicule. Vous devez créer/appliquer des outils qui rendent le travail de coupe du bois plutôt que humain. En général, vous devez toujours améliorer votre environnement pour être plus efficace.
  • ce que les autres disent ne sont pas de bons conseillers - peu importe que cela ait été dit par Martin Fowler ou Seeman - leur environnement, je suis presque sûr que ce n'est pas comme vous est bon pour votre projet et comment le rendre meilleur. Si vous appliquez des choses parce qu'elles ont été dites par des personnes, vous êtes respectueux sans même y penser, vous vous retrouverez dans une situation difficile. Je ne dis pas que vous n'avez pas besoin de conseils et/ou d'aide ou d'opinion, vous devez appliquer le bon sens pour les appliquer.
  • TDD ne répond pas à deux questions importantes. Cependant, BDD vous donne les réponses aux questions ci-dessous. Mais, si vous en suivez une seule, vous n'aurez pas une livraison dans les délais et dans la qualité. Donc, peu importe si vous êtes un puriste TDD ou non .
    • que faut-il tester? (il dit que tout doit être testé - mauvaise réponse à mon avis)
    • quand le test doit être terminé?

Dans l’ensemble, il n’ya pas de bonne réponse. Juste d'autres questions auxquelles vous devez répondre pour obtenir ce point temporaire où vous êtes capable de décider si c'est nécessaire ou non. 

0
SayusiAndo