72 votes

Qu'y a-t-il de mal à faire d'un test unitaire un ami de la classe testée?

En c++, j'ai souvent fait un test de l'unité de la classe, un ami de la classe, je suis en train de tester. Je le fais parce que parfois, je ressens le besoin d'écrire un test unitaire pour une méthode privée, ou peut-être que je veux avoir accès à certains membre privé afin que je puisse plus facilement d'installation de l'état de l'objet, afin que je puisse le tester. Pour moi, cette aide en preservant l'encapsulation et d'abstraction, parce que je ne suis pas la modification du public ou protégé de l'interface de la classe.

Si j'achète une bibliothèque tierce, je ne voudrais pas que c'est l'interface publique d'être pollué avec un tas de méthodes publiques je n'ai pas besoin de savoir à propos de tout simplement parce que le vendeur voulait unité de test!

Je ne veux avoir à se soucier d'un tas de membres que je n'ai pas besoin de savoir si j'hérite d'une classe.

C'est pourquoi je dis qu'il préserve l'abstraction et d'encapsulation.

À mon nouveau travail, ils froncent les sourcils à l'encontre de l'aide de l'ami des classes de même pour les tests unitaires. Ils disent que, parce que la classe ne devrait pas "savoir" quoi que ce soit sur les tests et que vous ne voulez pas que le couplage de la classe et de son test.

Quelqu'un peut-il expliquer ces raisons, pour moi, plus afin que je puisse mieux comprendre? Je ne vois pas pourquoi à l'aide d'un ami pour les tests unitaires est mauvais.

71voto

bcat Points 5033

Idéalement, vous ne devriez pas besoin de test de l'unité méthodes privées à tous. Tous les consommateurs de la classe se soucient que de l'interface publique, de sorte que ce que vous devriez tester. Si une méthode privée a un bug, il faudrait le prendre un test unitaire qui appelle certaines méthode publique de la classe qui finalement finit par appeler le buggy méthode privée. Si un bug parvient à glisser, ce qui indique que votre cas de test ne pas refléter pleinement le contrat que vous souhaitez de votre classe à mettre en œuvre. La solution à ce problème est presque certainement pour tester les méthodes publiques avec plus d'attention, de ne pas avoir de vos cas de test de creuser dans la classe de détails de mise en œuvre.

Encore une fois, c'est le cas idéal. Dans le monde réel, les choses ne sont pas toujours si clair, et d'avoir une unité de test de la classe d'être un ami de la classe de tests peut être acceptable, voire souhaitable. Encore, ce n'est probablement pas quelque chose que vous voulez faire tout le temps. Si elle semble venir assez souvent, qui pourrait un signe que vos classes sont trop gros et/ou de réalisation du trop grand nombre de tâches. Si oui, encore subdiviser par refactoring ensembles complexes de méthodes privées dans des classes séparées, devrait contribuer à éliminer la nécessité pour les tests unitaires pour connaître les détails de l'implémentation.

15voto

Philipp Points 5308

Vous devez considérer qu'il y a différents styles et méthodes de test: la boîte Noire test ne teste que l'interface publique (traitement de la classe comme une boîte noire). Si vous avez une classe de base abstraite vous pouvez même utiliser les mêmes tests à l'encontre de tous vos implémentations.

Si vous utilisez des tests en boîte Blanche, vous pouvez même regarder les détails de la mise en œuvre. Pas seulement à propos de laquelle les méthodes d'une classe a, mais ce genre de déclarations conditionnelles sont inclus (par exemple, si vous voulez augmenter votre couverture de condition, car vous savez que les conditions étaient difficiles à code). Dans les tests en boîte blanche, vous avez certainement "haut de couplage" entre les classes/mise en œuvre et les tests qui est nécessaire parce que vous voulez tester la mise en œuvre et de ne pas l'interface.

Comme bcat l'a souligné, il est souvent utile d'utiliser la composition et plus, mais de plus petites classes au lieu de plusieurs méthodes privées. Cela simplifie les tests en boîte blanche, car vous pouvez spécifier plus facilement les cas de test pour obtenir une bonne couverture de test.

9voto

bjskishore123 Points 2471

Comme bcat suggéré, autant que possible, vous avez besoin de trouver des bugs à l'aide de l'interface publique elle-même. Mais si vous voulez faire les choses comme l'impression variables privées et en comparant avec le résultat attendu etc(Utile pour les développeurs de déboguer les problèmes facilement), alors vous pouvez faire UnitTest classe comme un ami de la classe à tester. Mais vous pouvez avoir besoin de l'ajouter dans une macro comme ci-dessous.

class Myclass
{
#if defined(UNIT_TEST)
    friend class UnitTest;
#endif
};

Activer le drapeau UNIT_TEST uniquement lorsque l'Unité de test est nécessaire. Pour les autres versions, vous devez désactiver cette option.

5voto

Dave K Points 39

Je ne vois aucun inconvénient à utiliser une classe de test unitaire ami dans de nombreux cas. Oui, il est parfois préférable de décomposer une classe nombreuse en classes plus petites. Je pense que les gens sont un peu trop hâtifs pour écarter l'utilisation du mot clé friend pour quelque chose comme ceci - ce n'est peut-être pas une conception idéale orientée objet, mais je peux sacrifier un peu d'idéalisme pour une meilleure couverture de test si c'est ce dont j'ai vraiment besoin.

1voto

Inverse Points 2228

En règle générale, vous ne testez que l'interface publique pour pouvoir modifier et repenser la mise en œuvre. L'ajout de cas de test pour les membres privés définit une exigence et une restriction sur l'implémentation de votre classe.

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