179 votes

Faut-il écrire des tests unitaires pour les getter et setters ?

Sommes-nous censés écrire des tests pour nos getters et setters ou est-ce excessif ?

0 votes

Je ne pense pas. Vous ne devez pas écrire de scénario de test pour les getter/setter.

1 votes

Je suppose que vous voulez dire Java ? C'est une question particulièrement aiguë pour Java, beaucoup moins pour les langages plus modernes.

0 votes

Quels sont les langages modernes qui n'ont pas de propriétés ? Bien sûr, des langages comme Java exigent qu'elles soient des corps de méthode complets, mais cela ne les rend pas logiquement différentes de C#, par exemple.

231voto

skaffman Points 197885

Je dirais non.

@Will a dit que vous devriez viser une couverture de code de 100%, mais à mon avis, c'est une distraction dangereuse. Vous pouvez écrire des tests unitaires qui ont une couverture de 100%, et pourtant ne tester absolument rien.

Les tests unitaires sont là pour tester le comportement de votre code, d'une manière expressive et significative, et les getters/setters ne sont qu'un moyen d'y parvenir. Si vos tests utilisent les getters/setters pour atteindre leur objectif de tester la "vraie" fonctionnalité, alors c'est suffisant.

Si, d'un autre côté, vos getters et setters font plus que simplement get et set (c'est-à-dire qu'il s'agit de méthodes correctement complexes), alors oui, ils doivent être testés. Mais n'écrivez pas un scénario de test unitaire juste pour tester un getter ou un setters, c'est une perte de temps.

10 votes

Viser une couverture de code à 100% est stupide. Vous finirez par couvrir du code qui n'est pas exposé au public, et/ou du code sans complexité. Il est préférable de laisser ces choses à l'autogénération, mais même les tests autogénérés sont assez inutiles. Il est préférable de se concentrer sur les tests importants, comme les tests d'intégration.

9 votes

@Claus : Je suis d'accord sauf pour la partie concernant la concentration sur les tests d'intégration. Les tests unitaires sont essentiels à une bonne conception, et complètent les tests d'intégration.

8 votes

Je pense qu'une couverture de code de 100 % lorsque la suite de tests complète est exécutée est un bon objectif. Les getters setters de propriétés et autres codes sont exécutés dans le cadre de tests plus larges. Les derniers éléments à couvrir sont probablement la gestion des erreurs. Et si la gestion des erreurs n'est pas couverte par des tests unitaires, elle ne le sera jamais. Voulez-vous vraiment livrer un produit qui contient du code qui n'a jamais été exécuté ?

48voto

azhidkov Points 107

Roy Osherove dans son célèbre livre 'The Art Of Unit Testing' dit :

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 pas de test. Mais attention : dès que vous ajoutez une vérification à l'intérieur de la propriété, vous devez vous assurer que cette logique est testée.

3 votes

Compte tenu du peu de temps qu'il faut pour les tester et de la probabilité que des comportements soient ajoutés, je ne vois pas pourquoi pas. Je pense que si on le pressait, il pourrait répondre "bien, je suppose pourquoi pas".

3 votes

Les premiers livres importants contiennent souvent de mauvais conseils. J'ai vu tellement de cas où les gens ont rapidement mis en place des getters et setters et ont fait des erreurs parce qu'ils ont fait un copier-coller ou ont oublié ceci. ou ceci-> ou quelque chose comme ça. Ils sont faciles à tester et devraient certainement être testés.

25voto

ArtB Points 3922

tl;dr : Oui vous debe et avec OpenPojo c'est trivial.

  1. Vous devriez faire de la validation dans vos getters et setters, donc vous devriez les tester. Par exemple, setMom(Person p) ne devraient pas permettre de prendre pour mère une personne plus jeune qu'eux.

  2. Même si vous ne faites rien de tout cela aujourd'hui, il y a de fortes chances que vous le fassiez à l'avenir, ce qui constitue une bonne analyse de régression. Si vous voulez permettre aux mères encadrantes de null vous devriez avoir un test pour cela, si quelqu'un le change plus tard, cela renforcera vos hypothèses.

  3. Un bug commun est void setFoo( Object foo ){ foo = foo; } où il devrait être void setFoo( Object foo ){ this.foo = foo; } . (Dans le premier cas, le foo dans lequel on écrit est le paramètre no le site foo dans le champ objet ).

  4. Si vous renvoyez un tableau ou une collection, vous devez tester si le récupérateur va ou non exécuter le test. copies de sécurité des données passées dans le setter avant de revenir.

  5. Sinon, si vous avez les setters/getters les plus basiques, le test unitaire de ceux-ci ajoutera peut-être 10 minutes au maximum par objet, alors quelle est la perte ? Si vous ajoutez un comportement, vous avez déjà un squelette de test et vous obtenez ce test de régression gratuitement. Si vous utilisez Java, vous n'avez aucune excuse puisqu'il existe des tests de régression. OpenPojo . Il existe un ensemble de règles que vous pouvez activer, puis balayer l'ensemble de votre projet avec elles pour vous assurer qu'elles sont appliquées de manière cohérente dans votre code.

