Question

J'ai une classe dans laquelle je suis en train de tester avec DUnit. Il a un certain nombre de méthodes dont des méthodes publiques et des méthodes privées.

type
  TAuth = class(TDataModule)
  private
    procedure PrivateMethod;
  public
    procedure PublicMethod;
  end;

Pour écrire un test unitaire pour cette classe, je dois rendre toutes les méthodes publiques.

Existe-t-il un moyen différent de déclarer les méthodes privées afin que je puisse toujours les tester mais elles ne sont pas publiques?

Était-ce utile?

La solution

Vous n'avez pas besoin de les rendre publics. Protégé va faire. Ensuite, vous pouvez sous-taper la classe pour le test unitaire et afficher les méthodes protégées. Exemple:

type
  TAuth = class(TDataModule)
  protected
    procedure MethodIWantToUnitTest;
  public
    procedure PublicMethod;
  end;

Vous pouvez maintenant le sous-taper pour votre test unitaire:

interface

uses
  TestFramework, Classes, AuthDM;

type
  // Test methods for class TAuthDM
  TestAuthDM = class(TTestCase)
     // stuff
  end;

  TAuthDMTester = class(TAuthDM)
  public
    procedure MethodIWantToUnitTestMadePublic;
  end;

implementation

procedure TAuthDMTester.MethodIWantToUnitTestMadePublic;
begin
  MethodIWantToUnitTest;
end;

Toutefois, si les méthodes que vous souhaitez tester unitairement effectuent des opérations si intimement liées au module de données qu'il n'est pas sûr de les utiliser autrement que de manière privée, vous devez vraiment envisager de refactoriser les méthodes afin de séparer le code nécessaire. à tester et le code qui accède aux entrailles du module de données.

Autres conseils

C’est un peu hacky, mais je pense que c’est l’approche la plus simple et la plus claire. Utilisez cette directive de compilation conditionnelle:

  {$IfNDef TEST}
  private
  {$EndIf}

Votre projet de test unitaire doit définir TEST dans projet & # 8594; conditionnel définit . Sans spécification de visibilité, ils sont publiés.

Attention: si la visibilité privée n’est pas la première de la déclaration de classe, elle aura la définition précédente. Une manière plus sûre, mais plus verbeuse et moins claire, serait:

  private
  {$IfDef TEST}
  public
  {$EndIf}

Cela présente de nombreux avantages par rapport au sous-classement ou à d’autres approches:

  • Aucune complexité supplémentaire: pas de classes supplémentaires dans votre code.
  • Personne ne peut "faire une erreur". sous-classe et remplacez votre classe: vous conservez votre architecture.
  • Lorsque vous dites qu'une méthode est protégée, vous vous attendez un peu à ce qu'elle soit remplacée. Vous dites ceci pour qui lit votre code. Une méthode protégée qui ne doit pas être remplacée confondra vos lecteurs de code, ce qui violera mon premier principe de programmation: "Le code doit être écrit pour être lu par d'autres êtres humains."
  • DUnit est dans sa propre unité, non incluse partout.
  • Vous ne touchez pas RTTI en désordre.

Je pense que c'est une solution plus claire et meilleure que la réponse choisie.

Lorsque je l'utilise, je configure également le projet de test pour qu'il mette les objets de construction dans un autre répertoire du projet principal. Ceci empêche les fichiers binaires avec la directive TEST de se mélanger avec l’autre code.

Je recommande les " modèles de test XUnit " livre de Gerard Meszaros:

sous-classe spécifique au test

  

Question : Comment créer du code?   testable lorsque nous avons besoin d'accéder   état privé du SUT?

     

Réponse : ajoutez des méthodes exposant le   état ou comportement requis par le test   dans une sous-classe de SUT.

     

... Si le système testé (SUT) n'était pas   conçu spécifiquement pour être testable,   nous pouvons trouver que le test ne peut pas obtenir   accès à déclarer qu'il doit   initialiser ou vérifier à un moment donné   le test.

L'article explique également quand l'utiliser et quels risques il comporte.

Mettez le code DUnit dans votre unité. Vous pouvez ensuite accéder à tout ce que vous voulez.

En général, lorsque je me retrouve dans cette situation, je me rends souvent compte que je viole le principe de responsabilité unique. Bien sûr, je ne connais rien à votre cas particulier, mais PEUT-ÊTRE, que les méthodes privées doivent être dans leur propre classe. Le TAuth aurait alors une référence à cette nouvelle classe dans sa section privée.

Avec RTTI étendu (Delphi 2010 et versions ultérieures), l’appel de méthodes privées via RTTI est une autre option. Cette solution est également la réponse la mieux notée dans Comment tester une classe contenant des méthodes privées, des champs ou des classes internes?

{$IFNDEF UNITEST}
private
{$ENDIF}

Solution simple, qui est à peine un hack. J'ai souvent besoin de tester des méthodes privées et cette technique ajoute le moins de complications possible.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top