526 votes

Meilleures pratiques avec les classes abstraites de tests unitaires ?

Je me demandais quelle est la meilleure pratique pour les tests unitaires des classes abstraites et des classes qui étendent les classes abstraites.

Dois-je tester la classe abstraite en l'étendant, déraciner les méthodes abstraites, puis de tester toutes les méthodes concrètes? Puis tester les méthodes que j'remplacer, et de tester les méthodes abstraites dans les tests unitaires pour les objets qui s'étendent de ma classe abstraite.

Dois-je avoir un cas de test abstrait qui peut être utilisé pour tester les méthodes de la classe abstraite, et d'étendre cette classe dans mon cas de test pour les objets d'étendre la classe abstraite?

Notez que ma classe abstraite a certaines méthodes concrètes.

Je serais intéressé de voir ce que les gens utilisent.

527voto

Nigel Thorne Points 6412

Il y a deux façons dans lequel les classes de base abstraites sont utilisés.

  1. Vous êtes spécialisé votre objet abstrait, mais tous les clients peuvent utiliser la classe dérivée par le biais de son interface de base.

  2. Vous utilisez une classe de base abstraite pour le facteur de répétition à l'intérieur des objets dans votre dessin, et des clients utilisent des implémentations concrètes par le biais de leurs propres interfaces.!


Solution 1 - Modèle De Stratégie

Option1

Si vous avez de la première situation, alors vous avez réellement besoin d'une interface définie par les méthodes virtuelles dans la classe abstraite que vos classes dérivées sont à mettre en œuvre.

Vous devriez envisager d'en faire une véritable interface, changer votre classe abstraite pour être concret, et de prendre une instance de cette interface dans son constructeur. Vos classes dérivées deviennent alors les implémentations de cette nouvelle interface.

IMotor

Cela signifie que vous pouvez maintenant tester vos précédemment classe abstraite à l'aide d'une maquette instance de la nouvelle interface, et chaque nouvelle mise en œuvre, par le biais de la désormais interface publique. Tout est simple et vérifiable.


Solution 2

Si vous avez la seconde situation, votre classe abstraite est une classe d'assistance.

AbstractHelper

Jetez un oeil à la fonctionnalité qu'il contient. Voir si elle peut être poussée sur les objets qui sont manipulés afin de minimiser cette duplication. Si vous avez encore quelque chose à gauche, regard à en faire une classe helper que votre mise en œuvre concrète de prendre dans leur constructeur et de suppression de ses de la classe de base.

Motor Helper

Cela entraîne encore pour les classes de béton, qui sont simples et facilement vérifiables.


En Règle générale

Faveur réseau complexe de simples objets sur un simple réseau d'objets complexes.

La clé extensible de code de tests est petits blocs de construction et indépendant de câblage.


Mise à jour : Comment gérer les mélanges des deux?

Il est possible d'avoir une classe de base réaliser les deux de ces rôles... c'est à dire: il a une interface publique, et a protégé méthodes d'aide. Si c'est le cas, alors vous pouvez factoriser l'aide de méthodes dans une classe (scénario 2), et de convertir de l'arbre d'héritage dans un modèle de stratégie.

Si vous trouvez que vous avez certaines méthodes de votre classe de base met en œuvre directement et d'autres sont virtuels, alors vous pouvez toujours convertir l'arbre d'héritage dans un modèle de stratégie, mais je voudrais aussi le prendre comme un bon indicateur que les responsabilités ne sont pas correctement alignés, et peut-être besoin d'un refactoring.


Mise à jour 2 : les Classes Abstraites comme d'un tremplin (2014/06/12)

J'ai eu une situation à l'autre jour où j'ai utilisé abstrait, donc j'aimerais explorer pourquoi.

Nous avons un format standard pour nos fichiers de configuration. Cet outil a 3 fichiers de configuration de tous dans ce format. Je voulais une classe fortement typée pour chaque paramètre du fichier de sorte, par le biais de l'injection de dépendance, une classe pourrait demander pour les réglages, il se souciait.

Je l'ai fait en ayant une classe de base abstraite qui sait comment analyser les paramètres des formats de fichiers et les classes dérivées qui a exposé ces mêmes méthodes, mais encapsulée l'emplacement du fichier de paramètres.

