fbpx
devstyle.pl - Blog dla każdego programisty
devstyle.pl - Blog dla każdego programisty
3 minut

IUseFixture<T>


19.12.2013

Był taki smutny czas, że struktura dziedziczenia w moich testach zdecydowanie przerastała stopniem skomplikowania dziedziczenie w testowanym kodzie. A bo jedna klasa bazowa dla testów umożliwiała na przykład kontakt z prawdziwą bazą. Inna – testy z bazą in-memory. Jeszcze inna – puszczanie requestów do systemu. I tak dalej.

Efekt był taki, że de facto wszystkie testy dziedziczyły ze wszystkiego. Fuj na maxa, z pryszczem jeszcze ohydnym.

Wszystko to uległo znaczącej poprawie, gdy nauczyłem się korzystać z interfejsu IUseFixture<T> w xunit. Celowo piszę “nauczyłem się korzystać” a nie “dowiedziałem się że istnieje”, ponieważ między tymi dwoma momentami minęło bez mała półtora roku.

Co to jest IUseFixture? Jest to prosty sposób na powiedzenie runnerowi: “testy w tej klasie potrzebują funkcjonalności oferowanej przez klasę T”.

Mógłbym dalej się “słownie” rozwodzić nad tym tematem, ale lepiej rozwieść się kodowo. Oto przykład “fixture” oferującej dostęp do nowej instancji “in memory database” z Simple.Data:

/// <summary>
/// Fixture for tests using in-memory db.
/// </summary>
public class InMemoryDbFixture : IDisposable
{
    public dynamic Db;

    public InMemoryDbFixture()
    {
        Reset();
    }

    public void Dispose()
    {
        Database.StopUsingMockAdapter();
    }

    public void Reset()
    {
        var inMemoryAdapter = new InMemoryAdapter();

        configure_schema(inMemoryAdapter);

        Database.UseMockAdapter(inMemoryAdapter);

        Db = Database.Open();
    }

    static void configure_schema(InMemoryAdapter adapter)
    {
        // keys / relations configuration
    }
}

Jak to działa? Bardzo prosto: każda moja klasa z testami sprawdzającymi poprawność wykonywanych operacji wykorzystując bazę utworzoną w pamięci przez Simple.Data (co w kolejnej wersji będzie “full-blown database” a nie tylko słownikiem na słowniku jak jest teraz) posiada taki oto kod:

private InMemoryDbFixture _db;
public void SetFixture(InMemoryDbFixture data)
{
    _db = data;
    _db.Reset();
}

A dostęp do bazy mam przez “_db.Db”. Sweet.

A dlaczego zawsze w SetFixture mam wywołanie Reset()? Bo instancja InMemoryFixture jest tworzona tylko raz dla wszystkich testów z danej klasy. W pewnych okolicznościach ma to zastosowanie, a w innych: nie. To co robię jest faktycznym zasymulowaniem klasy bazowej posiadającej w swoim konstruktorze całą logikę inicjalizacji bazy. Z tą różnicą, że teraz mogę sobie dobierać dowolne “fixtures” z których moje testy korzystają. A tych “fixtures” mam parę.

Na koniec ciekawostka: aktualnie implementacja omawianego interfejsu wymusza stworzenie metody

public void SetFixture(T data)

, która to metoda weźmie parametr “data” i przypisze go prawdopodobnie do jakiegoś pola. A jej implementacja będzie identyczna w każdej klasie, która danej zależności potrzebuje. W v2.0 xunit ma się to zmienić: zależności testów będą przekazywane w konstruktorze. How cool is that?

Nie przegap kolejnych postów!

Dołącz do ponad 9000 programistów w devstyle newsletter!

Tym samym wyrażasz zgodę na otrzymanie informacji marketingowych z devstyle.pl (doh...). Powered by ConvertKit
Notify of
Bart
Bart

Witam, dziękuję za wpis, jednak proponował bym wrzucić cały kod klasy testu. W tytule wpisu nazwa”IUseFixture”, więc szukam wykorzystania tego interfejsu w listingach i nigdzie nie ma. Dopiero zapytanie wujka googla pokazało o co tak naprawdę biega. Pisze to z punktu widzenia czytelnika, który nie korzysta na codzień z xunit.

orientman

Kontynuując z twittera. Pierwsza myśl po przeczytaniu twojego wpisu była taka: ojoj, znowu niepotrzebnie odkryłem amerykę i w bólach doszedłem do podobnego rozwiązania dla NUnit. A wystarczyło się rozejrzeć… Druga myśl: przecież dokładnie takie API można zaimplementować na bazie NUnit i stąd machnąłem szybko: https://gist.github.com/orient-man/8039247 (z uproszczeniem, że cykl życia fikstury to 1 test – bo tego zwykle potrzebuję, BTW nie wiem jak zrobią “W v2.0 xunit ma się to zmienić: zależności testów będą przekazywane w konstruktorze” – przecież to zmieni semantykę, gdzie zawołasz Reset? No chyba, że dla każdego testu z klasy leci nowa instancja – nie znam xunit).… Read more »

orientman

Mała wtopa, książka jest o xUnit dla Javy – zupełnie innym frameworku – dzięki @gutek ;)

trackback

IUseFixture | Maciej Aniserowicz o programowaniu…

Dziękujemy za dodanie artykułu – Trackback z dotnetomaniak.pl…

Moja książka

Facebook

Zobacz również