Dobrze napisane testy nie powinny posiadać zduplikowanego kodu. Powtarzalnym kodem jest kod przygotowujący dane testowe, w związku z tym konieczny jest Clean code. Poniżej poglądowy przykład:
![]()
![]()
![]()
W testach potrzebujemy wiele podobnych obiektów różniących się przykładowo jednym polem. Powoduje to, że podobny kod będzie wielokrotnie powielany. Powoduje to szereg problemów:
- Zmiany w konstrukcji obiektów wymuszają zmianę w wielu testach.
- Rośnie szum informacyjny w testach. Testy nie zawierają wyłącznie istotnych informacji.
- Nadpisanie pewnych cech modelu może powodować problemy. Obiekty mogą być niespójne pomiędzy testami.
Są dwa rozwiązania tego problemu. Wzorzec Object Mother i Test Builders.
Object Mother a Clean code
Dostarcza zestaw fabryk, które tworzą obiekty. Np. w postaci statycznych metod klasy:
![]()
![]()
![]()
Przykłady użycia:
![]()
![]()
![]()
Jak możesz zauważyć:
- Kodu jest znacznie mniej. Jest wielokrotnego użytku.
- Przykłady są odpowiednio nazwane. Dzięki temu od razu wiadomo jak będą działały.
- Znacznie prościej dokonać zmiany obiektu. Wszystko jest w jednym miejscu.
W bardziej złożonych aplikacjach fabryki muszą dostarczyć bardziej złożone kombinacje:
![]()
![]()
![]()
Zwiększa to stopień komplikacji. Tworzenie takich przypadków testowych jest bardziej czasochłonne.
Test Builders
Rozwiązaniem problemów z tworzeniem złożonych przypadków testowych we wzorcu Object Mother jest wzorzec Test Builders. Pozwala na nadpisanie konstrukcji obiektu. Poglądowa implementacja:
![]()
![]()
![]()
Builder umożliwia ustawienie dowolnego parametru. Wywołujemy kolejno metody Buildera. Mamy pełną dowolność w kolejności wywołań. Na końcu wywołujemy metodę build(). W ten sposób doprowadzamy obiekt do oczekiwanego stanu.
Przykładowo dla ułatwienia tworzenia koszyków ze zniżką studencką dodaliśmy metodę withStudentDiscount. Dzięki temu nasze testy będą czystsze i czytelniejsze:
![]()
![]()
![]()
Wielokrotnie możemy korzystać z wcześniej przygotowanych builderów.
Nie trzeba tworzyć wielu obiektów. Wystarczy nadpisywać parametry dla kolejnych testów.
Tworzymy Builder z trzema produktami. Następnie przy jego pomocy tworzymy koszyk bez zniżki i drugi koszyk już ze zniżką studencką. O wiele mniej kodu:
![]()
![]()
![]()
Test Builders oraz Lombok
Test Builders ułatwia życie. Ale musimy dołożyć trochę kodu. Dlatego wykorzystajmy Lomboka. Biblioteka. Pozwala ona generować niektóre powtarzalne części kodu.
Dodajemy adnotację @Builder, która wygeneruje metody tworzenia instancji. Podobne do tych utworzonych wcześniej w BasketBuilder.
Dodatkowo ustawiamy inną nazwę buildera na “aBasket”, a także ustawiamy prefix dla każdej metody buildera na “with”.
- Dodajemy też adnotację @Singular nad kolekcją, ponieważ pozwala to na pojedyncze dodawanie produktów do koszyka.
![]()
![]()
![]()
Tyle kodu wystarczy, aby uzyskać podobny efekt co wcześniej:
![]()
![]()
![]()
To rozwiązanie ma też ograniczenia. Nie możemy ustalać dokładnych reguł. Nie możemy dodawać specjalnych metod jak np. withStudentDiscount.
Możemy to obejść. Możemy dodać specjalne metody wykorzystując wzorzec Object Mother. Klasa zwraca nie obiekt, ale buildera, którego możemy nadpisywać.
Mamy stworzoną metodę withStudentDiscount. Zwraca ona buildera, do którego np. możemy dodać produkty. Mamy to w jednym miejscu. Możemy wielokrotnie używać.
![]()
![]()
![]()
Wybierz rozwiązanie, które najbardziej pasuje do twojej sytuacji. Staraj się jednak nie powielać podobnych kodów. Żeby łatwiej było czytać i utrzymywać testy.
Jeżeli będziesz mieć problem z działaniem Lomboka w Intellij Idea to zajrzyj tutaj: link.
Jeśli chcesz więcej informacji na ten temat, zajrzyj tutaj: link.
Źródła:
https://www.arhohuttunen.com/test-data-builders/
https://softwareskill.pl/dane-testowe-matki-obiektow-test-builders



