web-dev-qa-db-fra.com

Quand dois-je utiliser l'attribut TestFixtureSetUp au lieu d'un constructeur par défaut?

La documentation NUnit ne me dit pas quand utiliser une méthode avec un TestFixtureSetup et quand faire la configuration dans le constructeur.

public class MyTest
{
    private MyClass myClass;

    public MyTest()
    {
        myClass = new MyClass();
    }

    [TestFixtureSetUp]
    public void Init()
    {
        myClass = new MyClass();
    }
}

Existe-t-il des bonnes/mauvaises pratiques concernant le constructeur TestFixtureSetup par rapport au constructeur par défaut ou n'y a-t-il aucune différence?

68
Paco

Je pense que cela a été l'un des problèmes qui n'ont pas été abordés par l'équipe nUnit. Cependant, il y a l'excellent projet xUnit qui a vu ce problème exact et a décidé que les constructeurs étaient une bonne chose à utiliser sur initialisation du luminaire de test .

Pour nunit, ma meilleure pratique dans ce cas a été d'utiliser les méthodes TestFixtureSetUp, TestFixtureTearDown, SetUp et TearDown comme décrit dans la documentation.

Je pense que cela m'aide également lorsque je ne considère pas un appareil de test nUnit comme une classe normale, même si vous le définissez avec cette construction. Je les considère comme des appareils, et cela me permet de surmonter l'obstacle mental et me permet d'ignorer ce problème.

15
casademora

Pourquoi auriez-vous besoin d'utiliser un constructeur dans vos classes de test?

J'utilise [SetUp] et [TearDown] méthodes marquées pour le code à exécuter avant et après chaque test, et de même [TestFixtureSetUp] et [TestFixtureTearDown] méthodes marquées pour que le code ne soit exécuté qu'une seule fois avant et après l'exécution de tous les tests dans le luminaire.

Je suppose que vous pourriez probablement remplacer le [TestFixtureSetUp] pour un constructeur (même si je n'ai pas essayé), mais cela ne semble rompre avec la convention claire que les méthodes marquées fournissent.

64
Sam Wessel

Une chose que vous ne pouvez pas faire avec [TestFixtureSetup] que vous pouvez faire dans le constructeur est de recevoir les paramètres du [TestFixture].

Si vous souhaitez paramétrer votre appareil de test, vous devrez utiliser le constructeur pour au moins certains de la configuration. Jusqu'à présent, je ne l'ai utilisé que pour les tests d'intégration, par exemple pour tester une couche d'accès aux données avec plusieurs fournisseurs de données:

[TestFixture("System.Data.SqlClient",
  "Server=(local)\\SQLEXPRESS;Initial Catalog=MyTestDatabase;Integrated Security=True;Pooling=False"))]
[TestFixture("System.Data.SQLite", "Data Source=MyTestDatabase.s3db")])]
internal class MyDataAccessLayerIntegrationTests
{
    MyDataAccessLayerIntegrationTests(
        string dataProvider,
        string connectionString)
    {
        ...
    }
}
12
Ergwun

Je me suis souvent demandé quel était le besoin de [TestFixtureSetUp] était, étant donné qu'il existe une construction de langage de première classe simple et bien comprise qui fait exactement la même chose.

Ma préférence est d'utiliser des constructeurs, pour tirer parti du mot clé readonly en veillant à ce que les variables membres ne puissent pas être réinitialisées.

9
David Chapman

Il existe une différence entre le constructeur et la méthode marquée par [TestFixtureSetUp] attribut. Selon la documentation NUnit:

Il est conseillé que le constructeur n'ait aucun effet secondaire, car NUnit peut construire l'objet plusieurs fois au cours d'une session.

Donc, si vous avez une initialisation coûteuse, il vaut mieux utiliser TestFixtureSetUp.

9
oderibas

[TestFixtureSetUp] et [TestFixtureTearDown] sont pour toute la classe de test. ne fonctionne qu'une seule fois.

[SetUp] et [TearDown] sont pour chaque méthode de test (test). fonctionne pour chaque test.

4
Shankar

Une différence importante entre le constructeur et TestFixtureSetUp est que, dans NUnit 2 au moins, le code du constructeur est en fait exécuté lors de l'énumération des tests, pas seulement du test en cours d'exécution, donc vous voulez essentiellement limiter le code ctor à ne remplir que les valeurs en lecture seule, c'est-à-dire les paramètres. Tout ce qui provoque des effets secondaires ou fait un travail réel doit être enveloppé dans un Lazy ou fait dans le TestFixtureSetUp/OneTimeSetUp. Ainsi, vous pouvez considérer le constructeur uniquement comme un endroit pour configurer le test. Alors que TestFixtureSetUp est l'endroit où le dispositif de test, l'état initial requis du système avant l'exécution des tests, est initialisé.

3
Novaterata

Je pense avoir une bonne réponse négative - la raison d'utiliser un constructeur au lieu de l'attribut est lorsque vous avez un héritage entre les classes de test.

Une seule méthode annotée avec [TestFixtureSetup] sera appelé (sur la classe concrète uniquement), mais pas les autres initialiseurs de fixture. Dans ce cas, je préfère mettre l'initialisation dans le constructeur, qui a une sémantique bien définie pour l'héritage :)

2
ripper234