JUnit TESTY JEDNOSTKOWE Waldemar Korłub Platformy Technologiczne KASK ETI Politechnika Gdańska
Testy aplikacji 2 Ręczne testowanie Czasochłonne Powtarzalność trudna do uzyskania Nudne Testowanie automatyczne Szybsze Powtarzalne Nie wymaga ciągłej uwagi ze strony dewelopera Ułatwia kontrolowanie regresji n Po wykonaniu zmian/refaktoryzacji uruchamiamy testy
Testy aplikacji 3 Testować można na wielu poziomach Testy jednostkowe Testy integracyjne Testy funkcjonalne/akceptacyjne Testy interfejsu użytkownika
Testy jednostkowe 4 Testowanie komponentów aplikacji w separacji od ich zależności np. odseparowanie od bazy danych, innych komponentów aplikacji Testy dokumentują oczekiwane zachowanie komponentu To że każdy komponent z osobna działa poprawnie, nie oznacza, że aplikacja jako całość jest poprawna Stąd inne poziomy testowania (poprzedni slajd)
Co testować 5 Poprawne przebiegi Prawidłowe zachowanie dla poprawnych danych wejściowych Przypadki graniczne Krańce przedziałów dozwolonych wartości, min, max Sytuacje wyjątkowe Czy komponent reaguje prawidłowo na błędne dane?
JUnit 6 Podstawowe narzędzie w rękach każdego dewelopera Javy W projekcie budowanym Mavenem: src/test/java Integracja we wszystkich popularnych IDE Testy implementowane jako klasy z odpowiednimi adnotacjami
Wzorzec Arrange-Act-Assert 7 Wzorzec Arrange-Act-Assert określa strukturę testu: Arrange przygotowanie danych wejściowych i wszystkich wymaganych obiektów Act wykonanie operacji na testowanym obiekcie Assert weryfikacja czy uzyskane rezultaty są zgodne z oczekiwaniami Jasno rozdziela testowaną funkcjonalność od kodu inicjującego i weryfikującego
Przykład (niezbyt przydatnego) testu 8 public class OrdersServiceTest { @Test public void whengivenlowercasestring_toupperreturnsuppercase() { //Arrange String lower = "abcdef"; } } //Act String result = lower.touppercase(); //Assert Assert.assertEquals("ABCDEF", result);
Asercje 9 org.junit.assert assertequals assertarrayequals assertnotsame assertfalse/asserttrue assertnotnull assertthat(t actual, Matcher<T> matcher)
Matcher 10 org.hamcrest.corematchers assertthat(arrays.aslist("one", "two", "three"), hasitems("one", "three")); assertthat(arrays.aslist(new String[]{"fun","ban","ne"}), everyitem(containsstring("n"))); assertthat("good", anyof(equalto("bad"), equalto("good"))); assertthat("album", both(containsstring("a")).and(containsstring("b")));
Mocki (zaślepki) 11 Jak przetestować komponent, który używa obiektu klasy EntityManager? Do testów jednostkowych nie używamy bazy danych Wydłużenie czasu testu Taki test może się nie powieść ze względu na błąd po stronie bazy danych, a nie w testowanym komponencie Mocki to specjalnie zbudowane obiekty-zaślepki, które zachowują się w z góry określony sposób W projekcie Spring Boot domyślnie dostępna jest biblioteka Mockito
@RunWith(MockitoJUnitRunner.class) public class OrdersServiceTest { 12 @Mock EntityManager em; @Test public void whenorderedbookavailable_placeorderdecreasesamountbyone() { //Arrange Order order = new Order(); Book book = new Book(); book.setamount(1); order.getbooks().add(book); Mockito.when(em.find(Book.class, book.getid())).thenreturn(book); OrdersService ordersservice = new OrdersService(em); //Act ordersservice.placeorder(order); //Assert assertequals(0, (int)book.getamount()); } } Mock dla EntityManagera
13 @Test(expected = OutOfStockException.class) public void whenorderedbooknotavailable_placeorderthrowsoutofstockex() { } //Arrange Order order = new Order(); Book book = new Book(); book.setamount(0); order.getbooks().add(book); Mockito.when(em.find(Book.class, book.getid())).thenreturn(book); OrdersService ordersservice = new OrdersService(em); //Act ordersservice.placeorder(order); //Assert spodziewany wyjątek Testowanie sytuacji wyjątkowej
TDD: Test Driven Development 14 Pracę nad nowym komponentem/funkcjonalnością zaczynamy od napisania testów Testy opisują oczekiwane zachowanie komponentu Pisząc testy zastanawiamy się jak komponent będzie używany (np. przez innych deweloperów) Pierwsze uruchomienie testów wszystkie kończą się niepowodzeniem Bo jeszcze nie mamy żadnej funkcjonalności! Implementujemy komponent tak, aby kolejne testy kończyły się sukcesem Gdy wszystkie testy przechodzą pomyślnie, implementacja komponentu jest zakończona
Testowanie 15 Testy aplikacji mogą ujawnić występujące w niej błędy, nie mogą wykazać, że błędów nie ma! --Edsger Dijkstra
16 Pytania?