Question

Je me demande comment utiliser correctement NUnit. J'ai d'abord créé un projet-test distinct qui utilise mon projet principal comme référence. Mais dans ce cas, je ne suis pas en mesure de tester des méthodes privées. J'imagine que je dois inclure mon code de test dans mon code principal?! - Cela ne semble pas être la bonne façon de le faire. (Je n'aime pas l'idée de code d'expédition contenant des tests.)

Comment testez-vous les méthodes privées avec NUnit?

Était-ce utile?

La solution

En règle générale, le test unitaire concerne l'interface publique d'une classe, sur le principe que l'implémentation est immatérielle, tant que les résultats sont corrects du point de vue du client.

NUnit ne fournit donc aucun mécanisme pour tester les membres non publics.

Autres conseils

Bien que je convienne que les tests unitaires doivent être principalement axés sur l'interface publique, vous obtenez une impression beaucoup plus détaillée de votre code si vous testez également des méthodes privées. Le framework de test MS permet cela via l'utilisation de PrivateObject et de PrivateType, contrairement à NUnit Ce que je fais à la place est:

private MethodInfo GetMethod(string methodName)
{
    if (string.IsNullOrWhiteSpace(methodName))
        Assert.Fail("methodName cannot be null or whitespace");

    var method = this.objectUnderTest.GetType()
        .GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);

    if (method == null)
        Assert.Fail(string.Format("{0} method not found", methodName));

    return method;
}

De cette façon, vous n’aurez pas à compromettre l’encapsulation pour la tester. N'oubliez pas que vous devez modifier vos BindingFlags si vous souhaitez tester des méthodes statiques privées. L'exemple ci-dessus concerne uniquement les méthodes d'instance.

Un modèle courant pour l'écriture de tests unitaires consiste à tester uniquement les méthodes publiques.

Si vous souhaitez tester de nombreuses méthodes privées, vous devez normalement refactoriser votre code.

Il serait faux de rendre ces méthodes publiques sur la classe où elles habitent actuellement. Cela romprait le contrat que vous souhaitez attribuer à cette classe.

Il peut être correct de les transférer dans une classe d’aide et de les rendre publics. Cette classe ne peut pas être exposée par votre API.

Ainsi, le code de test n'est jamais mélangé avec votre code public.

Un problème similaire est le test des classes privées, par exemple. les classes que vous n'exportez pas de votre assemblage. Dans ce cas, vous pouvez explicitement faire de votre assemblage de code de test un ami de l'assemblage de code de production à l'aide de l'attribut InternalsVisibleTo.

Il est possible de tester des méthodes privées en déclarant votre assembly de test en tant qu'assembly ami de l'assembly cible que vous testez. Voir le lien ci-dessous pour plus de détails:

http://msdn.microsoft.com/en-us/library/ 0tke9fxk.aspx

Ceci peut être utile car il sépare généralement votre code de test de votre code de production. Je n'ai jamais utilisé cette méthode moi-même, car je n'en ai jamais trouvé le besoin. Je suppose que vous pouvez l'utiliser pour essayer de tester des cas de test extrêmes que vous ne pouvez tout simplement pas répliquer dans votre environnement de test pour voir comment votre code le gère.

Comme cela a été dit, vous ne devriez vraiment pas avoir besoin de tester les méthodes privées. Plus que probablement, vous voulez reformuler votre code en blocs de construction plus petits. Une astuce qui peut vous aider lorsque vous venez de refactoriser est d'essayer de réfléchir au domaine auquel votre système est lié et aux objets "réels" qui habitent ce domaine. Vos objets / classes dans votre système doivent se rapporter directement à un objet réel, ce qui vous permettra d’isoler le comportement exact que doit contenir l’objet et de limiter les responsabilités de cet objet. Cela signifie que vous effectuez une refactorisation logique plutôt que de simplement permettre de tester une méthode particulière; vous pourrez tester le comportement des objets.

Si vous ressentez toujours le besoin de tester interne, vous pouvez également envisager de vous moquer de vos tests car vous voudrez probablement vous concentrer sur un élément de code. Le mocking est l'endroit où vous injectez des dépendances d'objets, mais les objets injectés ne sont pas des objets "réels" ou de production. Ce sont des objets factices avec un comportement codé en dur pour faciliter l’isolement des erreurs de comportement. Rhino.Mocks est un framework de moquage gratuit et populaire qui va essentiellement écrire les objets pour vous. TypeMock.NET (un produit commercial avec une édition communautaire disponible) est un framework plus puissant qui peut se moquer des objets CLR. Très utile pour se moquer des classes SqlConnection / SqlCommand et Datatable, par exemple lors du test d’une application de base de données.

J'espère que cette réponse vous donnera un peu plus d'informations pour vous informer sur les tests unitaires en général et vous aidera à obtenir de meilleurs résultats à partir des tests unitaires.

Je suis favorable à la possibilité de tester des méthodes privées. Lorsque xUnit a démarré, il était destiné à tester les fonctionnalités après l'écriture du code. Tester l'interface est suffisant à cet effet.

Les tests unitaires ont évolué vers un développement piloté par les tests. Avoir la possibilité de tester toutes les méthodes est utile pour cette application.

L'objectif principal des tests unitaires est de tester les méthodes publiques d'une classe. Ces méthodes publiques utiliseront ces méthodes privées. Les tests unitaires testeront le comportement de ce qui est publiquement disponible.

