
TDD (Test-Driven Development) – to metoda programowania, w której deweloper pisze testy jednostkowe przed implementacją kodu. Ta technika pozwala na zwiększenie jakości i stabliności kodu oraz ułatwia utrzymanie i rozwój aplikacji. W TDD kierujemy się trzema zasadami (Red, Green, Refactor) , najpierw piszemy test który nie przechodzi (Red). Drugim krokiem jest implementacja funkcjonalności po to by test przechodził (Green), trzecim natomiast jest refaktoryzacja (Refactor), uruchamiamy ponownie testy jeśli dalej wszystko jest „zielone” to wracamy do punktu pierwszego. Jest to podejście iteracyjne, doskonale widać to na powyższym obrazku, robimy jak najmniejsze kroki by iść do przodu z implementowaną funkcjonalnością.
Jak to wygląda w praktyce?
Dla przykładu stworzymy metodę dodającą pojazd do repozytorium. Zgodnie z metodą TDD zaczynam od pisania testu:
class CarRepositoryTest:
package cars; import org.junit.jupiter.api.Test; public class CarRepositoryTest { @Test void shouldBeAbleToAddCarToRepository(){ //given CarRepository carRepository = new CarRepository(); } }
Na tym etapie otrzymujemy czerwony test ponieważ brakuje nam klasy „CarRepository”.
Teraz przechodzimy do utworzenia brakującej klasy:
class CarRepository:
package cars; public class CarRepository { }
W tym momencie nasz test stał się zielony:
class CarRepositoryTest:
package cars; import org.junit.jupiter.api.Test; public class CarRepositoryTest { @Test void shouldBeAbleToAddCarToRepository(){ //given CarRepository carRepository = new CarRepository(); } }
Zgodnie z zasadami TDD kontynuujemy pisanie testu:
class CarRepositoryTest:
package cars; import org.junit.jupiter.api.Test; public class CarRepositoryTest { @Test void shouldBeAbleToAddCarToRepository(){ //given CarRepository carRepository = new CarRepository(); Car car = new Car(15000, "BMW E46"); //when carRepository.add(car); } }
Na tym etapie ponownie otrzymujemy test czerwony ponieważ nie mamy utworzonej metody „add”, przechodzimy do jej utworzenia:
class CarRepository:
package cars; public class CarRepository { public void add(Car car){ } }
Teraz przerywamy implementację ponieważ nasz test ponownie stał się zielony:
class CarRepositoryTest:
package cars; import org.junit.jupiter.api.Test; public class CarRepositoryTest { @Test void shouldBeAbleToAddCarToRepository(){ //given CarRepository carRepository = new CarRepository(); Car car = new Car(15000, "BMW E46"); //when carRepository.add(car); } }
Stwórzmy asercję dla naszego testu sprawdzającą czy w liście znajduję się nasz dodany obiekt „car”:
class CarRepositoryTest:
package cars; import org.junit.jupiter.api.Test; import static org.hamcrest.Matchers.* import static org.hamcrest.MatcherAssert.assertThat; public class CarRepositoryTest { @Test void shouldBeAbleToAddCarToRepository(){ //given CarRepository carRepository = new CarRepository(); Car car = new Car(15000, "BMW E46"); //when carRepository.add(car); //then assertThat(carRepository.getAllCars().get(0), is(car)); } }
Test czerwony, metoda „getAllCars” nie została jeszcze przez nas utworzona:
class CarRepository:
package cars;
import java.util.List;
public class CarRepository {
public void add(Car car){
}
public List getAllCars() {
return null;
}
}
Przeszliśmy do etapu w którym nasz test się kompiluje ale nie przechodzi, teraz musimy dodać trochę logiki dla naszych metod aż ten test zacznie przechodzić:
class CarRepository:
package cars; import java.util.ArrayList; import java.util.List; public class CarRepository { private List<Car> cars = new ArrayList<>(); public void add(Car car){ cars.add(car); } public List<Car> getAllCars() { return cars; } }
Voilà! Po dodaniu logiki nasz test zaczął przechodzić:

Mam nadzieję, że choć trochę pomogłem zrozumieć Ci metodę działania Test-Driven Development 🙂