Test Driven Development z użyciem JUnit 5. Część 2

Luxoft Training
5 min readOct 7, 2021

--

Druga część naszej serii artykułów na temat programowania sterowanego testami w JUnit 5. Miłej lektury.

2. Aplikacja do zarządzania lotami

Tworzymy aplikację do zarządzania lotami. Obecnie aplikacja jest w stanie tworzyć i konfigurować loty, a także dodawać i usuwać pasażerów lotów.

Przedstawimy scenariusze zgodne z codzienną pracą programistów. Zaczniemy od aplikacji innej niż TDD, która ma robić kilka rzeczy, na przykład przestrzegać zasad firmy dla pasażerów zwykłych i VIP. Musimy zrozumieć aplikację i upewnić się, że naprawdę realizuje oczekiwane operacje. Musimy więc pokryć istniejący kod testami jednostkowymi. Gdy już to zrobimy, zajmiemy się kolejnym wyzwaniem: dodaniem nowych funkcji, najpierw rozumiejąc, co należy zrobić, następnie pisząc testy, które kończą się niepowodzeniem, a następnie pisząc kod, który je naprawia. Ten cykl roboczy jest jednym z fundamentów TDD.

Aplikacja do zarządzania lotami to aplikacja Java zbudowana przy pomocy Mavena. Oprogramowanie musi przestrzegać zasad dotyczących dodawania i usuwania pasażerów z lotów. Loty mogą być różnych typów: obecnie istnieją loty ekonomiczne i biznesowe, ale inne typy mogą zostać dodane później, w zależności od wymagań klienta. Do lotów ekonomicznych mogą być dodawani zarówno pasażerowie VIP, jak i stali klienci, ale tylko pasażerowie VIP mogą być dodani do lotów biznesowych.

Istnieje również polityka usuwania pasażerów z lotów: zwykły pasażer może zostać usunięty z lotu, ale pasażer VIP nie może zostać usunięty. Jak widać na tych dwóch diagramach aktywności, początkowa logika biznesowa skupia się na podejmowaniu decyzji.

Spójrzmy na wstępny projekt tej aplikacji. Zawiera pole o nazwie FlightType w klasie lotu. Jej wartość określa zachowanie metod addPassenger i removePassenger. W przypadku tych dwóch metod programiści muszą skupić się na podejmowaniu decyzji na poziomie kodu.

public class Passenger {

private String name; #1
private boolean vip; #2

public Passenger(String name, boolean vip) { #3
this.name = name; #3
this.vip = vip; #3
} #3

public String getName() { #4
return name; #4
} #4

public boolean isVip() { #5
return vip; #5
} #5

}

  • Klasa Passenger zawiera pole nazwy # 1 wraz z funkcją pobierającą # 4
  • Zawiera również pole VIP # 2 wraz z getter # 5
  • Konstruktor klasy Passenger inicjalizuje pola name i VIP # 3

Następna lista pokazuje klasę lotu.

public class Flight {

private String id; #1
private List passengers = new ArrayList(); #2
private String flightType; #3

public Flight(String id, String flightType) { #4
this.id = id; #4
this.flightType = flightType; #4
} #4

public String getId() { #5
return id; #5
} #5

public List getPassengersList() { #6
return Collections.unmodifiableList(passengers); #6
} #6

public String getFlightType() { #7
return flightType; #7
} #7

public boolean addPassenger(Passenger passenger) {
switch (flightType) { #8
case “Economy”: #9
return passengers.add(passenger); #9
case “Business”: #10
if (passenger.isVip()) { #10
return passengers.add(passenger); #10
} #10
return false; #10
default: #11
throw new RuntimeException(“Unknown type: “ + flightType); #11
}

}

public boolean removePassenger(Passenger passenger) {
switch (flightType) { #12
case “Economy”: #13
if (!passenger.isVip()) { #13
return passengers.remove(passenger); #13
} #13
return false; #13
case “Business”: #14
return false; #14
default: #15
throw new RuntimeException(“Unknown type: “ + flightType); #15
}
}

}