De leur exemples :

final Validator pojoValidator = ValidatorBuilder.create()
        .with(
            new NoPublicFieldsRule  (),
            new NoPrimitivesRule    (),
            new GetterMustExistRule (),
            new SetterMustExistRule ()
        )
        .with(
            new DefaultValuesNullTester (),
            new SetterTester            (),
            new GetterTester            ()
        )
        .build();

pojoValidator.validate(  PojoClassFactory.getPojoClasses( "net.initech.app", new FilterPackageInfo() )  );

12 votes

Je sais que c'est un peu vieux maintenant, mais.. : DEVRIEZ-VOUS faire la validation dans vos getters et setters ? J'avais l'impression que setMom devait faire ce qu'il dit. S'il s'agit de valider, alors cela ne devrait-il pas être validateAndSetMom ? Ou mieux, le code de validation ne devrait-il pas exister AILLEURS qu'un simple objet ? Qu'est-ce que je rate ici ?

18 votes

Oui, vous devriez toujours valider vos entrées. Si vous ne le faites pas, pourquoi ne pas utiliser une variable publique ? C'est la même chose. L'avantage d'utiliser des setters plutôt que des variables est que cela vous permet de vous assurer que votre objet n'est jamais invalide, par exemple que l'âge est un nombre négatif. Si vous ne le faites pas dans l'objet, vous le ferez ailleurs (comme dans un "service"). objet divin ) et ce n'est pas vraiment OOP à ce moment-là.

1 votes

Eh bien, c'est probablement le point culminant de ma semaine. Merci.

14voto

bryanbcook Points 7184

Bien qu'il existe des raisons justifiées pour les propriétés, une croyance commune en matière de conception orientée objet veut que l'exposition de l'état des membres via les propriétés soit une mauvaise conception. Article de Robert Martin sur le principe de l'ouverture et de la fermeture. poursuit en affirmant que les propriétés encouragent le couplage et limitent donc la possibilité de fermer une classe aux modifications - si vous modifiez la propriété, tous les consommateurs de la classe devront également le faire. Il précise que l'exposition des variables membres n'est pas nécessairement une mauvaise conception, mais simplement un mauvais style. Cependant, si les propriétés sont en lecture seule, il y a moins de risques d'abus et d'effets secondaires.

La meilleure approche que je puisse proposer pour les tests unitaires (et cela peut paraître étrange) est de rendre le plus grand nombre possible de propriétés protégées ou internes. Cela permet d'éviter le couplage tout en décourageant l'écriture de tests stupides pour les getters et setters.

Il existe des raisons évidentes pour lesquelles les propriétés en lecture/écriture doivent être utilisées, comme les propriétés du ViewModel qui sont liées aux champs de saisie, etc.

De manière plus pratique, les tests unitaires devraient conduire la fonctionnalité à travers les méthodes publiques. Si le code que vous testez utilise ces propriétés, vous obtenez une couverture de code gratuite. S'il s'avère que ces propriétés ne sont jamais mises en évidence par le code-coverage, il y a une très forte possibilité que :

  1. Il vous manque des tests qui utilisent indirectement les propriétés
  2. Les propriétés sont inutilisées

Si vous écrivez des tests pour les getters et setters, vous obtenez une fausse impression de couverture et vous ne serez pas en mesure de déterminer si les propriétés sont réellement utilisées par le comportement fonctionnel.

14voto

Si le complexité cyclomatique du getter et/ou du setter est égal à 1 (ce qui est généralement le cas), alors la réponse est non, vous ne devez pas le faire.

Donc, à moins que vous n'ayez un accord de niveau de service qui exige une couverture du code à 100 %, ne vous donnez pas la peine et concentrez-vous sur le test de l'aspect important de votre logiciel.

P.S. N'oubliez pas de différencier les getters et les setters, même dans des langages comme C# où les propriétés peuvent sembler être la même chose. La complexité du setter peut être supérieure à celle du getter, et donc valider un test unitaire.

5 votes

Bien qu'il faille tester la copie défensive sur les getters

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X