Ten wzorzec projektowy musisz znać. Zalety Page Object Model

Wzorzec projektowy Page Object jest obecnie jednym z najpopularniejszych podejść do automatyzacji testów webowych. Znajduje zastosowanie we frameworkach tworzonych według paradygmatu programowania obiektowego i pozwala na pełne wykorzystanie jego zalet. Na czym polega Page Object i w czym dokładnie może pomóc?
Agata Ostaszewska-Smykała. Product Engineer w Axxiome Polska, związana z branżą IT i testowaniem oprogramowania od prawie siedmiu lat. Absolwentka informatyki, studentka filologii angielskiej, wolny czas poświęca literaturze i nauce języków obcych, a także rozwojowi umiejętności programowania w Javie. Od niedawna prowadzi bloga znerdziej.pl, skierowanego przede wszystkim do osób rozpoczynających karierę w IT.
Najważniejszą ideą, stojącą u podstaw wzorca Page Object, jest opakowanie strony i jej elementów w odpowiednie klasy i ich pola. Należy pamiętać, że wbrew temu, co sugeruje powszechnie przyjęte nazewnictwo, klasą niekoniecznie musi być cała strona – w praktyce częściej zdarza się, że jest nią określona funkcjonalna część strony, na przykład panel czy lista wyników wyszukiwania. Elementy strony zaczynają odpowiadać polom klasy, a czynności, które można za ich pomocą wykonać wykonać – metodom tej klasy. Powstaje w ten sposób swojego rodzaju API (interfejs aplikacji), umożliwiający testom wykonywanie czynności na stronie bez odwoływania się do ścieżek do elementów. Upraszcza to prace nad automatyzacją i poprawia czytelność samych metod testowych.
Spis treści
Architektura
W typowym przypadku kod rozdzielony jest na klasy opakowujące testowane strony (przykładowo zgromadzone w folderze o nazwie Pages) i na scenariusze testowe (znajdujące się na przykład w folderze Tests). Testy korzystają z obiektów klas z folderu Pages, aby wykonywać poszczególne kroki na stronie. Jeżeli chodzi o asercje, można znaleźć zarówno zwolenników umieszczania ich w testach, jak i w klasach stron. Zwolennicy obu rozwiązań mają swoje argumenty, jednak najważniejsze wydaje się, aby konsekwentnie trzymać się wybranej opcji i nie mieszać dwóch podejść.
Do znajdowania elementów na stronie wykorzystuje się koncepcję o nazwie Page Factory. Polega ona na zadeklarowaniu obiektów typu WebElement, a następnie oznaczeniu ich adnotacją @FindBy wraz ze ścieżką szukanych elementów (przykładowo w postaci xPath czy ścieżki CSS). Elementy te następnie inicjalizuje się poprzez wywołanie statycznej metody initElements klasy PageFactory, dostępnej jako część biblioteki WebDrivera. Metodę tę wywołuje się w konstruktorze klasy. Być może brzmi to skomplikowanie, jednak prosty przykład powinien wszystko wyjaśnić.
Przykład
Załóżmy, że istnieje strona logowania, składająca się z trzech elementów – pola tekstowego przyjmującego nazwę użytkownika, pola tekstowego przyjmującego hasło i przycisku „Zaloguj”. Przy tak prostej stronie wydaje się zasadne, aby cała strona odpowiadała jednemu obiektowi. Tworzymy zatem folder Pages, a w nim LoginPage.java:
1 2 3 4 5 6 7 8 |
public class LoginPage{ WebDriver driver; //konstruktor public LoginPage(WebDriver driver){ this.driver = driver; } } |
Na początek deklarujemy w klasie elementy strony, korzystając z PageFactory (w przykładzie pokazano różne sposoby wyszukiwania elementów – w praktyce dałoby się to uprościć):
1 2 3 4 5 6 7 8 |
@FindBy(xpath=” //*[@id="username"]”) WebElement usernameInput; @FindBy(id=”pass”) WebElement passwordInput; @FindBy(className=”submitBtn”) WebElement loginButton; |
Do konstruktora dodajemy inicjalizację elementów, przez co wygląda on teraz następująco:
1 2 3 4 |
public LoginPage(WebDriver driver){ this.driver = driver; PageFactory.initElements(driver, this); } |
Pozostaje już tylko napisać metody umożliwiające wykonywanie czynności za pomocą elementów strony:
1 2 3 4 5 6 7 8 9 10 11 |
public void enterUsername(String username){ usernameInput.sendKeys(username); } public void enterPassword(String password){ passwordInput.sendKeys(password); } public void login(){ loginButton.click(); } |
Aby przeprowadzić weryfikację logowania, potrzebny będzie obiekt strony, która otworzy się po poprawnym zalogowaniu. Tworzymy więc kolejną klasę w folderze Pages – WelcomePage.java. Przykładowo mogłaby ona wyświetlać powitalny tekst „Welcome” i nazwę zalogowanego użytkownika oraz udostępniać przycisk wylogowania. Klasa dla takiej strony wyglądałaby następująco:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
public class WelcomePage{ WebDriver driver; @FindBy(id=”welcomeTxt”) WebElement welcomeText; @FindBy(id=”loggedUser”) WebElement loggedUser; @FindBy(id=”logoutBtn”) WebElement logoutButton; public WelcomePage(WebDriver driver){ this.driver = driver; PageFactory.initElements(driver, this); } public String getWelcomeTxt(){ return welcomeText.getText(); } public String getLoggedUser(){ return loggedUser.getText(); } public void logout(){ logoutButton.click(); } } |
Kiedy klasy stron są gotowe, przechodzimy do pisania testu – dodajemy plik US01.java w folderze Tests:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
public class US01 { WebDriver driver; @Before public void setup(){ //ustawienia drivera i przejście do naszej strony logowania } @Test() public void correctLogin(){ String correctUsername = “correctusername”; String correctPassword = “correctpass1”; Loginpage loginPage = new LoginPage(driver); loginPage.enterUsername(correctUsername); loginPage.enterPassword(correctPassword); loginPage.login(); WelcomePage welcomePage = new WelcomePage(driver); Assert.assertTrue(welcomePage.getWelcomeText() .contains(“Welcome”)); Assert.assertTrue(welcomePage.getLoggedUser() .contains(correctUsername); } } |
Podsumowanie
Page Object Model pozwala na wykorzystanie zalet programowania obiektowego podczas implementacji testów automatycznych. Kod klas reprezentujących strony może zostać wielokrotnie wykorzystany w różnych testach, natomiast same scenariusze stają się czytelne dzięki temu, że składają się z wywołania metod odpowiadających poszczególnym krokom. Uproszczone jest również utrzymanie takich testów – w razie gdyby ścieżka do elementu została zmieniona, potrzebna będzie jej aktualizacja jedynie w klasie reprezentującej stronę. Podobnie w przypadku zmiany sposobu wykonywania danej czynności na stronie – wystarczy zaktualizować odpowiadającą jej metodę, bez konieczności modyfikacji wszystkich korzystających z niej testów.
Zdjęcie główne artykułu pochodzi z pexels.com.
Podobne artykuły

Automatyzuj przewidywalną część pracy. Zaoszczędzony czas poświęć na dogłębną analizę kodu

Czy każdy programista powinien umieć testować? Devdebata

Testowanie oprogramowania krok po kroku. Zobacz, jak tworzymy strategię testowania

Za jakość odpowiada nie tylko dział QA, ale wszyscy członkowie zespołu. Wywiad z Radosławem Inczewskim

Jak opracować strategię testowania oraz inne popularne problemy w C++

QA retro czy retro QA? 10 lat w testach manualnych - subiektywne studium przypadku

W jaki sposób Wirex - firma działająca na rynku kryptowalut testuje transakcje finansowe Visa i Mastercard?
