Wyślij zapytanie Dołącz do Sii

Od jakiegoś czasu korzystam z jednego z najlepiej rozwijających się narzędzi do automatyzacji testów UI (ale nie tylko), którym jest Playwright. W tym artykule chcę Ci zaprezentować, jak zacząć i dlaczego warto korzystać z tego narzędzia oraz jak wyglądają testy automatyczne w Playwright w praktyce.

Początki Playwrighta

Microsoft opublikował Playwrighta w 2020 roku. Jest to narzędzie open source, stworzone przez Andreya Lushnikova, który pracował wcześniej przy innym popularnym produkcie do automatyzacji, jakim jest, rozwijany przez Google, Puupeteer. Playwright służy do automatyzacji akcji w przeglądarce, ale również umożliwia automatyzację API.

Mocne strony Playwrighta

Narzędzie posiada szereg interesujących zalet, które sprawiają, że warto się nim zainteresować. Opiszę je poniżej.

Auto Wait

Jeżeli pracowaliście kiedyś nad testami automatycznym UI, to zdajecie sobie sprawę, jak dużym problemem jest obsługa czekania na różne elementy dynamiczne, które znajdują się na stronie. W Selenium WebDriver poleca się korzystać z tzw. Explicit waitu, który powinien rozwiązywać ten problem. Jednak czasami znalezienie odpowiedniego waitu nie jest takie proste. Ma na to wpływ, jak wiele javascriptu i operacji asynchronicznych jest używanych na naszej stronie.

Playwright korzysta z tzw. mechanizmu auto-wait. Co to oznacza? W wielu sytuacjach nie musimy dokładać dodatkowego czekania na elementy, bo Playwright sam domyślnie oczekuje elementów i akcji. Oczywiście, gdy natrafimy na bardziej złożoną sytuację, w której potrzebujemy poczekać na jakiś element, to Playwright dostarcza nam metody, z których możemy skorzystać.

Korzystanie z różnych języków programowania

Obecnie Playwright wspiera kilka popularnych języków programowania. Są to:

  • Java,
  • C#,
  • JS/TS,
  • Python.

Dzięki temu, rozwiązanie w wersji dla różnych języków znajduje coraz szersze zastosowanie na rynku.

Dokumentacja

Playwright ma świetną dokumentację. Korzystanie z metod jest opisane na praktycznych przykładach, które pomagają skorzystać z wielu możliwości aplikacji. Również dokumentacja, która pojawia się, gdy wywołujemy jakąś metodę w IDE, jest często wystarczająca do tego, aby ją realnie wykorzystać.

Popularność narzędzia

Warto zauważyć, że liczba użytkowników narzędzia Playwright rośnie, co można zobaczyć na poniższej grafice.

Playwright, spośród bibliotek używanych w testach, poprawił wynik wykorzystania wśród społeczności z 3% w 2020 roku do 10% w 2021 roku. Ten ranking odnośni się do wersji JS/TS Playwrighta, jednak moim zdaniem jest to zauważalny skok popularności, który będzie prawdopodobnie również odnotowany przy innych wersjach językowych narzędzia.

Poprawiła się również świadomość na temat Playwrighta wśród społeczności – z 19% w 2020 roku do 34% rok później.

Przy wyborze narzędzi warto zwracać uwagę na ich popularność oraz pozytywny odbiór przez społeczność. Playwright posiada oba aspekty.

Częstotliwość dostarczania nowych wersji

Playwright – częstotliwość dostarczania nowych wersji
Ryc. 3 Playwright – częstotliwość dostarczania nowych wersji

Niewątpliwie warto wspomnieć o szybkim rozwoju Playwrighta. Co około dwa tygodnie dodawana jest nowa wersja z usprawnieniami (częstotliwość zmian można sprawdzić na GitHubie).

Przy wyborze potencjalnego narzędzia zawsze zwracam uwagę na rozmiar społeczności, która za nim stoi. W tym wypadku jest to Microsoft i jego pracownicy, ale również coraz więcej zaangażowanych osób spoza firmy.

Przeglądarki wspierane przez Playwrighta

Obecnie Playwright wspiera wszystkie najpopularniejsze przeglądarki internetowe, czyli:

  • Chrome,
  • Edge,
  • Firefox,
  • Opera,
  • Safari.

Rozwiązania oparte na Electronie również mają eksperymentalne wsparcie dla wersji JS/TS.

Projekty wykorzystujące Playwrighta

Coraz więcej projektów chwali się, że korzysta z narzędzia Playwright w swoich testach UI. Są to popularne inicjatywy open source, ale również rozwiązania komercyjne. Poniżej kilka przykładów:

Słabe strony Playwrighta

W przypadku wszystkich narzędzi zdarzają się momenty, gdy jakaś metoda nie działa poprawnie w określonej sytuacji. Jako użytkownik Playwrighta spotkałem się z problemami sporadycznie i zawsze udawało mi się znaleźć rozwiązanie. Nie mogę natomiast wykluczyć, że możemy trafić na okoliczności, w których rozwiązania nie znajdziemy. Warto wówczas porozmawiać z twórcami narzędzia – są oni dostępni i aktywnie biorą udział w odpisywaniu na zgłoszenia, które trafiają na GitHuba.

Napiszmy pierwszy test!

Po krótkim, teoretycznym wprowadzeniu możemy przejść do napisania naszego pierwszego testu automatycznego w tej aplikacji.

Implementacja testu automatycznego

Przygotowany przeze mnie test będzie polegał na zautomatyzowaniu prostego przypadku dla testowo stworzonego sklepu. Scenariusz testu wygląda tak:

  1. Przejdź na stronę seleniumsklep.pl
  2. Kliknij w wybrany produkt na podstawie jego nazwy.
  3. Przejdź do koszyka i sprawdź, czy cena na podsumowaniu jest zgodna z ceną, która znajduje się w szczegółach produktu.

Przechodzimy do Visual Studio i rozpoczynamy pracę od utworzenia projektu package library. Jest to preferowany typ projektu, który zastosujemy. Kolejnym krokiem będzie dodanie potrzebnych paczek za pomocą NuGet packages. W naszym przypadku:

  • Playwright,
  • Playwright Nunit.
Dodawanie potrzebnych paczek
Ryc. 6 Dodawanie potrzebnych paczek

Playwright Nunit zawiera przydatne klasy, które pomagają współpracować narzędziom np. w kontekście uruchamiania testów w sposób współbieżny.

Kolejnym krokiem jest stworzenie potrzebnych katalogów tak, aby od samego początku porządkować nasze rozwiązanie.

Tworzenie katalogów
Ryc. 7 Tworzenie katalogów

Najpierw tworzymy katalog „Pages”, w którym umieścimy wszystkie page objecty potrzebne nam do testu automatycznego. Kolejnym niezbędnym katalogiem jest „Tests”. 

fragment kodu

W klasie BaseSetup mamy dwie metody, których użyjemy we wszystkich testach dziedziczących z tej klasy. Metoda „Setup()” na początku inicjalizuje obiekt Playwrighta. Robimy to w linii 17. Przed nią deklarujemy trzy pola, które będą nam potrzebne w dalszej pracy.

Są to pola:

  • Playwright,
  • Browser,
  • Context.
fragment kodu

W metodzie Setup() inicjalizujemy pole Browser, które definiujemy, aby ustawić jakiej przeglądarki będziemy używać w testach. Jeżeli nie podamy parametru Headless, nie zobaczymy przebiegu testów, ponieważ uruchomią się bez trybu graficznego. Jest to przydatna opcja, dzięki której unikamy wyskakujących okiem z testami. 

Kolejną rzeczą, którą możemy ustawić w tym miejscu jest Channel. Playwright pozwala nam zdecydować, jaką wersję Chrome użyć w naszym teście automatycznym. W bardzo prosty sposób możemy zdefiniować, że chcemy skorzystać np. z Chrome czy z Edge’a w wersji beta. Może być to bardzo przydatne do sprawdzenia działania naszej aplikacji z nadchodzącymi wersjami przeglądarek.

fragment kodu

fragment kodu

Następnie przechodzimy do zdefiniowania Contextu. Czym jest Context? Inicjalizujemy pole Context, które pozwala obsługiwać sesję danej przeglądarki. Wyróżnikiem Playwrighta jest to, że potrafi obsługiwać więcej niż jedną sesję przeglądarki na raz. Dodatkowo każde z okien ma „Focus”, więc nie musimy się przełączać pomiędzy nimi, jeżeli chcemy wykonać jakąś akcję.

Również w obiekcie Browser moglibyśmy od razu skorzystać z metody NewContextAsync(), jednak twórcy Playwrighta polecają, żeby tworzyć kontekst za każdym razem. Każdy „Context” przechowuje oddzielny cache i ciasteczka.

fragment kodu

Kolejnym krokiem jest zdefiniowanie tzw. Tracingu. Ta metoda pozwala na zbieranie logów podczas działania testu automatycznego. Śledzić możemy:

  • Screenshots – tworzenie zrzutu ekranu po każdej akcji,
  • Snapshots – zbieranie zawartości DOM-u po każdej akcji oraz zbieranie informacji z „networku”, czyli wszystkie żądania i informacje z konsoli,
  • Sources – zbieranie informacje na temat tego, która linia kodu była uruchomiona w danym momencie.