Cette question en est à un âge avancé, mais je pensais partager ma façon de le faire.

En gros, toutes mes classes de test d'unité sont contenues dans l'assemblage qu'ils testent dans un espace de noms 'UnitTest' situé sous la valeur 'par défaut' de cet assemblage. Chaque fichier de test est encapsulé dans un:

#if DEBUG

...test code...

#endif

block, et tout cela signifie que a) il n'est pas distribué dans une version et b) je peux utiliser les déclarations de niveau interne / Friend sans effectuer de sauts de boucle.

L’autre chose que cela propose, plus pertinente pour cette question, est l’utilisation des classes partial , qui peuvent être utilisées pour créer un proxy pour tester des méthodes privées, par exemple pour tester quelque chose comme un méthode privée qui renvoie une valeur entière:

public partial class TheClassBeingTested
{
    private int TheMethodToBeTested() { return -1; }
}

dans les classes principales de l'assemblage et dans la classe de test:

#if DEBUG

using NUnit.Framework;

public partial class TheClassBeingTested
{
    internal int NUnit_TheMethodToBeTested()
    {
        return TheMethodToBeTested();
    }
}

[TestFixture]
public class ClassTests
{
    [Test]
    public void TestMethod()
    {
        var tc = new TheClassBeingTested();
        Assert.That(tc.NUnit_TheMethodToBeTested(), Is.EqualTo(-1));
    }
}

#endif

Évidemment, vous devez vous assurer que vous n’utilisez pas cette méthode lors du développement, bien que la construction de la version Release indique bientôt un appel accidentel à cette méthode si vous le faites.

Veuillez nous excuser si cela ne répond pas à la question, mais des solutions telles que l’utilisation de la réflexion, des instructions #if #endif ou la visualisation de méthodes privées ne résolvent pas le problème. Il peut y avoir plusieurs raisons de ne pas rendre visibles les méthodes privées ... qu’il s’agisse s’il s’agit d’un code de production et que l’équipe écrit par exemple rétrospectivement des tests unitaires.

Pour le projet sur lequel je travaille, seul MSTest semble (malheureusement) avoir un moyen, en utilisant des accesseurs, de tester des méthodes privées.

Vous ne testez pas les fonctions privées. Il existe des moyens d'utiliser la réflexion pour entrer dans des méthodes et des propriétés privées. Mais ce n’est pas vraiment facile et je décourage vivement cette pratique.

Vous ne devriez tout simplement pas tester quoi que ce soit qui ne soit pas public.

Si vous disposez de certaines méthodes et propriétés internes, vous devez envisager de le rendre public ou d'envoyer vos tests avec l'application (quelque chose que je ne vois pas vraiment comme un problème).

Si votre client est capable d'exécuter une suite de tests et de constater que le code que vous avez fourni fonctionne réellement, je ne vois pas cela comme un problème (tant que vous ne cédez pas votre adresse IP). ce). Les éléments que j'inclus dans chaque version sont les rapports de test et les rapports de couverture de code.

Vous pouvez rendre vos méthodes protégées en interne, puis en utilisant assembly: InternalVisibleTo ("NAMESPACE")  à votre espace de noms de test.

Par conséquent, NON! Vous ne pouvez pas accéder aux méthodes privées, mais il s'agit d'une solution de contournement.

En théorie, les tests unitaires ne doivent porter que sur les contrats. c'est-à-dire uniquement les membres publics de la classe. Mais dans la pratique, le développeur souhaite généralement tester les membres internes. - et c'est pas mal. Oui, cela va à l’encontre de la théorie, mais dans la pratique, cela peut parfois être utile.

Si vous voulez vraiment tester les membres internes, vous pouvez utiliser l'une de ces approches:

  1. Rendez votre membre public. Dans de nombreux livres, les auteurs suggèrent ceci approche aussi simple
  2. Vous pouvez rendre vos membres internes et ajouter InternalVisibleTo to aussi
  3. Vous pouvez protéger les membres de la classe et hériter de votre classe de test de votre classe sous test.

Exemple de code (pseudo-code):

public class SomeClass
{
    protected int SomeMethod() {}
}
[TestFixture]
public class TestClass : SomeClass{

    protected void SomeMethod2() {}
    [Test]
    public void SomeMethodTest() { SomeMethod2(); }
}

Je rendrais visible le package de méthodes privées. De cette façon, vous le garderez raisonnablement privé tout en pouvant tester ces méthodes. Je ne suis pas d'accord avec les gens qui disent que les interfaces publiques sont les seules à être testées. Il existe souvent dans les méthodes privées un code vraiment critique qui ne peut pas être correctement testé en passant uniquement par les interfaces externes.

Donc, cela revient vraiment à dire si vous vous souciez davantage du code correct ou de la dissimulation d’informations. Je dirais que la visibilité du paquet est un bon compromis car pour accéder à cette méthode, il faudrait que quelqu'un place sa classe dans votre paquet. Cela devrait vraiment les inciter à réfléchir à deux fois s’il s’agit là d’une chose vraiment intelligente à faire.

Je suis un gars de Java, donc la visibilité d'un paquet peut être appelée quelque chose de complètement différent en C #. Autant dire que c'est lorsque deux classes doivent être dans le même espace de noms pour pouvoir accéder à ces méthodes.

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