Zasadniczo mam sedno TDD. Sprzedano mi, że jest to przydatne i mam rozsądną znajomość frameworka MSTEST. Jednak do tej pory nie udało mi się ukończyć z wykorzystaniem go jako podstawowej metody rozwoju. Najczęściej używam go jako surogatu do pisania aplikacji konsolowych jako sterowników testowych (moje tradycyjne podejście).
Najbardziej użyteczną rzeczą dla mnie jest sposób, w jaki pochłania rolę testowania regresji.
Nie zbudowałem jeszcze niczego, co konkretnie izoluje różne zachowania, które można przetestować, co jest kolejną dużą częścią obrazu, który znam.
Tak więc pytanie polega na zapytaniu o wskazówki, jakie pierwsze testy mogę napisać dla następującego zadania programistycznego: Chcę stworzyć kod, który zawiera wykonanie zadania w stylu producenta / konsumenta.
Zatrzymałem się i postanowiłem napisać to pytanie po tym, jak napisałem ten kod (zastanawiam się, czy tym razem naprawdę mogę użyć TDD)
Kod:
interface ITask
{
Guid TaskId { get; }
bool IsComplete { get; }
bool IsFailed { get; }
bool IsRunning { get; }
}
interface ITaskContainer
{
Guid AddTask(ICommand action);
}
interface ICommand
{
string CommandName { get; }
Dictionary<string, object> Parameters { get; }
void Execute();
}
Odpowiedzi:
Począwszy od tej koncepcji:
1) Zacznij od pożądanego zachowania. Napisz na to test. Zobacz test zakończony niepowodzeniem.
2) Napisz wystarczającą ilość kodu, aby pomyślnie przejść test. Zobacz wszystkie testy zaliczone.
3) Poszukaj kodu nadmiarowego / niechlujstwa -> refaktora. Zobacz, testy wciąż się kończą. Idź 1
Tak więc w punkcie 1 powiedzmy, że chcesz utworzyć nowe polecenie (rozciągam się na sposób działania polecenia, więc trzymaj się mnie). (Będę też bardziej pragmatyczny niż ekstremalny TDD)
Nowe polecenie nazywa się MakeMyLunch, więc najpierw tworzysz test, aby go utworzyć i uzyskać nazwę polecenia:
To się nie udaje, zmuszając cię do utworzenia nowej klasy poleceń i zwrócenia jej nazwy (purysta powiedziałby, że to dwie rundy TDD, a nie 1). Tworzysz klasę i implementujesz interfejs ICommand, w tym zwracając nazwę polecenia. Uruchomienie wszystkich testów pokazuje teraz wszystkie zaliczenia, więc zaczynasz szukać możliwości refaktoryzacji. Prawdopodobnie żaden.
Następnie chcesz, aby implementacja wykonała. Musisz więc zapytać: skąd mam wiedzieć, że „MakeMyLunch” z powodzeniem „zrobił mój lunch”. Jakie zmiany w systemie spowodowane tą operacją? Czy mogę to przetestować?
Załóżmy, że łatwo jest przetestować:
Innym razem jest to trudniejsze i naprawdę chcesz przetestować obowiązki badanego obiektu (MakeMyLunchCommand). Być może obowiązkiem MakeMyLunchCommand jest interakcja z lodówką i kuchenką mikrofalową. Aby to przetestować, możesz użyć fałszywej lodówki i fałszywej kuchenki mikrofalowej. [dwie przykładowe frameworki to Mockito i nMock lub spójrz tutaj .]
W takim przypadku zrobiłbyś coś takiego jak następujący pseudo kod:
Purysta mówi, aby przetestować odpowiedzialność swojej klasy - jej interakcje z innymi klasami (czy polecenie otworzyło lodówkę i włączyło kuchenkę mikrofalową?).
Pragmatysta mówi: przetestuj grupę zajęć i sprawdź wynik (czy lunch jest gotowy?).
Znajdź odpowiednią równowagę, która działa dla twojego systemu.
(Uwaga: pamiętaj, że być może doszedłeś do struktury interfejsu zbyt wcześnie. Być może możesz to ewoluować, pisząc testy jednostkowe i implementacje, aw kroku # 3 „zauważysz” powszechną możliwość interfejsu).
źródło