Kod źródłowy testu automatycznego

fragment kodu

Przechodząc do kodu źródłowego testu automatycznego, zaczynamy od zdefiniowania nazwy metody. W tym przypadku jest to EnterToShop_AddProductToBasket_CheckProductPriceInSummary()

Jako parametr definiujemy „option”, dzięki któremu w sposób dynamiczny możemy przekazać nazwę artykułu, wybieranego przez test. Odpowiada na niego atrybut „TestCase”. Każda kolejna linia w postaci atrybutu TestCase z argumentem, definiuje nam kolejny przypadek testowy.

Zaczynamy od zdefiniowania obiektu page. Odpowiada on za kontrolę pojedynczej zakładki w przeglądarce (oczywiście skojarzonej z naszym kontekstem).

HomePage

fragment kodu

Definiujemy page object dla strony HomePage. Sama strona posiada listę interesujących nas produktów.

Strona z interesującymi nas produktami
Ryc. 6 Strona z interesującymi nas produktami

Następnie tworzymy konstruktora dla tej klasy. Konstruktor będzie przyjmował parametr jako obiekt page, który zawiera metody pozwalające kontrolować akcje związane z tą stroną. Kolejnym krokiem jest zdefiniowanie pola ProductTitles z selektorem odpowiadającym nazwie każdego z produktów.

Potrzebujemy również metody SelectDefineProduct, która odpowiada za kliknięcie w dany produkt na podstawie jego nazwy.  

fragment kodu

fragment kodu

  • Metoda QuerySelectorAllAsync – pozwala nam na pobranie wszystkich elementów na podstawie zadanego selectora.
  • Metoday InnerText – umożliwia pobranie tekstu z danego elementu.
  • Metoda ClickAsync – klika w element, który chcemy wybrać.

Ciekawą właściwością Playwrighta jest to, że większość wykorzystywanych metod, posiada dodatkowe sposoby użycia, które poszerzają jego możliwości.

fragment kodu

Jedną z nich jest metoda ClickAsync. Pozwala nam zdefiniować, ile razy chcemy kliknąć lub określić czekanie po kliknięciu.

Metod, których możemy użyć na danym obiekcie jest wiele. Oto kilka z nich:

Wybrane metody - lista
Ryc. 7 Dostępny wybór metod

Waity

Tak jak wspominałem dla większości operacji nie mamy potrzeby dodawania dodatkowych waitów. Jednak, możemy skorzystać z tych metod, gdy nasza strona jest bardziej skomplikowana i zależy nam na dodaniu czekania na element.

Metody czekania na element
Ryc. 8 Metody czekania na element

Możemy poczekać, aż pop-up lub określone żądanie się pojawią. Ta metoda jest przydatna, gdy przechodzimy pomiędzy stronami i potrzebujemy poczekać dłużej na załadowanie strony.

fragment kodu

fragment kodu

Wracając do testów: następny krokiem w linii 18 jest skorzystanie z metody GoToAsync(), która przejdzie do określonej strony internetowej. Adres do strony zapisujemy w osobnej klasie TestSettings.EnvUrl. Takie wartości jak adres do środowiska najlepiej przechowywać w osobnych klasach/plikach. Metoda GoToAsync ma również możliwość dodania dodatkowego czekania na załadowanie strony. Adres strony zapisujemy we właściwościach w klasie TestSettings.

fragment kodu

Po tym kroku, w teście przechodzimy do wywołania metody SelectDefineProduct(option). To ona kliknie w określony produkt. Kolejnym działaniem jest dodanie klasy DetailsProductPage, w której zaczynam od stworzenia pól potrzebnych do metod używanych na dalszych etapach tego testu.

Pole AddToBasketBtn odpowiada przyciskowi na stronie.
Ryc. 9 Pole AddToBasketBtn odpowiada przyciskowi na stronie
Pole ProceedToCheckoutBtn odpowiada przyciskowi na stronie
Ryc. 10 Pole ProceedToCheckoutBtn odpowiada przyciskowi na stronie
Pole CurrentPrice odpowiada obecnej cenie produktu, która znajduje się na stronie szczegółów produktu
Ryc. 11 Pole CurrentPrice odpowiada obecnej cenie produktu, która znajduje się na stronie szczegółów produktu

Następnie, dodajemy konstruktor, który przez argument będzie przyjmował obiekt page, pozwalający na wykonywanie akcji związanych ze stroną.

fragment kodu

