Powrót do: Praktyczne wprowadzenie do testów automatycznych z Playwright
Rozwiązanie: Kolejny test pulpitu
Dodatkowe materiały
Link do testowanej stronyTwoim zadaniem było przygotowanie testu automatycznego dla operacji doładowania telefonu na stronie Pulpit. Poniżej znajdziesz porady jak podejść do tego zadania oraz jego rozwiązanie 😉
Nagrywanie testu
Aby nagrać test za pomocą codegen użyj polecenia:
npx playwright codegen [adres]
czyli np:
npx playwright codegen https://demo-bank.vercel.app/
Uruchomienie jednego testu
Podczas pisania nowego testu warto często go uruchamiać, aby sprawdzić, czy podążamy w dobrą stronę 😉 Aby skupić się tylko na tym, co piszemy, warto uruchamiać tylko jeden testy
Aby to zrobić, skorzystaj z konstrukcji only()
np.:
test.only('successful mobile top-up', async ({ page }) => {
Przerywanie działającego procesu w konsoli
Kliknij w terminalu, w którym proces node.js nadaj jest uruchomiony, a następnie użyj skrótu CTRL + C, aby przerwać działający proces.
Komentowanie wiele linii
Zaznacz wiele linii i użyj skrótu CTRL + /
Duplikacja danej linii
Ustaw kursor na linii, którą chcesz zduplikować, a następnie naciśnij ALT + SHIFT + ↓
Selektory i wyszukiwanie elementów na stronie
Aby wyszukać elementy w przeglądarce za pomocą selektorów CSS otwórz narzędzia developerskie (DevTools). Następnie otwórz konsolę i użyj następującej konstrukcji:
$$(‘selektor CSS’)
Wyszukiwaniu elementów w przeglądarce omawiamy w naszych lekcjach bonusowych:
Cały kod
Zawartość pliku pulpit.spec.ts z rozwiązaniem zadania w postaci testu successful mobile top-up:
import { test, expect } from '@playwright/test'; test.describe('Pulpit tests', () => { test('quick payment with correct data', async ({ page }) => { await page.goto('https://demo-bank.vercel.app/'); await page.getByTestId('login-input').fill('testerLO'); await page.getByTestId('password-input').fill('password'); await page.getByTestId('login-button').click(); await page.locator('#widget_1_transfer_receiver').selectOption('2'); await page.locator('#widget_1_transfer_amount').fill('150'); await page.locator('#widget_1_transfer_title').fill('pizza'); await page.getByRole('button', { name: 'wykonaj' }).click(); await page.getByTestId('close-button').click(); await expect(page.locator('#show_messages')).toHaveText('Przelew wykonany! Chuck Demobankowy - 150,00PLN - pizza') }); test('successful mobile top-up', async ({ page }) => { await page.goto('https://demo-bank.vercel.app/'); await page.getByTestId('login-input').fill('testerLO'); await page.getByTestId('password-input').fill('password'); await page.getByTestId('login-button').click(); await page.locator('#widget_1_topup_receiver').selectOption('503 xxx xxx'); await page.locator('#widget_1_topup_amount').fill('50'); await page.locator('#uniform-widget_1_topup_agreement span').click(); await page.getByRole('button', { name: 'doładuj telefon' }).click(); await page.getByTestId('close-button').click(); await expect(page.locator('#show_messages')).toHaveText('Doładowanie wykonane! 50,00PLN na numer 503 xxx xxx') }); });
Szczególnie cenna jest ta analiza krok po kroku. Sprawdzanie lokatorów na różne sposoby, gdzie dzieje się faktycznie akcja na stronie. A potem rozważenie optymalnego dla danego testu wyboru.
Myślę, że dla osób z doświadczeniem w testach manualnych może to jest intuicyjne ale dla nowicjuszy to zaprezentowanie “jak myśleć pisząc testy” jest bezcenne. 🙂
Dzięki wielkie!
Ciesze się, że Ci się podoba nasz sposób 🙂 Zatem korzystaj i stosuj 🙂
Czy konstrukcja only() nadal jest wspierana?
Tak, cały czas możesz używać
test.only()
, aby uruchamiać tylko jeden test 🙂https://playwright.dev/docs/test-annotations#focus-a-test
Hej mam pytanie o tego checkboxa, przyznam, że zamiast używać codegen do nagrania testu to spróbowałem po prostu z devtoolsami i szybko poszło, ale kod na końcu się różnił od tego co podaliście, ale wszystko działa. Sięgnąłem też do dokumentacji playwrighta i zauważyłem, że są tam sugerowane lokatory elementów i raczej odradza się używanie CSS i Xpath jeśli nie jest to konieczne, ze względu na trudność w utrzymaniu testów (cssy i xpathy łatwo ulegają zmianom). Jednak ja złapałem element #widget_1_topup_agreement zamiast uniform-widget_1_topup_agreement span, kierowałem się przy tym myśleniem, że mimo wszystko to Id, odwołuje się bezpośrednio do checkboxa (który jest inputem), a uniform-widget_1_topup_agreement span odwołuje się do jakiegoś elementu opakowującego/trzymającego w sobie ten input. Założyłem, że prędzej ten div może ulec zmianie niż sam input, który może co najwyżej zostać przeniesiony. Czy tutaj istnieje jakieś jednoznaczne stwierdzenie, które z tych rozwiązań jest lepsze czy “to zależy”?
U mnie:
W podanym rozwiązaniu przez jaktestowac.pl:
Druga rzecz, kiedy po zrobieniu zadania, spróbowałem zrobić je jeszcze raz z codegen zauważyłem, że na sam koniec kiedy zamykam ekran informujący o tym, że doładowanie zakończyło się powodzeniem, playwright inspektor czasem zapisuje kliknięcie buttona OK jako getByRole a czasem jako page.getByTestId, czy oba te rozwiązania są równie dobre?
Ogólnie Twoje rozwiązanie również wygląda poprawnie 🙂
Również myślę, że Twoje przemyślenia nt zmienności elementów są poprawne – czyli, że lepiej odnieść się do konkretnego elementu przez jego ID, niż po typie elementu 🙂 I też sugerowałbym odnosić się do ID, które jest najbliżej interesującego nas elementu.
To zależy odnosiłoby się do projektów, w których elementy nie mają ID i musimy wybierać “mniejsze zło” 😉
Działanie codegen może się zmieniać między wersjami Playwrighta… i jak widać również w zależności od uruchomienia😅 Obecnie nie wiem dokładnie na jakiej podstawie są generowane i wybierane lokatory w codegen, jednak obie opcje mogą być poprawne 🙂
Tutaj zachęcałbym również do przyjrzenia się czy dałoby radę zrobić to lepiej/inaczej – np. po ID. Bo codegen nie zawsze działa optymalnie 🙂
Super lekcja, dzięki! 🙂 Jednak zauważyłem coś dziwnego: po wybraniu nr tel 504 xxx xxx zamiast pola input mamy listę rozwijaną z kwotami do wyboru.
Mimo to, jeśli wpiszę w teście
i puszczę test, to Playwright wskazuje mi w tym miejscu błąd:
No i jeszcze dziwniejsze jest to, że test dla numeru 504 xxx xxx przechodzi, jeśli zamiast metody selectOption dam metodę fill:
Trzeba będzie sprawdzić, co się dzieje w API 🙂
Hej 😀
Dzięki wielkie! 🙇♂️
selectOption
nie zadziała napage.locator('#widget_1_topup_amount')
, bo jest to obiekt typu input (a nie select/drop down) 😉 Select byłby odpowiedni dla elementupage.locator('#widget_1_topup_receiver')
🙂Krzysiek, cały wic polega na tym, że dla numeru 504 xxx xxx (tylko dla tego numeru) zamiast pola input mamy listę rozwijaną z kwotami doładowania do wyboru. Przynajmniej u mnie tak to działa. Zaręczam, że nie gmerałem w kodzie w devtoolsach 🙂 Tym dziwniejsze jest to, że ten numer nie przechodzi testu, jeśli wybierzemu lokator selectOption. Prawda testu i prawda ekranu. 😀
504 xxx xxx
wybierz telefon do doładowania
500 xxx xxx
502 xxx xxx
503 xxx xxx
504 xxx xxx
Faktycznie 😀 Sprawdziłem dla innych numerów – i akurat nie sprawdziłem
504 xxx xxx
.W sumie w realnym projekcie -> idealne na zgłoszenie buga 😀
W naszym przypadku – pozostaje nam pominąć ten przypadek 😉
Widać w tej apcje mamy więcej bugów niż zakładaliśmy i niż jesteśmy świadomi 😀
Oprócz “braku wiadomości” test szybkiego przelewu czasami nie przechodzi, gdy kwota w wiadomości jest podawana bez wartości dziesiętnych.
Expected string: “Przelew wykonany! Chuck Demobankowy – 150,00PLN – pizza”
Received string: “Przelew wykonany! Chuck Demobankowy – 150PLN – pizza”
Pewnie treść wiadomości powinna być doprecyzowana w specyfikacji, a sytuacja stworzona w celach dydaktycznych.
W pewnych przypadkach testy mogą kończyć się niepowodzeniem, gdzie powody mogą być różne – począwszy od połączenia internetowego, prędkości testu, czy z winy samej aplikacji. W tym przypadku możemy ten błąd zignorować, a w projekcie warto przedyskutować go z innymi QA lub developerami.
Również takie niestabilne testy w testowej aplikacji pozwalają też pobawić się z ustawieniami w Playwrighcie – np w pliku config jest parametr
retries
, który pozwala ponawiać testy, które zakończyły się niepowodzeniem.Domyślnie wartość ustawiona jest na 0, czyli każdy test ma tylko jedną szanse, ale przy niestabilnych testach możemy poeksperymentować z wartością
retries
.Przy czym – warto tu się zastanowić czy takie ponawianie testów jest dobrym rozwiązaniem w naszym kontekście (czyli projekcie) i jaki jest faktyczny powód tej niestabilności testów. Bo ustawiając
retries
bez analizy problemy możemy bardzo łatwo przeoczyć faktyczny błąd w aplikacji 😉Więcej o tym powiemy w przyszłych materiałach – również o wadach, zaleta oraz zagrożeniach 🙂
mnie jedynie drażni ten “Brak wiadomości”, od czapy się lubi pokazać 😛
Idealnie! 😀
A tak na serio – była w tym głębsza myśl 😉
Aplikacja została specjalnie tak zaprojektowana, aby oddać różne (czasem specyficzne) wymagania klienta oraz kilka innych niedogodności… Dzięki temu symulujemy prosty projekt, w którym musimy się dostosować, ale momentami nie jesteśmy pewni czy znaleziona rzeczy to bug czy feature 😉
Jak zwykle wszystko świetnie wytłumaczone od podstaw!
Dzięki wielki! 🙇♂️