Uczę się TDD przy użyciu c #, o ile wiem, test powinien kierować rozwojem , to znaczy najpierw napisać test zakończony niepowodzeniem po napisaniu minimalnego kodu, aby przejść test, a następnie dokonać refaktoryzacji.
Mówi się również, że „ Program do interfejsu, a nie implementacja ”, więc najpierw napisz interfejs . Tu zaczyna się moje zamieszanie. Jeśli najpierw piszę Interfejs, narusza to dwie rzeczy
Kod napisany dla interfejsu nie jest sterowany przez test .
Nie jest to absolutne minimum, oczywiście, że mogę napisać to za pomocą prostej klasy.
Czy powinienem zacząć od napisania testów interfejsu? bez żadnej implementacji, co zamierzam przetestować?
Jeśli to pytanie brzmi głupio przepraszam za to, ale jestem całkowicie zdezorientowany. Być może biorę rzeczy zbyt dosłownie.
źródło
interface
do wszystkiego. Aclass
zapewnia również interfejs, ponieważ można ukryć szczegóły implementacji wprivate
zmiennych.contract
. Może to być na przykład klasa abstrakcyjna, chociaż nie powinna to być wirtualna klasa / metoda, ponieważ nie powinno być możliwości jej utworzenia.Odpowiedzi:
Twoje pierwsze naruszenie („Kod napisany dla interfejsu nie jest sterowany przez test.”) Jest nieprawidłowy. Użyjmy trywialnego przykładu. Załóżmy, że piszesz klasę kalkulatora i piszesz operację dodawania. Jaki test możesz napisać?
Twój test właśnie zdefiniował interfejs. To jest
add
metoda, rozumiesz?add
pobiera dwa argumenty i zwraca ich sumę. Możesz później ustalić, że potrzebujesz wielu kalkulatorów, i wyodrębnić (w tym przypadku) interfejs Java w tym czasie. Twoje testy nie powinny się wtedy zmienić, ponieważ przetestowałeś publiczny interfejs tej klasy.Na poziomie bardziej teoretycznym testy są wykonywalną specyfikacją systemu. Interfejsy do systemu powinny być obsługiwane przez użytkowników tego systemu, a testy to pierwsza metoda definiowania interakcji.
Nie sądzę, że można oddzielić projekt interfejsu od projektu testowego. Definiowanie interakcji i projektowanie dla nich testów to ta sama operacja mentalna - kiedy wysyłam te informacje do interfejsu, oczekuję określonego rezultatu. Gdy coś jest nie tak z moim wejściem, oczekuję tego błędu. Możesz wykonać tę pracę projektową na papierze, a następnie napisać z niej swoje testy lub możesz wykonać je jednocześnie - to nie ma znaczenia.
źródło
new Calculator()
czy wdrożenie jest prawidłowe? Jeśli potrzebna jest nowa implementacja, może zrobiłbyś wtedy MultiplicationCalculator i musiałbyś zmienić test, aby użyćnew AdditionCalculator()
go, aby nadal mógł przejść? A może coś mi brakuje?Co robimy, kiedy piszemy
interface
? Piszemy kod, czy projektujemy?Nie jestem fanem koncepcji Test Driven Design, ale uwielbiam Test Driven Development . Osobiście osiągnąłem najlepsze wyniki, projektując klasę z góry, projektując interfejs przed napisaniem testu. Nie liczę interfejsu jako kodu. Interfejs to projekt, który będę wdrażał za pomocą TDD. Prawdopodobnie zmieni się w trakcie pracy, ale jest to moja mapa drogowa (wraz z moją listą testów).
Przestanę, zanim zacznę mówić, ale mam nadzieję, że jest to pomocny sposób, aby o tym pomyśleć.
źródło
Wszystko zależy od tego, jak ortodoksyjni / religijni chcesz robić TDD .
Ponieważ uczysz się, powinieneś eksperymentować, aby uzyskać osobisty przepływ pracy, który działa dla Ciebie.
Jeśli chcesz to zrobić zgodnie z książkami , najpierw piszesz test, który oczywiście się nie powiedzie, ponieważ zaczynasz bez kodu. Następnie piszesz kod, aby test przeszedł pomyślnie. Jeśli tak się stanie, możesz przefakturować istniejący kod, ponieważ masz test, który zapewnia pewnego rodzaju siatkę bezpieczeństwa dla refaktoryzacji. Decyzja o użyciu interfejsu jest pewnego rodzaju refaktoryzacją.
Poza TDD, czy nie: Pytanie, czy użyć interfejsu, czy nie, nie jest interesujące w pierwszej kolejności. Oczywiście, jeśli jesteś pewien, że masz różne zachowanie, które chcesz rozłożyć na kilka obiektów, warto pomyśleć o użyciu interfejsu: Na przykład, jeśli masz jakieś wyjście do różnych miejsc docelowych, warto wdrożyć je za pośrednictwem interfejs Writer i mają różne klasy danych wyjściowych ( FileWriter , Printer itp.). Chociaż pisanie do interfejsu jest powszechnym powiedzeniem , ale to nie znaczy: używaj interfejsu do wszystkiego . Czasami jest to jeden poziom pośredni za dużo. Btw. to samo dotyczy usług. Ale to inny temat.
Z drugiej strony możesz opracować test napędzany w inny sposób: zaprojektuj kod pod kątem testowalności. Co oznacza, że piszesz kod, który jest łatwy do przetestowania - chociaż testy są pisane później . Nie ma znaczenia, czy piszesz testy wcześniej, czy później, o ile i tak testujesz.
źródło
TDD lub BDD oznaczałoby najpierw wykonanie interfejsów domeny, a następnie napisanie testów przeciwko nim według mojej interpretacji. implementacja interfejsu ma oczekiwane zachowanie.
wciąż testuje przed kodem, ponieważ interfejs nie zawiera logiki testowalnej, to jest struktura, na której piszesz test.
Zrobiłbym to w następujący sposób
Napisz zachowanie półformalne (biorąc pod uwagę: Kiedy: Wtedy :)
Napisz interfejs (do metody enkapsulacji zachowania hosta)
Napisz Test, który identyfikuje (wprowadź dane, zadzwoń kiedy, przetestuj wtedy)
Napisz / zmień beton (klasa implementująca interfejs), aby zdać test
źródło
Nigdy nie pisz testów przed zaprojektowaniem interfejsów. Kiedy zastanawiasz się, jakie testy napisać (projekt testu), nie powinieneś jednocześnie projektować (architektura) aplikacji. Nie myśl o dwóch rzeczach jednocześnie. Czy słyszałeś o rozdzieleniu obaw? Dotyczy to nie tylko fizycznej struktury kodu, ale także procesu myślenia.
Zdecyduj, jak twoja aplikacja powinna być najpierw zaprojektowana. Oznacza to, że projektujesz swoje interfejsy i relacje między nimi. Dopóki tego nie zrobisz, nie powinieneś zaczynać myśleć o testach. Kiedy już wiesz, jakie masz interfejsy, możesz albo najpierw je utworzyć, a następnie napisać testy przeciwko nim lub najpierw napisać testy, a następnie je utworzyć. W tym drugim przypadku oczywiście nie będziesz w stanie skompilować testów. Nie widzę żadnej szkody ani żadnego naruszenia filozofii TDD w tworzeniu interfejsów przed testami.
źródło
interface
słowa kluczowego C # , a nie ogólnego terminu „interfejs”.Można pisać interfejs / kod / test w tym samym czasie, o ile ich włączenie do projektu jest atomowe.
Chyba że twój szef jest religijny na temat TDD, w takim przypadku prawdopodobnie musisz napisać pusty interfejs -> test -> minimalny kod (bezcelowy krok) -> więcej testów -> więcej bezsensownego kodu -> więcej testów -> w końcu napisać prawdziwy kod > gotowe.
źródło