Definiujemy pole AddToBasektBtn. Aby dodać element w Playwright, korzystamy z metody _page.Locator(„nazwa_selectora”), która na podstawie podanego selectora pozwala uzyskać dostęp do elementu za pomocą Playwrighta. Kolejnym elementem, który definiujemy w tej klasie, jest odpowiednik przycisku „Proceed to Checkout”.

By test zadziałał, kolejne wymagane pole to „CurrentPrice”. Pozwala ono na pobranie aktualnej ceny za nasz przedmiot.

Po zdefiniowaniu wszystkich pól niezbędnych dla testu przechodzimy do zdefiniowania dwóch prostych metod:

  • metoda AddProductToCart() zawiera kliknięcie przycisku dodania do koszyka,
  • metoda ProceedToCheckout() jest analogiczną metodą do kliknięcia dla przycisku „Proceed to checkout”.
fragment kodu

Definiuję metodę GetCurrentProductPrice, która odpowiada za pobranie obecnej wartości ceny ze szczegółów tego produktu. Potrzebujemy jeszcze dodać metodę ParseEuroToDouble. Jest to metoda, która stosuje proste tzw. parsowanie, które w tym przypadku usuwa symbol € z tekstu. W tym wypadku musimy to zrobić, ponieważ element jest zdefiniowany w ten sposób w HTML-u strony.

fragment kodu

Oczywiście jest to jedna z dróg, ale można podejść do tego na wiele sposobów. Innym pomysłem jest skorzystanie z wyrażenia regularnego, które pozwoliłoby na pobranie liczbowej wartości z tekstu. Metoda ParseEuroToDouble wygląda tak:

fragment kodu

Wracamy do kodu źródłowego testu. Wywołujemy metody, które pozwolą dodać produkt do koszyka.

fragment kodu

W kolejnej linii inicjalizujemy obiekt SummaryCartPage. Jest to obiekt reprezentujący klasę SummaryCartPage.

fragment kodu

W tej klasie oprócz zdefiniowania konstruktora, dodajemy pole odpowiadające elementowi kwoty w podsumowaniu koszyka.

element kwoty

Również w tym miejscu korzystamy z metody ParseEuroToDouble, bo w tej sytuacji jest porównywalna. Po dodaniu tej metody, wracamy do kodu testu i porównujemy wartość zmiennej currentTotalPrice z productPrice. To porównanie korzysta z biblioteki FluentAssertions, którą dodajemy poprzez NuGeta. Jest to biblioteka do asercji, która pozwala na bardziej czytelny zapis niż standardowe metody z klasy Assert. Dalej, przechodzimy do uruchomienia testu. Możemy tego dokonać za pomocą dotnet test z poziomu VS oraz z poziomu VS i R#.

test
Ryc. 12 Uruchamianie testu
fragment kodu

Podsumowanie

W artykule pokazałem Playwrighta w praktyce i przedstawiłem kilka cech, które mogą Cię zainteresować i przekonać do spróbowania pracy z tym narzędziem.

W następnej części chciałbym zaprezentować jak skorzystać z Trace Viewer, przydatnej funkcji, która pozwala nam przeglądać zebrane logi z testów. Przedstawię także inne ciekawe właściwości tego narzędzia.

Kod znajdziecie w przygotowanym repozytorium.

Ocena:
Autor
Avatar
Michał Ślęzak

Test Architect w Sii Polska. Automatyzacją testów zajmuje się od kilku lat. Prowadzi bloga: testingplus.me oraz jest jednym z liderów PTaQ.org i prowadzącym podcastu TestingParrot: jednego z pierwszych podcastów o testowaniu w Polsce. Pisał dla geek.justjoin.it / blog.testuj.pl / Programista Magazyn. Poza pracą lubi rozwój osobisty, czytanie książek i oglądanie seriali.

Zostaw komentarz

Twój adres e-mail nie zostanie opublikowany.

Może Cię również zainteresować

Pokaż więcej postów

Bądź na bieżąco

Zasubskrybuj naszego bloga i otrzymuj informacje o najnowszych wpisach.

Otrzymaj ofertę

Jeśli chcesz dowiedzieć się więcej na temat oferty Sii, skontaktuj się z nami.

Wyślij zapytanie Wyślij zapytanie

Natalia Competency Center Director

Get an offer

Dołącz do Sii

Znajdź idealną pracę – zapoznaj się z naszą ofertą rekrutacyjną i aplikuj.

APLIKUJ APLIKUJ

Paweł Process Owner

Join Sii

ZATWIERDŹ

This content is available only in one language version.
You will be redirected to home page.

Are you sure you want to leave this page?