2008-10-17 7 views
64

Die NUnit-Dokumentation sagt mir nicht, wann ich eine Methode mit einer verwenden soll und wann ich das Setup im Konstruktor machen soll.Wann verwende ich das TestFixtureSetUp-Attribut anstelle eines Standardkonstruktors?

public class MyTest 
{ 
    private MyClass myClass; 

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

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

Gibt es gute/schlechte Praktiken über die TestFixtureSetup im Vergleich zu Standard-Konstruktor oder nicht es einen Unterschied?

+0

Da dies immer eine häufig gestellte Frage ist, sollten Sie [this] (https://stackoverflow.com/a/4970076/908336) und [this] (https://stackoverflow.com/a/8689398/908336) (die gleichen Diskussionen für 'MSTest'). Aber hüte dich vor den Nebenwirkungen von Fixture Setups auf die Lesbarkeit der Tests (schau [hier] (http://jamesnewkirk.typepad.com/posts/2007/09/why-you-should-.html) und [hier] (https: //losechies.com/jimmybogard/2013/09/26/test-styles-and-avoiding-setupteardown/)). –

Antwort

13

Ich denke, das war eines der Probleme, die vom nUnit-Team nicht behandelt wurden. Jedoch gibt es die ausgezeichnete xUnit project, die dieses genaue Problem sah und entschied, dass Konstruktoren eine gute Sache waren, auf test fixture initialization zu verwenden.

Für nunit, meine beste Praxis in diesem Fall war die TestFixtureSetUp, TestFixtureTearDown, SetUp und TearDown Methoden zu verwenden, wie in der Dokumentation beschrieben.

Ich denke, es hilft mir auch, wenn ich nicht an ein nUnit Test Fixture als eine normale Klasse denke, obwohl Sie es mit diesem Konstrukt definieren. Ich denke an sie als Fixpunkte, und das bringt mich über die mentale Hürde und erlaubt mir, dieses Thema zu übersehen.

+0

Bitte beachten Sie, dass der [xUnit-Artikel] (https://xunit.github.io/docs/comparisons.html) darauf hinweist, dass 'Setups (wie auch Konstruktoren) im Allgemeinen eine schlechte Idee sind, die Testcode [schwierig zu machen folge] (http://jamesnewkirk.typepad.com/posts/2007/09/why-you-should-.html), NICHT diese Konstruktoren sind besser als die 'Setup's. Parameterlose Konstrukteure sind jedoch der letzte Ausweg für diejenigen, die sie wirklich brauchen. Siehe auch: [Test Stile und Vermeidung von Setup/Teardown] (https://losechies.com/jimmybogard/2013/09/26/test-styles-and-avoiding-setupteardown/) –

62

Warum sollten Sie einen Konstruktor in Ihren Testklassen verwenden?

Ich benutze [SetUp] und [TearDown] markierte Methoden für Code vor und nach jedem Test ausgeführt werden, und in ähnlicher Weise [TestFixtureSetUp] und [TestFixtureTearDown] markierte Methoden zur Code nur einmal ausgeführt werden, bevor und nachdem alle Tests in der Vorrichtung ausgeführt wurden.

Ich denke, Sie könnten wahrscheinlich die [TestFixtureSetUp] für einen Konstruktor ersetzen (obwohl ich es noch nicht versucht habe), aber das scheint nur von der klaren Konvention zu brechen, die die markierten Methoden bieten.

+4

Ich hatte keine Ahnung, warum ich einen Konstruktor brauche, aber ich habe auch keine Ahnung, warum ich ein TestFixtureSetUp brauche. Ich weiß über die Setup-, Teardown- und Testfilltextteardown-Attribute. Ich kenne nur nicht den Unterschied zwischen dem Konstruktor und testfixturesetup Attribut. – Paco

+3

Nur um Ihre Frage zu beantworten. Sie müssen einen Konstruktor in Ihren Testklassen verwenden, wenn Sie Testadapter parametriert haben. –

9

Ich habe mich oft gefragt, was die Notwendigkeit für [TestFixtureSetUp] war, da es ein einfaches, gut verstandenes Konstrukt der ersten Klasse gibt, das genau dasselbe tut.

Meine Präferenz besteht darin, Konstruktoren zu verwenden, um das Readonly-Schlüsselwort zu nutzen, das sicherstellt, dass Mitgliedsvariablen nicht reinitialisiert werden können.

+4

Das readonly-Schlüsselwort stellt nicht sicher, dass a Mitglied wird nicht geändert. Wenn das Mitglied eine Klasse ist, kann der interne Zustand der Klasse in einem Test geändert werden, und dieser Zustand wird auf die nächste Testmethode übertragen (da die Einheit die Klasse nicht zwischen jedem Testlauf neu erstellt) – Pete

2

Ich denke, ich habe eine negative gute Antwort - der Grund, einen Konstruktor anstelle des Attributs zu verwenden, ist, wenn Sie eine Vererbung zwischen Testklassen haben.

Es wird nur eine mit [TestFixtureSetup] annotierte Methode aufgerufen (nur in der konkreten Klasse), die anderen Fixture-Initialisierer jedoch nicht. In diesem Fall würde ich lieber die Initialisierung in den Konstruktor setzen, der eine wohldefinierte Semantik für die Vererbung hat :)

+2

Dies hat sich seit dem geändert NUnit 2.5 Nun werden alle mit [TestFixtureSetup] annotierten Methoden aufgerufen. –

12

Eine Sache, die Sie nicht mit [TestFixtureSetup] tun können, die Sie im Konstruktor tun können, sind die Parameter von erhalten [TestFixture].

Wenn Sie Ihre Testvorrichtung parametrieren möchten, müssen Sie den Konstruktor für mindestens einige des Setups verwenden. Bisher habe ich dies nur für Integrationstests verwendet, z. eine Datenzugriffsschicht mit mehreren Datenanbietern für die Prüfung:

[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) 
    { 
     ... 
    } 
} 
8

Es ist der Unterschied zwischen Konstrukteur und Verfahren mit [TestFixtureSetUp] Attributen gekennzeichnet.Laut NUnit-Dokumentation:

Es ist ratsam, dass der Konstruktor keine Nebenwirkungen hat, da NUnit das Objekt im Laufe einer Sitzung mehrmals konstruieren kann.

Wenn Sie eine teure Initialisierung haben, ist es besser, TestFixtureSetUp zu verwenden.

+1

Dies setzt voraus, dass die mit TestFixtureSetUp markierte Methode statisch ist. Andernfalls wäre es für den Konstruktor unmöglich, öfter aufgerufen zu werden, wenn die Testinstanz nicht von NUnit verwendet wird, was ich bezweifle. – jpierson

-2

Der Konstruktor und die SetUp Methoden werden unterschiedlich verwendet:
Der Konstruktor wird nur einmal ausgeführt.
Die Methoden SetUp werden jedoch mehrmals ausgeführt, bevor jeder Testfall ausgeführt wird.

+1

Sie beziehen sich auf '[SetUp]', während sich das OP auf '[TestFixtureSetUp]' bezieht. – onedaywhen

2

[TestFixtureSetUp] und [TestFixtureTearDown] sind für die gesamte Testklasse. Läuft nur einmal.

[SetUp] und [TearDown] sind für jede Testmethode (Test). läuft für jeden Test.

1

Ein wichtiger Unterschied zwischen Konstruktor und TestFixtureSetUp ist, dass in NUnit 2 zumindest Konstruktorcode tatsächlich auf Test Enumeration ausgeführt wird, nicht nur Testlauf, also im Grunde möchten Sie ctor Code zu nur readonly befüllen, dh Parameter, Werte. Alles, was Nebenwirkungen oder tatsächliche Arbeit verursacht, muss entweder in einen Lazy gewickelt oder in der TestFixtureSetUp/OneTimeSetUp erledigt werden. Sie können sich den Konstruktor also nur als einen Ort zum Konfigurieren des Tests vorstellen. Während das TestFixtureSetUp das Testgerät ist, wird der erforderliche Anfangszustand des Systems vor dem Test initialisiert.

Verwandte Themen