it-swarm.com.de

Verwenden Sie TestInitialize oder den Testklassenkonstruktor, um jeden Test vorzubereiten? und warum?

Diese Frage bezieht sich auf Komponententests in Visual Studio mit MSTest (dies ist wegen der MSTest Ausführungsreihenfolge wichtig). Sowohl die als [TestInitialize] markierte Methode als auch der Testklassenkonstruktor werden vor jeder Testmethode ausgeführt.

Die Frage ist also, was machen Sie in jedem dieser Bereiche? Vermeiden Sie bestimmte Aktivitäten in beiden Bereichen? Was ist dein Grund: Stil, Technik, Aberglaube?

59

Der Konstruktor ist nur eine von der Sprache bereitgestellte Struktur. Jedes Test-Framework scheint seinen eigenen kontrollierten Lebenszyklus zu "initialisieren". Sie werden wahrscheinlich nur in Schwierigkeiten geraten, wenn Sie den Konstruktor verwenden, um Ihre Ortsansässigen zu mutieren.

MSTest: Für jede TestMethod erhalten Sie eine komplett neue Instanz der Testklasse. Dies kann der einzige Fall sein, in dem es in Ordnung ist, die lokalen Variablen im Konstruktor, Initialisierer oder in der Testmethode zu mutieren und die anderen Testmethoden nicht zu beeinflussen.

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: Sie erhalten nur eine Establish und Because für alle Ihre Aussagen (It). Mutieren Sie also nicht Ihre Einheimischen in Ihren Behauptungen. Verlassen Sie sich nicht auf Mutationen von Ortsansässigen in Basiskontexten (wenn Sie diese verwenden).

[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;
}
49

Hier sind einige Vorteile, die ich mit TestInitialize gefunden habe.

  • Auf einige Umgebungsvariablen (z. B. TestContext) kann erst zugegriffen werden, nachdem die Testklasse instanziiert wurde.
  • Kann die Implementierung mit einer abgeleiteten Klasse erfordern, indem ein Basistext der TestInitialize-Methode markiert wird.
  • Kann eine TestInitialize-Basismethode leicht überschreiben und bestimmen, ob das Base-Impl vor dem abgeleiteten Impl, after oder überhaupt aufgerufen werden soll. Wenn Sie dagegen eine Testklasse von einer Basistestklasse ableiten, wird im Falle eines parameterlosen Konstruktors der Basis-Ctor aufgerufen, ob Sie dies beabsichtigt haben oder nicht. 
  • Ihre explizite Definition macht die Absichten klar und ergänzt die TestCleanup-Methode. Sie könnten argumentieren, dass Sie für jeden Konstruktor einen destructor erstellen können, es ist jedoch nicht garantiert, dass MS Test Destruktoren wie erwartet behandelt.
17
T. Webster

Der Hauptvorteil der Verwendung von TestInitialize () oder ClassInitialize () anstelle der Testklasseninstanz oder der statischen Konstruktoren ist ihre explizite Natur. Es zeigt deutlich, dass Sie vor Ihren Tests einige Einstellungen vornehmen. Wenn Sie dies konsequent tun, sollte sich die Wartbarkeit langfristig verbessern.

16
Romi

Ich bevorzuge die Verwendung der [TestInitialize]-Methode, um eine Instantiierung des getesteten Objekts und seiner Parameter durchzuführen. Ich arbeite nur im Konstruktor, wenn eine Testbasisklasse instanziiert werden muss (in der Regel erstellte oder aktualisiere ich Repositorys usw.). Dies hilft mir, den Test-Framework-Code und den Test-Code logisch und physikalisch voneinander zu trennen.

4

Diese Frage wird auch (später) gestellt unter Was ist der Unterschied zwischen der Verwendung des Konstruktors im VS Testing-Framework und dem TestInitialize () - Attribut?

FWIW Ich nehme an, mit "Klassenkonstruktor" meinen Sie den Instanzkonstruktor (nicht den statischen Konstruktor ).

Ich glaube, die gleiche Frage, die Sie stellen, könnte auch über den statischen Konstruktor vs. ClassInitialize ... gestellt werden.

3
bacar

Ich sage, verwenden Sie den Konstruktor, es sei denn, Sie benötigen TestContext.

  1. Wenn Sie die Dinge einfach halten können, warum nicht. Ein Konstruktor ist einfacher als ein magisches Attribut. 
  2. Sie können readonly verwenden, was eine große Sache bei der Testinitialisierung ist, wenn Sie etwas für die Tests vorbereiten möchten, die sie nicht ändern sollen (idealerweise wäre das, was Sie vorbereiten, auch unveränderlich).
1
Ohad Schneider

Das von Ihnen getestete Objekt muss nicht in der [TestInitialize] -Methode instanziiert werden. Sie können den Konstruktor Ihres Objekts in einer Testmethode testen [Test].

Das Objekt in [TestInitialize] kann dazu dienen, Ihren Persistenzspeicher einzurichten oder einen Wert zu erstellen, den das getestete Objekt in den Tests verwendet.

1

Ich weiß, dass ich zu spät zur Party komme, aber mit async ist das ein weiterer Grund (der nicht übergangen wird, als diese Frage gestellt wurde) für [TestInitialize]. Das ermöglicht es Ihnen, async Operationen durchzuführen, um eine Datei einzurichten (zB zu laden), die im Konstruktor nicht möglich sind:

        private string approver;        

        [TestInitialize]
        public async Task Initialize()
        {
            approver = File.ReadAllTextAsync("approver.json");
        }
0
sschoof

Das hängt vom Szenario ab. Wenn Sie über eine Testklasse verfügen und aus irgendeinem Grund eine Instanz einer anderen Testklasse erstellen müssen, müssen Sie den Konstruktor verwenden.

Andernfalls passt der Test mehr Passungen in das Konzept ein. Aus den gleichen Gründen wie oben beschrieben, kann die zweite MS weitere Merkmale in dieses Attribut einführen, und Sie profitieren davon. Mit Konstruktor bleiben Sie dabei.

0
Teoman shipahi