Je pourrais avoir écrit "un SettingsFileParser" que les 3 classes enveloppé, puis délégué par le biais de la classe de base afin d'exposer les méthodes d'accès aux données. J'ai choisi de ne pas le faire encore car elle conduirait à 3 classes dérivées avec plus de délégation de code en eux qu'autre chose.

Cependant... que ce code évolue, et les consommateurs de chacun de ces paramètres de classes deviennent plus claires. Chacun des paramètres utilisateurs demander de certains paramètres et de les transformer en quelque sorte (comme les paramètres de texte, ils peuvent enveloppez-les dans des objets, de les convertir en nombres, etc.). Comme cela arrive, je vais commencer à extraire de cette logique dans la manipulation des données méthodes et les pousser à l'arrière sur la fortement typé paramètres de classes. Cela conduira à un plus haut niveau de l'interface pour chaque jeu de paramètres, c'est finalement pas plus au courant il s'agit de "paramètres".

À ce stade, la fortement typé paramètres de classes n'aurez plus besoin de le "getter" méthodes qui exposent le sous-jacent "paramètres" de la mise en œuvre.

À ce point, je ne veux plus de leur interface publique pour inclure les paramètres des méthodes accesseur; je vais donc changer cette classe d'encapsuler un des paramètres de l'analyseur de classe au lieu de tirer.

La classe Abstraite est donc: pour moi un moyen d'éviter de délégation de code pour le moment, et d'un marqueur dans le code pour me rappeler de changer la conception plus tard. J'ai peut-être jamais, de sorte qu'il peut vivre un bon moment... seul le code peut dire.

J'ai trouver que cela est vrai avec une règle... comme "pas de méthodes statiques" ou "pas de méthodes privées". Ils indiquent une odeur dans le code... et c'est bon. Il vous permet de rester à la recherche de l'abstraction que vous avez manqué... et vous permet d'effectuer sur la fourniture de valeur à votre client dans le temps de le dire.

J'imagine que les règles comme celle de la définition d'un paysage, où maintenable code de vie dans les vallées. Lorsque vous ajoutez de nouveaux comportements, c'est comme la pluie d'atterrissage sur votre code. Au départ, vous la mettre là où il atterrit.. alors vous refactoriser le code pour autoriser les forces de la bonne conception de pousser le comportement autour jusqu'à ce que tout se termine dans les vallées.

287voto

Patrick Desjardins Points 51478

Écrire un objet simulacre et utilisez-les seulement pour les tests. Ils sont généralement très très très minimes (héritent de la classe abstraite) et pas plus. Ensuite, dans votre Test unitaire, vous pouvez appeler la méthode abstraite que vous souhaitez tester.

Vous devez tester la classe abstraite qui contiennent une logique comme toutes les autres classes que vous avez.

12voto

Mnementh Points 19831

Ce que je fais pour les classes abstraites et interfaces est le suivant : J’ai passer un test, qui utilise l’objet tel qu’il est concret. Mais la variable de type X (X représente la classe abstraite) n’est pas définie dans le test. Cette classe de test n’est pas ajoutée à la suite de tests, mais des sous-classes de celui-ci, de disposent d’une méthode d’installation-qui a défini la variable à une implémentation concrète de X. De cette façon je ne duplique le code de test. Les sous-classes du test ne sont pas utilisé peuvent ajouter plusieurs méthodes de contrôle si nécessaire.

9voto

Seth Petry-Johnson Points 5709

Si votre classe abstraite contient béton fonctionnalité qui a la valeur de l'entreprise, alors en général, je vais le tester directement par la création d'un essai de double que les talons de l'abstrait de données, ou à l'aide d'un moqueur cadre pour le faire pour moi. Qui je choisir dépend de si j'ai besoin d'écrire tester les implémentations spécifiques des méthodes abstraites ou non.

Le scénario le plus commun dans lequel j'ai besoin de le faire c'est quand je suis en utilisant la Méthode de Modèle de modèle, comme quand je suis en train de construire une sorte de cadre extensible qui sera utilisé par une 3ème partie. Dans ce cas, la classe abstraite est ce qui définit l'algorithme que je veux tester, de sorte qu'il est plus judicieux de tester le résumé d'une mise en œuvre spécifique.

Cependant, je pense qu'il est important que ces tests devraient se concentrer sur des implémentations concrètes de véritable logique d'entreprise uniquement; vous ne devriez pas le test de l'unité des détails de l'implémentation de la classe abstraite parce que vous vous retrouverez avec cassants tests.

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