W artukule JUnit 5 i Selenium - Wprowadzenie do projektu automatycznych testów aplikacji internetowej rozpocząłem tworzenie projektu testów automatycznych dla aplikacji TodoMVC. Mimo że aplikacja jest bardzo prosta, stworzyłem sporo kodu, którego utrzymanie i modyfikacja to nie lada wyzwanie. W tym artykule spróbuję usprawnić projekt poprzez eliminację powtarzającego się kodu oraz prawidłowe określenie odpowiedzialności metod testowych.
O serii
Czytasz część 2 serii artykułów na temat automatyzacji testów aplikacji internetowej TodoMVC. Pozostałe części:
- Część 1 - JUnit 5 i Selenium - Wprowadzenie do projektu automatycznych testów aplikacji internetowej
- Część 3 - JUnit 5 i Selenium - Wprowadzenie do wzrorca Page Object
- Część 4 - JUnit 5 i Selenium - Optymalizacja konfiguracji i uruchomienia projektu
- Część 5 - JUnit 5 i Selenium - klasa PageFactory z pakietu support biblioteki Selenium
Kod źródłowy
Kod źródłowy opracowany w poprzednim artykule znajduje się w repozytorium Git
: https://gitlab.com/qalabs/blog/junit5-selenium-todomvc-example w branchu 1-getting-started
. Klasa testowa, która zostanie zmodyfikowana w tym artykule, to TodoMvcTests
, do jej kodu można przejść bezpośrednio po kliknięciu w link pl.qalabs.blog.junit5.selenium.todomvc.TodoMvcTests.
Właściwa odpowiedzialność metod testowych
Jeśli dobrze przyjrzeć się implementacji testów, to można w niej zauważyć dwie części: pierwszą, związaną z niskopoziomową manipulacją interfejsem użytkownika, wymaganą przez testy (wyszukiwanie elementów, wypełnianie pól, klikanie - mechanika strony) oraz drugą, czyli właściwą logikę testu (tworzenie todo, usuwanie todo - funkcjonalność aplikacji). Do tej pory metody testowe nie posiadały wyraźnego podziału odpowiedzialności. Sprawiało to, że testy były trudniejsze w analizie, a przede wszystkim w utrzymaniu.
Czytając poniższy kod musimy nie tylko zrozumieć, jaka funkcjonalność jest wykorzystywana podczas testu, ale również w jaki sposób musimy zmodyfikować elementy interfejsu w celu wywołania tej funkcjonalności:
1 |
|
Jeżeli tylko rozdzielimy te odpowiedzialności, zastępując fragmenty oznaczone komentarzami wywołaniami nowych metod, które zawierać będą logikę związaną z manipulacją zawartością strony, otrzymamy dużo bardziej czytelny kod:
1 |
|
Metody prywatne, wykorzystywane w teście, dostarczają programiście wysokopoziomowe API
, ukrywające szczegóły implementacyjne, służące obsłudze aplikacji z poziomu użytkownika. Z perspektywy testu, użytkownik tworzy todo, użytkownik usuwa todo, użytkownik widzi, ile todo pozostało do zrobienia itd. Szczegóły technicznie, czyli w jaki sposób todo jest tworzone lub usuwane, metody testowej nie interesuje. Można zatem przyjąć, że test należy traktować jak użytkownika aplikacji, ukrywając przed nim szczegóły implementacji danej funkcjonalności.
Takie podejście znacznie poprawia czytelność kodu, sprawiając dodatkowo, że metody testowe są pewnego rodzaju dokumentacją funkcjonalności testowanej aplikacji. Warto również zwrócić uwagę na “niewyciekanie” WebDriver API
do metod testowych - metody testowe właściwie nic o nim nie wiedzą.
Refaktoryzacja pozostałych metod testowych
Postępując zgodnie z powyższym przykładem, wykorzystując podstawowe techniki refaktoryzacji, takie jak extract method czy extract variable, możemy usprawnić kod dla całej klasy testowej. Dodatkowo też pozbywamy się problemu duplikacji kodu, gdyż poszczególne akcje użytkownika uzyskują swoje metody (API
), przez co zwiększa się możliwość ich ponownego użycia w pozostałych metodach testowych. Takie podejście eliminuje wiele problemów z późniejszym utrzymaniem i rozszerzaniem testów. Na przykład jeżeli zmieni się lokator pola tekstowego w formularzu dodawania todo, zmiana w kodzie nastąpi tylko w jednym miejscu, bez wpływu na istniejące już metody testowe.
W procesie refaktoryzacji warto korzystać ze wsparcia, jakie daje IntelliJ
. W trakcie refaktoryzacji kodu podczas tworzenia tego artykułu korzystałem z głównie z:
- Extract method - https://www.jetbrains.com/help/idea/extract-method.html
- Extract variable - https://www.jetbrains.com/help/idea/extract-variable.html
- Extract parameter - https://www.jetbrains.com/help/idea/javaintroduce.html
Korzystając z powyższych technik, kod metod testowych można usprawnić aż do uzyskania następującego efektu:
1 |
|
Utworzone API
może być z łatwością wykorzystywane do tworzenia kolejnych metod testowych. Na przykład:
1 |
|
Poprawny podział odpowiedzialności oraz usunięcie duplikacji poprzez utworzenie metod prywatnych pozytywnie wpłynęło na jakość i czytelność kodu metod testowych. Usprawnianie można kontunuować aż do uzyskania całkowitej eliminacji powtórzeń, również na poziomie użycia WebDriver API
w nowoutworzonych metodach prywatnych. To spowoduje, że pojawi się dodatkowa warstwa odpowiedzialna za powtarzalne operacje z użyciem WebDriver API
:
1 |
|
Dalsze zmiany mogą doprowadzić do niemal całkowitego wyeliminowania duplikacji. Jako ciekawostkę przedstawię wynik analizy powtórzeń w IntelliJ przed i po refaktoryzacji:
- Przed:
- Po:
Dalsze kroki
Poprawny podział odpowiedzialności oraz usunięcie duplikacji poprzez utworzenie metod prywatnych pozytywnie wpłynęło na jakość i czytelność kodu. Kolejnym krokiem będzie wydzielenie odpowiednich warstw do oddzielnych klas w celu zwiększenie możliwości ponownego użycia nowego API
również w innych klasach testowych.
Repozytorium Git projektu
Kod źródłowy opracowany w artykule znajduje się w repozytorium Git
: https://gitlab.com/qalabs/blog/junit5-selenium-todomvc-example w branchu 2-tests-responsibility
.