79 votes

Utilisez-vous TestInitialize ou le constructeur de la classe de test pour préparer chaque test ? et pourquoi ?

Cette question porte sur les tests unitaires dans Visual Studio à l'aide de MSTest (ce qui est important, en raison de l'utilité de MSTest). ordre d'exécution ). La méthode marquée [TestInitialize] et le constructeur de la classe de test seront exécutés avant chaque méthode de test.

La question est donc de savoir ce que vous avez tendance à faire dans chacun de ces domaines. Évitez-vous d'effectuer certaines activités dans l'un ou l'autre ? Quelle est votre raison : style, technique, superstition ?

65voto

Anthony Mastrean Points 8582

Le constructeur est juste une structure fournie par le langage. Chaque cadre de test semble avoir son propre cycle de vie contrôlé "initialize". Vous n'aurez probablement des problèmes qu'en utilisant le constructeur pour muter vos locals.

MSTest : Vous obtenez une toute nouvelle instance de la classe de test pour chaque TestMethod . Il s'agit peut-être du seul cas où il est possible de modifier les paramètres locaux dans le constructeur, l'initialisateur ou la méthode de test sans affecter les autres méthodes de test.

public class TestsForWhatever
{
    public TestsForWhatever()
    {
        // You get one of these per test method, yay!
    }

    [TestInitialize] 
    public void Initialize() 
    {
        // and one of these too! 
    }

    [TestMethod]
    public void AssertItDoesSomething() { }

    [TestMethod]
    public void AssertItDoesSomethingElse() { }
}

MSpec : Vous n'en avez qu'un seul. Establish y Because pour toutes vos affirmations ( It ). Donc, ne mutez pas vos locaux dans vos assertions. Et ne dépendez pas des mutations des locales dans les contextes de base (si vous les utilisez).

[Subject(typeof(Whatever))]
public class When_doing_whatever
{
    Establish context = () => 
    { 
        // one of these for all your Its
    };

    Because of = () => _subject.DoWhatever();

    It should_do_something;
    It should_do_something_else;
}

0 votes

J'avais le même problème et vous venez de fournir la bonne explication, merci !

7 votes

Vous pouvez également faire remarquer que [ClassInitialize] n'est exécuté qu'une fois par Test Run (avant le tout), il peut donc être utilisé pour toutes les routines de configuration coûteuses.

5 votes

-1 : Vous ne devriez pas détester votre question ; elle est très sensée, en fait. Voir, par exemple, xUnit.net il recommande d'utiliser le constructeur comme le site initialisateur de cas de test. Le fait d'être "juste une structure fournie par le langage" n'est pas une mince affaire ; quiconque écrit n'importe quel type de framework (y compris les frameworks de test) devrait no essayer de réinventer la roue, et utiliser plutôt des normes bien définies (comme, vous savez, utiliser des constructeurs pour initialiser des choses, etc.)

26voto

cyberSecurity Points 2233

Voici quelques avantages que j'ai trouvés avec TestInitialize.

  • Certaines variables d'environnement (par exemple TestContext) ne sont pas accessibles avant l'instanciation de la classe de test.
  • Peut exiger l'implémentation avec une classe dérivée en marquant une méthode de base TestInitialize abstraite.
  • Vous pouvez facilement surcharger une méthode TestInitialize de base et déterminer s'il faut appeler l'impl de base avant l'impl dérivé, après, ou pas du tout. En revanche, si vous dérivez une classe de test d'une classe de test de base, dans le cas d'un constructeur sans paramètre, le ctor de base sera appelé, que vous l'ayez voulu ou non.
  • Sa définition explicite rend les intentions claires, et complète la méthode TestCleanup. Vous pourriez argumenter que vous pouvez créer un destructeur pour chaque constructeur, mais il n'est pas garanti que MS Test gère les destructeurs comme vous le souhaitez.

2 votes

J'ai trouvé que MSTest fait exécuter un public void Dispose après chaque essai. Elle doit être publique, et peu importe si vous implémentez la méthode IDisposable : vous ne pouvez pas implémenter explicitement l'interface.

15voto

Romi Points 71

Le principal avantage d'utiliser soit TestInitialize() soit ClassInitialize() plutôt que l'instance de la classe de test ou les constructeurs statiques est sa nature explicite. Elle indique clairement que vous effectuez une certaine configuration avant vos tests. Le fait de le faire de manière cohérente devrait améliorer la maintenabilité à long terme.

12 votes

Je ne suis pas d'accord. Qu'est-ce qui pourrait être plus clair qu'un constructeur ? Bien sûr, vous devez savoir que vous obtenez une nouvelle instance de classe de test pour chaque test, mais c'est quelque chose que vous devez savoir de toute façon. Et ce n'est pas comme si TestInitialize est un nom si évident qu'il ne peut prêter à confusion : stackoverflow.com/questions/22999816/ .

4voto

Anthony Mastrean Points 8582

Je préfère utiliser le [TestInitialize] pour effectuer l'instanciation de l'objet testé et de ses paramètres. Je ne travaille dans le constructeur que s'il est nécessaire d'instancier une classe de base de test (ce qui est généralement le cas lorsque je crée ou rafraîchis des référentiels, etc.) Cela m'aide à garder le code du cadre de test et le code de test séparés logiquement et physiquement.

2voto

Patrick Desjardins Points 51478

L'objet que vous testez n'a pas besoin d'être instancié dans la méthode [TestInitialize]. Vous pouvez tester le constructeur de votre objet dans une méthode de test [Test].

L'objet dans le [TestInitialize] peut servir à configurer votre stockage de persistance ou à préparer la valeur que l'objet testé utilisera dans les tests.

2 votes

Je le sais. Vous pouvez instancier l'objet en ligne avec la déclaration si possible. Ma question est la suivante vous faire dans l'un ou l'autre de ces endroits. Et pourquoi ?

7 votes

Vous n'avez pas répondu à cette question dans votre réponse. Relisez la question.

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