19 May
2010

xUnit.net und IUseFixture<> für die TestFixture Initialisierung

 

Mein seit ein paar Monaten favorisiertes Unit Testing Framework ist xUnit.net. Vorher war es MbUnit, dies ist jedoch mit Gallio/MbUnit 3 in eine Richtung gegangen die mir nicht mehr zugesagt (Fett, Groß, Langsam).

xUnit.net ist ein kleines Framework was erweiterbar ist. Meine Hauptgründe für dessen Nutzung sind

  • neue Instanz der Testklasse für jeden Test
  • Minimale notwendige Attributierung
  • “schönere” Assert-Syntax
  • die xunit bdd externsions
  • Mitgelieferte Build-Tasks für Nant, MSBuild etc.
public class SimpleTest
{
    [Fact]
    public void SuperKlasse_macht_es_richtig()
    {
        var foo = new SuperKlasse();

        var result = foo.TolleMethode();

        Assert.Equal("SollSein",result);

    }
}

Was einem auffällt ist dass nur [Fact] an der Test-Methode steht, mehr nicht. Kein weiteres Attribut ist für den Test notwendig. Auch gibt es keine [SetUp] Attribut, ein Setup für einen Test wird im Konstruktor der Klasse gemacht.

public class SimpleTest
{
    SuperKlasse foo;

	public SimpleTest()
    {
        foo = new SuperKlasse();
    }

    [Fact]
    public void SuperKlasse_macht_es_richtig()
    {
        var result = foo.TolleMethode();

        Assert.Equal("SollSein",result);

    }
}

Da die Klasse für jede Test-Methode neu instanziiert wird wird auch der Konstruktor jedesmal aufgerufen. Somit ist auf diesem Wege auch kein Setup für das komplette TestFixture möglich. Dazu stellt xUnit.net  das IUseFixture<> Interface zu Verfügung. Damit ist es möglich Fixtures für Test zu verwenden, dies kann z.B. notwendig werden wenn das zusammenstellen der Daten länger dauert.

Die Anwendung sieht dann so aus.

public class SimpleTest : IUseFixture<SimpleFixture>
{
    SuperKlasse foo;

    public void SetFixture(SimpleFixture data)
    {

    }

	public SimpleTest()
    {
        for = new SuperKlasse();
    }

    [Fact]
    public void SuperKlasse_macht_es_richtig()
    {
	   // der Test	
    }
}

SimpleFixture ist eine beliebige Klasse die überlicherweise im Konstruktur die Initialisierung der notwenden Daten oder Funktionen übernimmt. Sie wird nur einmal pro TestKlasse erzeugt und für für alle Test wird die SetFixture() Methode aufgerufen um eventuell erzeugte Daten in den Test übernehmen zu können.

public class SimpleFixture: IDisposable
{
    public SimpleFixture()
    {
        new Bootstrap.BootstrapMetaData().Execute();
    }

    public void Dispose()
    {
        FluentMetadataBuilder.Reset();
    }
}

Am Ende des Tests wird, sofern implementiert, Dispose() der Fixture Klasse zum aufräumen der Daten aufgerufen

Das schöne daran finde ich dass man sich kleine Fixtures aufbauen kann und diese in verschiedenen Tests verwenden kann. Außerdem sieht man direkt in der Klassendefinition des Test welche Fixtures in den Tests gebraucht werden. Weiter ist es möglich IUseFixture<> mehrfach in einer Test-Klasse einzusetzen.

Technorati-Tags: ,,

Der Eintrag ist mir etwas Wert
 

Feedback

# re: xUnit.net und IUseFixture<> für die TestFixture Initialisierung

left by Uwe Grunwald at 5/20/2010 9:50 AM Gravatar
Hallo Albert,

schöner Artikel, das Interface kannte ich noch gar nicht.......
Wir setzen bei uns in der Firma ebenfalls xUnit + Björns bdd extensions ein, hiermit fahren wir bis jetzt sehr gut. Mit welchem Runner führst Du die Tests denn aus? Im Moment nehme ich Gallio, das nervt aber, weil es irgendwie zu träge ist.

Grüße
Uwe Grunwald

# re: xUnit.net und IUseFixture<> für die TestFixture Initialisierung

left by Albert at 5/20/2010 10:29 AM Gravatar
Ich setzte einen angepasste Version vom ReSharper Runner in Visual Studio ein http://xunitcontrib.codeplex.com/

Hier der Source zu angepassten Version
xunitcontrib.codeplex.com/.../xunitcontrib

# re: xUnit.net und IUseFixture<> für die TestFixture Initialisierung

left by Albert at 5/20/2010 10:36 AM Gravatar
In der angepassten Version ist jedoch ein aktueller Build von xUnit 1.6 enthalten (noch nicht fertig, der auch eine Anpassung der bdd extensions erforderlich macht)
Comments have been closed on this topic.