Test-Driven Development-Jak napisać test zanim żaden z kodu implementacji nie istnieje

Uczę się TDD, ale staram się go zaadoptować, ponieważ nie jest to proste.

Na pytanie, na które nie mogę odpowiedzieć, brzmi "Jak napisać test, zanim jakikolwiek kod implementacji istnieje?".

Jeśli nasza klasa docelowa / metoda docelowa / typ parametru docelowego / Typ zwracanego celu nie istnieją,

  • do czego odnosimy się pisząc kod w teście. Jak zacząć pisać test?
  • Jak to się stało, że test się nie powiódł, skoro mogliśmy napisać tylko nazwę metody testowej przed rzeczywistym kodem implementacyjnym?

Wszyscy mówią dlaczego, ale nie jak

Starałem się znaleźć zasoby, które rozwijają pisanie testów przed kodem produkcyjnym, ale zakładając, że brakowało mi dobrych zasobów, większość z nich jest wypełniona banałami wyjaśnienie, dlaczego TTD jest ważne, niż skupienie się na praktykach jego przyjęcia.

Przykładowy przypadek użycia.

Załóżmy, że tworzymy oprogramowanie dla uczelni, a nasz przypadek użycia to rejestracja na kurs.

Aby to uprościć, ograniczmy tę dyskusję do

    W 2011 roku w ramach Programu Erasmus + w Szkole Głównej Gospodarstwa Wiejskiego w Warszawie odbyła się konferencja pt.]}
  • testowanie warstwy serwisowej i warstwy dao.

Pseudocode

ENROLL(studentId, courseId)
    //check if student enrolled in less than 3 courses in the same semester as given courseId belongs in.
    //if yes, enroll him/her.
    //if not, return an error.

Rzeczywista implementacja powyższego może obejmować kilka klas obejmujących usługi, Dao itp.

Czy mógłbyś wyjaśnić, jak testować-driven-rozwijać go krok po kroku? Gdybyś miał to wdrożyć używając TDD, jak to zrobiłeś krok po kroku.

Mam nadzieję, że to może pomóc wielu zmaganiom takim jak ja w przyszłości.

Author: Carl Manaster, 2013-12-25

4 answers

Utwórz klasę EnrollingServiceTest w src / test / java w tym samym pakiecie co EnrollingService

class EnrollingServiceTest {
    private EnrollingService enrollingService;

    @Before 
    public void init() {
           enrollingService = new EnrollingService();
    }

    @Test
    public void testEnroll() {
           boolean result = enrollingService.enroll(1l, 1l);
           assertTrue(result);
    ...

IDE (zakładam, że używasz IDE) pokazuje błędy-EnrollingService nie istnieje .

Kursor na Enrolservice-IDE zaoferuje utworzenie klasy - niech utworzy w src/main / java

Teraz IDE mówi, że brakuje metody enroll(long, long) - pozwól IDE stworzyć ją za Ciebie.

Teraz IDE nie pokazuje żadnych błędów. Uruchom test-nie powiedzie się. Przejdź do rejestracji i zacznij implementacja logiki

I tak dalej...

 43
Author: Evgeniy Dorofeev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-24 15:41:58

Stanie się to jaśniejsze, gdy skupisz się na oczekiwanym zachowaniu kodu, a nie na jego implementacji. Więc biorąc pod uwagę scenariusz, który przedstawiłeś, możesz dojść do wniosku, że będziesz musiał napisać metodę enroll() w jakiejś klasie. Następnie możesz rozważyć, jak zamierzasz przetestować tę klasę.

Zaczynasz od rozważenia warunków klasy i tego, czego się od niej oczekuje. Może uda Ci się zidentyfikować pewne niezmienniki klasy. W takim przypadku, aby sprawdzić klasę rozważasz sposób, w jaki ten niezmiennik może zostać naruszony.

Więc biorąc pod uwagę stwierdzenie: student może zarejestrować się na maksymalnie 3 kursy W semestrze, wziąć pod uwagę sposoby, że może to nastąpić.

  1. Student jest zarejestrowany na 0 kursów na dany semestr, próba rejestracji na kurs, wynik: Rejestracja udana; student jest teraz zarejestrowany na 1 Kurs na dany semestr.
  2. Student jest zarejestrowany na 1 Kurs na dany semestr, próba rejestracji dla kursu, wynik: Rejestracja udana; student jest teraz zarejestrowany na 2 kursy na dany semestr.
  3. Student jest zarejestrowany na 3 kursy na dany semestr, próba rejestracji na kurs, wynik: Fail (może wyjątek jest wyrzucony?)
  4. etc etc

Następnie piszesz te testy. Każda z nich może być metodą badawczą. Tak więc metoda testowa zapewni, że obiekty są tworzone i środowisko jest ustawione zgodnie z oczekiwaniami. Następnie wywołaj metodę i porównaj wynik z oczekiwanym wynikiem. Jeśli to, czego się spodziewasz, faktycznie się wydarzy, test przeszedł pomyślnie.

Teraz, na początku, ponieważ nie napisałeś jeszcze metody, testy nie zdadzą egzaminu. Ale gdy zaczniesz pisać kod, twoje testy zaczną zdawać i ostatecznie 100% twoich testów przejdzie, w którym momencie jesteś przekonany, że Twój kod spełnia wymagania.

 4
Author: Vincent Ramdhanie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-25 03:42:40
public void shouldNotEnrollInMoreThanFourClassesInASemester() {
  Enroller enroller = new Enroller();
  Student student = new Student();
  Semester one = new Semester();
  Semester two = new Semester();
  Course geology = new Course(one);
  Course architecture = new Course(one);
  Course calculus = new Course(one);
  Course sociology = new Course(one);
  Course geometry = new Course(two);

  assertOk(enroller.enroll(student, geology));
  assertOk(enroller.enroll(student, architecture));
  assertOk(enroller.enroll(student, calculus));
  assertNotOk(enroller.enroll(student, sociology));
  assertOk(enroller.enroll(student, geometry));
}
 3
Author: Carl Manaster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-25 03:36:47

W Twoim scenariuszu powinieneś przetestować każdą warstwę osobno, więc wykoślaw dao podczas testowania warstwy usług.

Po pierwszym napisaniu testu nie będzie kompilowany, co oznacza, że nie powiedzie się, ale jest to w porządku, ponieważ klasy nie istnieją.

W twoim przykładzie którą warstwę należy wymusić, aby zarejestrować się na co najwyżej 3 kursach? To wpłynie na sposób, w jaki testujesz.

Napisanie testu w pierwszej kolejności pomoże Ci przejść przez tego typu pytania.

Jak już wspomniano jest to zbyt otwarte aby uzyskać ostateczną odpowiedź, ale jeśli zaczniesz pisać test, a następnie opublikować jako aktualizację, może to pomóc.

Więc napisz swój test dao, a następnie napisz klasy i metody, aby kompilował, ale i tak powinien zawieść, dopóki Yiu nie skończy implementacji. Prawdopodobnie będziesz chciał przetestować rejestracje klas 2,3,4 i upewnić się, że każda z nich zawiedzie odpowiednio, a następnie zakończyć implementację.

 1
Author: James Black,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-25 03:41:33