W tym listingu:

  • Klasa lotu zawiera identyfikator # 1 wraz z getter # 5, listę pasażerów zainicjowaną jako pusta lista # 2 wraz z getter # 6 oraz typ lotu # 3 wraz z getter # 7
  • Konstruktor klasy Flight inicjuje id i pola flightType # 4
  • Metoda addPassenger sprawdza typ lotu nr 8. Jeśli jest to lot ekonomiczny, można dodać dowolnych pasażerów # 9. Jeśli jest to lot biznesowy, można dodać tylko pasażerów VIP nr 10. W przeciwnym razie (jeśli lot nie jest lotem ekonomicznym ani biznesowym), metoda zgłosi wyjątek, ponieważ nie może obsłużyć nieznany typ lotu # 11
  • Metoda removePassenger sprawdza typ lotu # 12. Jeśli jest to lot ekonomiczny, można usunąć tylko zwykłych pasażerów # 13. Jeśli jest to lot biznesowy, pasażerowie nie mogą zostać usunięci # 14. W przeciwnym razie (jeśli lot nie jest lotem ekonomicznym ani biznesowym), metoda zgłosi wyjątek, ponieważ nie może obsłużyć nieznany typ lotu # 15

Aplikacja nie ma jeszcze testów. Zamiast tego początkowi programiści napisali kod, w którym po prostu śledzili wykonanie i porównali go ze swoimi oczekiwaniami. Na przykład istnieje klasa lotniska, w tym główna metoda, która działa jako klient klas lotu i pasażera oraz współpracuje z różnymi typami lotów i pasażerów.

public class Airport {

public static void main(String[] args) {
Flight economyFlight = new Flight(“1”, “Economy”); #1
Flight businessFlight = new Flight(“2”, “Business”); #1

Passenger james = new Passenger(“James”, true); #2
Passenger mike = new Passenger(“Mike”, false); #2

businessFlight.addPassenger(james); #3
businessFlight.removePassenger(james); #3
businessFlight.addPassenger(mike); #4
economyFlight.addPassenger(mike); #5

System.out.println(“Business flight passengers list:”); #6
for (Passenger passenger: businessFlight.getPassengersList()) { #6
System.out.println(passenger.getName()); #6
} #6

System.out.println(“Economy flight passengers list:”); #7
for (Passenger passenger: economyFlight.getPassengersList()) { #7
System.out.println(passenger.getName()); #7
} #7
}
}

W tym listingu:

  • Inicjujemy lot ekonomiczny i biznesowy nr 1. Inicjujemy również Jamesa jako pasażera VIP, a Mike’a jako zwykłego pasażera # 2
  • Próbujemy dodać Jamesa do i usunąć go z lotu biznesowego nr 3, a następnie próbujemy dodać Mike’a do i usunąć go z lotu biznesowego nr 4 i lotu ekonomicznego nr 5
  • Drukujemy listę pasażerów na lot biznesowy nr 6 i ekonomiczny nr 7

Wynik działania tego programu przedstawiono na rysunku 20.4. James, pasażer VIP, został dodany do lotu biznesowego i nie mogliśmy go usunąć. Mike’a, zwykłego pasażera, nie mógł zostać dodany do lotu biznesowego, ale mogliśmy dodać go do lotu ekonomicznego.

Jak dotąd wszystko działa zgodnie z oczekiwaniami, zgodnie z zasadami, które wcześniej zdefiniowaliśmy. Aby zbudować niezawodną aplikację oraz móc łatwo i bezpiecznie zrozumieć i wdrożyć logikę biznesową, przenosimy aplikację na podejście TDD.

Interesujesz się JUnit? Sprawdź nasze szkolenia

Catalin Tudose
Java and Web Technologies Expert

Originally published at https://www.luxoft-training.pl.

--

--