Selenium 77. Page Object Model: części wspólne różnych stron na przykładzie HeaderPage

Interesuje Cię ten kurs?

Dołącz do listy mailingowej, a poinformuję Cię o otwarciu zapisów.

Po małym refaktorze możemy przejść do kolejnej lekcji, a w niej przepisz ze mną kolejny już test. Tym razem pokażę Ci jak rozwiązać nowy dla nas problem, a mianowicie jak poradzić sobie w sytuacji, gdy mamy na stronie jakieś moduły albo części wspólne. Wyjaśnię to na przykładzie HeaderPage czyli klasy, która będzie reprezentowała nagłówek strony.

Uwaga: plik z projektem testowym, na którym pracujemy w lekcjach dotyczących POM wymaga uzyskania dostępu. Dostaniesz go tutaj.

 

Zaktualizowane klasy

Klasa testowa: CartTests

Ukryta treść

Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.

Bazowa klasa testowa: BaseTest

Ukryta treść

Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.

Klasa Page Object: CartPage

Ukryta treść

Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.

Klasa Page Object: CategoryPage

Ukryta treść

Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.

Klasa Page Object: ProductPage

Ukryta treść

Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.

Klasa Page Object: BasePage

Ukryta treść

Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.

Klasa Page Object: HeaderPage

Ukryta treść

Nie masz dostępu do tego kursu. Wykup dostęp albo zaloguj się, by móc zobaczyć pełną lekcję.

Lista lekcji dotyczących Page Object Model:

Wsparcie merytoryczne

Nie masz aktywnego członkostwa. Wykup dostęp albo Zaloguj się, by móc zadawać pytania.

  1. Hej 🙂 Mam takie pytanie odnośnie tej lekcji:
    A czy nie można by było umieścić wszystkich metod powiązanych z interakcją z tym headerem w BasePage? W końcu BasePage ma zawierać metody, które byłyby dostępne z każdej podstrony sklepu, a header jest częścią wspólną wszystkich PageObjectów. Rozchodzi mi się o to, czy to nie uprościłoby nam kodu, gdybyśmy się trzymali tego, że BasePage jest częścią wspólną dla PageObjectów, bez konieczności tworzenia kolejnych klas? Czy to jednak jest zły pomysł? I jeśli zły, to dlaczego?

    Odpowiedz
    • Halko! Wszystko można, pytanie czy warto. I jedyną sensowną odpowiedzią na to pytanie jest: to zależy. Są pewne zagrożenia w podejściu, które zaproponowałeś. Ponieważ BasePage jest trochę takim niewiadomo czym bardzo łatwo nam będzie ładować tam wszystko, co nigdzie indziej nam nie pasuje albo po prostu nam się nie chce tworzyć nowej klasy. W BasePage powinno się znajdować jak najmniej rzeczy moim zdaniem, bo to zwiększy czytelność tej klasy, która i tak sama z siebie jest tworem dosyć abstrakcyjnym, bo nie reprezentuje konkretnej strony. Dlatego też jak napakujemy tam elementów innych sekcji, które spokojnie mogłyby dostać swoją klasę, to zrobi nam się bałagan i zaraz sami nie będziemy wiedzieć co jest gdzie. Z drugiej strony jednak zależy ile metod związanych z inną sekcją byśmy tam wrzucili. Zwróć uwagę, że zamykanie tego paska na dole informującego o tym, że mamy do czynienia z wersją demo sklepu wrzuciłam właśnie do BasePage. Dlaczego? A bo to jest tylko jedna metoda i nie ma tez absolutnie żadnej perspektywy na rozszerzanie tego w przyszłości bo na tym pasku i tak nic więcej nie ma. Z headerem jest tak, że dopóki używasz jednej, może dwóch metod to pewnie ok jest wrzucenie tego do BasePage, może nawet lepiej, bo nie budujemy nowej klasy na jakąś drobnostkę. Co do Twojego argumentu z uproszczeniem kodu: tak, kod będzie prostszy, ale z drugiej strony akcji związanych z headerem nie będziesz wtedy szukać w klasie HeaderPage ale BasePage, więc musisz dobrze znać swój framework, żeby wiedzieć gdzie tego szukać. Myślę tutaj głównie o sytuacji, gdy na jednym frameworku pracuje kilka osób.
      Nie odpowiem Ci więc na to pytanie jednoznacznie, musisz sam to sobie wszystko wyważyć i popróbować w zależności od sytuacji. Możesz spokojnie zacząć od wrzucenia tego w BasePage i w miarę rozrastania się frameworka (zakładając, że będzie się rozrastał) pewnie sam zauważysz, że robi się trochę bałagan. Wtedy możesz się zwrócić w kierunku dedykowanych klas.

      Odpowiedz
  2. Cześć,
    we wszystkich dotychczasowych testach używaliśmy metody closeDemoNotice(), do zamknięcia informacji o wersji demonstracyjnej sklepu. Wprowadziliśmy tą metodę do BasePage, żeby móc z niej zawsze skorzystać, ale w teście z tej lekcji nie jest ona użyta.
    Domyślam się, że powodem jest użycie w pętli tych samych metod. Za pierwszym podejściem metoda closeDemoNotice() zadziała, ale w kolejnych już nie znajdzie paska z informacja i dostaniemy błąd. Mimo wszystko wspominałaś, że warto zamknąć ten pasek, bo może przeszkadzać.
    Co myślisz o tym, żeby dodać metodę closeDemoNotice() do wykonania w pętli, ale przerobić ją tak, że przed próba zamknięcia paska jest w if sprawdzane czy w ogóle pasek jest wyświetlony?
    [java]public void closeDemoNotice() {
    if (driver.findElement(demoNoticeLocator).isDisplayed()) {
    driver.findElement(demoNoticeLocator).click();
    }
    }[/java]
    Wtedy za pierwszym przejściem w pętli zamkniemy pasek informacyjny, a kolejne przejścia pętli przejdą.
    Ja tak zrobiłem i działa. Chyba, że masz inny pomysł?

    Odpowiedz
    • Im dłużej patrzę na te testy, tym bardziej przekonana jestem, że nie mam tam zamknięcia tego demo notice tylko dlatego, że zapomniałam, a działało bez tego. Pętla imo nie ma nic do tego, bo przecież można to zamknąć przed pętlą i wybór zapamiętuje się w ciasteczkach, więc nie ma potrzeby robienia tego za każdym razem w każdym obrocie pętli. Co do Twojego pytania z ifem: tutaj jestem bardzo kategoryczna i mówię żadnych ifów w testach. Wrzucanie ifa do metody, który ma zadanie ocenić stan aplikacji i na tej podstawie wybrać akcję to jak powiedzenie: nie wiem w jakim stanie jest aplikacja na tym etapie testu. A jak nie wiesz, to skąd masz wiedzieć czy to błąd czy nie? Pisząc testy mamy wiedzieć jak aplikacja się zachowa, a nie tworzyć metody, które same zadecydują co robić. Potem też debugowanie takiego testu może być wesołe, no bo nie wiemy co test zrobił (czy zamknął ten pasek, czy nie musiał). Można mieć jakieś srogi logi zaimplementowane żeby wiedzieć, ale testy powinny być napisane tak, że patrzysz na komunikat z asercji i od razu wiesz co poszło nie tak. W takich testach to jest niemożliwe.

      Odpowiedz