Poglavlje 13: Testiranje web aplikacija
Priča za početak. U utorak, 15. novembra 2022., počela je pretprodaja karata za veliku turneju pjevačice Taylor Swift u SAD-u, preko sajta Ticketmaster. Pravo na pretprodaju imali su samo unaprijed registrovani obožavatelji, koji su dobili kod. Sistem je bio pripremljen za veliku gužvu, ali ne za ono što je stiglo: obožavatelji, ali i ogroman broj botova (programa koji automatski kupuju karte da bi ih kasnije preprodali skuplje). Prema izjavi same firme, sistem je tog dana primio 3,5 milijardi zahtjeva, oko četiri puta više nego u bilo kojem ranijem vrhuncu. Stranica se zaglavljivala, redovi čekanja su stajali satima, korpe su se praznile u posljednjem koraku, a mnogi su dobijali poruke o grešci baš kad su karte bile u korpi. Opšta prodaja, planirana za nekoliko dana kasnije, otkazana je, jer nije ostalo dovoljno karata. Slučaj je završio na saslušanju u američkom Senatu u januaru 2023. Za nas je ova priča zanimljiva jer pokazuje koliko toga mora raditi zajedno da bi jedan klik na dugme „Kupi” uspio: preglednik, stranica, JavaScript, mreža, server, red čekanja, baza i zaštita od botova. Web aplikacija je mjesto na kojem se sve to susreće s korisnikom, i zato je testiranje weba posebna vještina.

U poglavlju 3 testirali smo web stranicu DeliveryApp ručno: test slučajevi TS-KOR-01 … TS-KOR-06, istraživanje, izvještaji o defektu, i našli greške UI-01 i UI-02. U poglavlju 4 vidjeli smo da testovi kroz korisnički interfejs stoje na vrhu piramide: malo ih je, sporiji su, ali provjeravaju ono što korisnik zaista vidi. Sada te ručne testove automatizujemo alatom Playwright. Prvo ukratko kako radi web i šta se na njemu testira. Zatim Playwright: kako pronaći dugme (lokatori), kako sačekati da se nešto pojavi i kako provjeriti rezultat. Na kraju obrazac Page Object, testiranje u više preglednika i na telefonu, i provjere pristupačnosti.
Literatura. Osnovna literatura predmeta:
- J. Popović: Priručnik za test inženjere, CET i Računarski fakultet, Beograd, 2023.
- Rakić-Skoković: Priručnik za testiranje softvera, Fakultet tehničkih nauka, Novi Sad, 2013.
- G. J. Myers: The Art of Software Testing, 2. izdanje, John Wiley & Sons, 2004.
- A. P. Mathur: Foundations of Software Testing, Addison-Wesley Professional, 2008.
Za ovo poglavlje: dokumentacija alata Playwright za Python (playwright.dev/python); W3C: Web Content Accessibility Guidelines (WCAG) 2.2, 2023; M. Fowler: „PageObject” (martinfowler.com, 2013).
Riječi ovog poglavlja.
- Preglednik (browser) – program koji prikazuje web stranice: Chrome, Firefox, Safari, Edge.
- HTML, CSS, JavaScript – sadržaj stranice, njen izgled i njeno ponašanje.
- DOM (Document Object Model) – stranica kako je preglednik vidi: stablo elemenata koje JavaScript stalno mijenja.
- Playwright – alat za automatsko upravljanje preglednikom: otvara stranicu, klikće, kuca i provjerava.
- Lokator – opis kako pronaći element na stranici, npr. „dugme s imenom Naruči”.
- Uloga (role) – šta element jeste za korisnika i čitač ekrana: dugme, polje, naslov, link.
- Automatsko čekanje (auto-waiting) – Playwright sam sačeka da element bude vidljiv i spreman prije radnje ili provjere.
- Page Object – klasa koja predstavlja stranicu i njene radnje, da testovi ne bi zavisili od detalja HTML-a.
- Responzivnost – stranica se prilagođava ekranu: računar, tablet, telefon.
- Pristupačnost (accessibility, a11y) – stranicu mogu koristiti i ljudi s invaliditetom: čitačem ekrana, samo tastaturom, uz uvećanje.
- Trag (trace) – snimak izvršavanja testa korak po korak, sa slikama ekrana, za istraživanje pada.
Ciljevi poglavlja. Nakon poglavlja možete: objasniti kako preglednik, stranica i server sarađuju; nabrojati šta se na web aplikaciji testira; instalirati Playwright i pokrenuti test stranice DeliveryApp; izabrati dobar lokator i objasniti zašto su uloga i oznaka bolji od CSS putanje; objasniti automatsko čekanje i zašto se ne koristi sleep; napisati provjere expect za tekst, vidljivost i stanje dugmeta; organizovati testove obrascem Page Object; pokrenuti testove u više preglednika i na ekranu telefona; napisati osnovne testove pristupačnosti; istražiti pad testa pomoću snimka ekrana i traga.
Plan poglavlja – Sedmica 13: tri časa teorije i tri časa praktične nastave
| Čas | Sadržaj | Na času |
|---|---|---|
| Teorija 1 | 13.1–13.3 Kako radi web; šta testiramo; prvi Playwright test | Ručni TS-KOR-01 postaje automatski |
| Teorija 2 | 13.4–13.6 Lokatori; čekanje i provjere; istraživanje pada | Zašto sleep(2) nije rješenje |
| Teorija 3 | 13.7–13.9 Page Object; preglednici i telefon; pristupačnost | Naručivanje samo tastaturom |
| Praksa 1–3 | Playwright testovi stranice DeliveryApp nad obje verzije | tests_web/ |
Dio 1 – Web i prvi automatski test
13.1 Kako radi web
Kad kupac otvori stranicu DeliveryApp, dešava se lanac koraka:
- preglednik pošalje HTTP zahtjev serveru (poglavlje 9);
- server vrati HTML (sadržaj: naslovi, dugmad, polja), CSS (izgled: boje, raspored) i JavaScript (ponašanje: šta se desi kad se klikne);
- preglednik od HTML-a napravi DOM, stablo elemenata, i nacrta ga na ekranu;
- kad kupac klikne „+” pored Margarite, JavaScript promijeni DOM: doda stavku u korpu i preračuna cijenu, bez novog učitavanja stranice;
- kad klikne „Naruči”, JavaScript pošalje zahtjev API-ju i prikaže odgovor.
Za testera, iz toga slijede tri važne stvari:
- Stranica se stalno mijenja. Cijena se ne pojavi odmah, nego kad JavaScript završi račun ili kad stigne odgovor servera. Test koji provjeri prerano vidi staru vrijednost.
- Isti kod, različiti preglednici. Chrome, Firefox i Safari tumače HTML, CSS i JavaScript skoro isto, ali „skoro” je dovoljno za grešku.
- Pravila se provjeravaju dva puta. Web stranica DeliveryApp računa cijenu sama, da kupac odmah vidi iznos, a server je računa ponovo (poglavlje 9), jer ne vjeruje klijentu. Obje kopije pravila moraju se slagati, i obje treba testirati.

Stranica iz primjeri/deliveryapp/web/index.html je mala, ali ima sve što nam treba: jelovnik s dugmadima „−” i „+”, korpu, polja za udaljenost i kod, pregled cijene, dugme „Naruči” i, poslije narudžbe, dugmad za promjenu stanja. Sa ?v=0 na kraju adrese učitava prvu verziju s greškama D-01 … D-05, UI-01 i UI-02 (poglavlje 3).
Ukratko.
- Preglednik dobija HTML, CSS i JavaScript, pravi DOM i crta stranicu.
- JavaScript stalno mijenja DOM, pa se rezultat na ekranu ne pojavljuje odmah.
- Isti kod se u različitim preglednicima može ponašati malo drugačije.
- Stranica DeliveryApp računa cijenu i sama i preko servera, pa se obje kopije pravila testiraju.
13.2 Šta se testira na webu
Web test nije samo „da li dugme radi”. Kontrolna lista, od funkcija ka kvalitetu:
| Šta | Pitanje | DeliveryApp |
|---|---|---|
| funkcionalnost | daje li stranica tačan rezultat? | N-1001 pokazuje 24,50 € |
| validacija unosa | odbija li loš unos s jasnom porukom? | 11 km → „izvan zone dostave”, dugme Naruči onemogućeno |
| stanja i tok | prate li dugmad i poruke pravila? | otkazivanje u pripremi odbijeno (PP-6) |
| preglednici | radi li isto u Chrome, Firefox, Safari? | isti testovi u tri preglednika |
| responzivnost | radi li na telefonu? | dugme Naruči vidljivo na ekranu 390 × 844 |
| pristupačnost | može li se koristiti tastaturom i čitačem ekrana? | dugmad imaju ime, polja imaju oznaku |
| performanse | koliko brzo se učita i reaguje? | alat Lighthouse u Chromeu |
| sigurnost | može li se ubaciti tuđi kod? | ime kupca <script>… iz poglavlja 10 |
Ručni testovi iz poglavlja 3 i automatski iz ovog poglavlja dopunjuju se. Automatski test ponavlja provjeru tačnih vrijednosti hiljadu puta bez umora. Ali samo čovjek primijeti da je dugme ružno, da je poruka zbunjujuća ili da je polje za kod skriveno ispod dugmeta.
Ukratko.
- Na webu se testiraju funkcionalnost, validacija unosa, tok stanja, preglednici, responzivnost, pristupačnost, performanse i sigurnost.
- Automatski testovi neumorno provjeravaju tačne vrijednosti i ponašanje.
- Ručni i istraživački testovi primjećuju ono što automat ne vidi: izgled, zbunjujuće poruke, nezgodan raspored.
- Obje vrste testova se dopunjuju.
13.3 Prvi Playwright test
Playwright je alat koji upravlja pravim preglednikom: otvori stranicu, klikne, upiše, i provjeri šta piše. Napravila ga je firma Microsoft, besplatan je i radi s Chromiumom (osnova Chromea i Edgea), Firefoxom i WebKitom (osnova Safarija). Instalacija:
pip install pytest-playwright
playwright install chromium
Druga naredba preuzme preglednik koji Playwright koristi (nekoliko stotina MB, jednom).
Ručni test slučaj TS-KOR-01 iz poglavlja 3 („N-1001: 2 × Margarita, 1 × Sok, 4,2 km → 24,50 €”) postaje automatski test u tests_web/test_web.py:
STRANICA = (pathlib.Path(__file__).parent.parent / "web" / "index.html").resolve().as_uri()
@pytest.fixture
def deliveryapp(page: Page):
page.goto(STRANICA)
return page
def dodaj(page, naziv, puta=1):
for _ in range(puta):
page.get_by_role("button", name="Dodaj " + naziv).click()
def test_n1001_ukupno(deliveryapp):
dodaj(deliveryapp, "Pizza Margarita", 2)
dodaj(deliveryapp, "Sok")
deliveryapp.get_by_test_id("udaljenost").fill("4.2")
expect(deliveryapp.get_by_test_id("dostava")).to_have_text("3,00 €")
expect(deliveryapp.get_by_test_id("ukupno")).to_have_text("24,50 €")Fixture page daje pytest-playwright: novu, praznu karticu preglednika za svaki test. Stranica se otvara direktno iz fajla, bez servera. Ostalo se čita skoro kao ručni test slučaj: dodaj dvije Margarite i sok, upiši 4,2 km, očekuj dostavu 3,00 € i ukupno 24,50 €. Isti obrazac pripremi–izvrši–provjeri kao u poglavlju 5.
pytest tests_web
............... [100%]
15 passed in 3.17s
Preglednik se po defaultu ne vidi (radi „bez glave”, headless), zato je brz. Da biste gledali šta test radi, dodajte --headed --slowmo 500: preglednik se otvori, a svaki korak traje pola sekunde.
Nad prvom verzijom (DeliveryApp=v0, stranica s ?v=0):
FAILED tests_web/test_web.py::test_n1001_ukupno[chromium] - AssertionError: L...
FAILED tests_web/test_web.py::test_kod_malim_slovima[chromium] - AssertionErr...
FAILED tests_web/test_web.py::test_izvan_zone_poruka[chromium] - AssertionErr...
FAILED tests_web/test_web.py::test_kolicina_ne_moze_biti_negativna[chromium]
FAILED tests_web/test_web.py::test_otkazivanje_u_pripremi[chromium] - Asserti...
...
9 failed, 6 passed in 48.46s
Pet testova iz test_web.py hvata D-02, D-03, UI-01, UI-02 i D-04, a četiri iz test_web_po.py (13.7) još D-01 na tačno 30,00 €. Primijetite i vrijeme: 48 sekundi umjesto 3. Svaka pala provjera čeka do 5 sekundi da se tačna vrijednost možda ipak pojavi (13.5), pa tek onda prijavi pad.
Na času. Pokrenite
playwright codegens adresom stranice DeliveryApp. Otvore se preglednik i prozor u kojem Playwright zapisuje kod dok vi klikćete. Dodajte dvije Margarite i pogledajte kakve lokatore je izabrao. Snimljen kod je dobar početak, ali ga uvijek treba urediti: dodati provjere (expect) i ukloniti suvišne korake.
Ukratko.
- Playwright upravlja pravim preglednikom (Chromium, Firefox, WebKit) i radi s pytestom preko
pytest-playwright.- Fixture
pagedaje novu karticu za svaki test.- Ručni test slučaj TS-KOR-01 postaje kratak automatski test s istim koracima i očekivanim rezultatom.
- Nad prvom verzijom 9 od 15 web testova pada i otkriva D-01 … D-04, UI-01 i UI-02.
Provjeri se.
- Šta je DOM? – Stranica kako je preglednik vidi: stablo elemenata koje JavaScript stalno mijenja.
- Zašto web stranica DeliveryApp i server oba računaju cijenu? – Stranica da kupac odmah vidi iznos, a server jer ne vjeruje broju koji bi poslao klijent.
- Šta radi
playwright codegen? – Otvori preglednik i zapisuje Playwright kod dok korisnik klikće.
Dio 2 – Lokatori, čekanje i provjere
13.4 Lokatori: kako naći dugme
Da bi kliknuo dugme, test ga mora pronaći. Opis kako se element traži zove se lokator. Isti element se može naći na više načina, i razlika je velika (slika 13.3):

- Po ulozi (
get_by_role): „dugme s imenom Naruči”. Tako element vide korisnik i čitač ekrana za slijepe. Ako se promijeni boja, raspored ili HTML oko dugmeta, test i dalje radi. - Po oznaci (
get_by_label): „polje s oznakom Udaljenost (km)”. Najbolje za polja forme. - Po tekstu (
get_by_text): „Korpa je prazna.” Dobro za poruke. - Po test oznaci (
get_by_test_id): atributdata-testid="ukupno"koji programeri dodaju posebno za testove. Stabilan, ali korisnik ga ne vidi, pa ne provjerava ništa o pristupačnosti. - Po CSS ili XPath putanji:
#jelovnik > div:nth-child(2) button. Opisuje strukturu stranice („drugo dugme u drugom redu”) i puca čim neko doda novo jelo ili omot oko dugmeta. Izbjegavati.
U stranici DeliveryApp dugmad „+” i „−” imaju samo znak, ali i opis za čitač ekrana: aria-label="Dodaj Pizza Margarita". Zato test može napisati get_by_role("button", name="Dodaj Pizza Margarita"). Ovdje se dobar test i dobra pristupačnost sreću: ako test ne može naći dugme po imenu, ne može ni slijepi korisnik.
Česta zabluda. „Najsigurnije je dodati
data-testidna sve.” Test oznake su stabilne i korisne za elemente koji nemaju smisleno ime (npr. iznos 24,50 € u pregledu). Ali za dugmad i polja je boljeget_by_roleiget_by_label: test tada usput provjerava i da element ima ime koje vide korisnik i čitač ekrana.
Ukratko.
- Lokator opisuje kako se element pronalazi na stranici.
- Najbolji su lokatori po ulozi i oznaci, jer opisuju element kako ga vidi korisnik.
- Test oznake (
data-testid) su stabilne, ali ne provjeravaju ništa o pristupačnosti.- CSS i XPath putanje opisuju strukturu stranice i pucaju pri svakoj izmjeni.
13.5 Automatsko čekanje i provjere
Stranica se mijenja asinhrono: klik na „+” pokrene JavaScript, koji tek poslije promijeni cijenu. Na sporom računaru to može trajati duže. Stari alati su tjerali testera da piše:
page.click("text=+")
time.sleep(2) # nadam se da je dovoljno…
assert page.inner_text("#ukupno") == "24,50 €"To je recept za nestabilan test (poglavlje 12): na brzom računaru gubi dvije sekunde, na sporom CI serveru ponekad nije dovoljno.
Playwright to rješava na dva mjesta:
- Prije radnje (
click,fill) sam sačeka da element postoji, da je vidljiv, da nije onemogućen i da se ne pomjera. - Provjere
expectponavljaju provjeru dok ne uspije ili dok ne istekne vrijeme (5 sekundi po defaultu). Ovo su tzv. provjere „za web” (web-first assertions).
expect(page.get_by_test_id("ukupno")).to_have_text("24,50 €") # čeka dok tekst ne bude 24,50 €
expect(page.get_by_test_id("naruci")).to_be_disabled() # čeka dok dugme ne bude onemogućeno
expect(page.get_by_test_id("poruka")).to_contain_text("izvan zone")
expect(page.get_by_label("Udaljenost (km)")).to_be_visible()Najvažnije provjere:
| Provjera | Šta znači |
|---|---|
to_have_text("…") |
tačan tekst elementa |
to_contain_text("…") |
tekst sadrži dati dio |
to_be_visible() / to_be_hidden() |
element se vidi / ne vidi |
to_be_enabled() / to_be_disabled() |
dugme se može / ne može kliknuti |
to_have_value("…") |
vrijednost u polju forme |
to_have_count(n) |
lokator nalazi tačno n elemenata |
Razlika između assert i expect je važna: assert page.get_by_test_id("ukupno").inner_text() == "24,50 €" pročita tekst jednom, u tom trenutku, i ne čeka. expect(...) čeka. Za web uvijek expect.
Ukratko.
- Stranica se mijenja asinhrono, pa test koji provjeri prerano vidi staru vrijednost.
time.sleepčini test sporim i nestabilnim.- Playwright prije radnje sam čeka da element bude spreman, a
expectponavlja provjeru do 5 sekundi.- Za provjere na webu koristi se
expect, a neassertnad jednom pročitanom vrijednošću.
13.6 Kad test padne: poruka, slika, trag
Kad web test padne, prvo pitanje je: šta je bilo na ekranu? Playwright daje tri pomoći.
1. Poruka provjere. Pad testa granice na v0 (3,1 km):
> expect(self.page.get_by_test_id("dostava")).to_have_text(tekst)
E AssertionError: Locator expected to have text '3,00 €'
E Actual value: 2,50 €
E Call log:
E - Expect "to_have_text" get_by_test_id("dostava") with timeout 5000ms
E - waiting for get_by_test_id("dostava")
E 14 × locator resolved to <span id="dostava" data-testid="dostava">2,50 €</span>
E - unexpected value "2,50 €"
Poruka kaže šta je očekivano, šta je dobijeno, i da je Playwright 14 puta provjerio u 5 sekundi prije nego što je odustao. To je N-1001 na v0: dostava 2,50 € umjesto 3,00 €, greška D-02.
2. Snimak ekrana. pytest tests_web --screenshot only-on-failure sačuva sliku ekrana u trenutku pada, u folder test-results/. Slika je odlična za izvještaj o defektu (poglavlje 3).
3. Trag. pytest tests_web --tracing retain-on-failure za svaki pali test sačuva trag: svaki korak, sliku ekrana prije i poslije, DOM, mrežne zahtjeve i poruke konzole. Otvara se naredbom:
playwright show-trace test-results/<ime-testa>/trace.zip
U pregledniku traga možete ići korak po korak, unazad i unaprijed, kao da gledate snimak utakmice. Trag je posebno koristan za pad u CI-ju, gdje ne možete gledati preglednik uživo.
Ukratko.
- Poruka
expectkaže šta je očekivano, šta je dobijeno i koliko puta je provjereno.- Opcija
--screenshot only-on-failurečuva sliku ekrana u trenutku pada.- Opcija
--tracing retain-on-failurečuva trag sa svakim korakom, DOM-om i mrežom.- Trag se otvara naredbom
playwright show-tracei posebno pomaže kod padova u CI-ju.
Provjeri se.
- Zašto je
get_by_role("button", name="Naruči")bolji od CSS putanje? – Opisuje element kako ga vidi korisnik, ne puca kad se promijeni struktura stranice, i usput provjerava da dugme ima ime.- Koja je razlika između
assert ... inner_text() == ...iexpect(...).to_have_text(...)? –assertpročita jednom i ne čeka;expectponavlja provjeru dok ne uspije ili istekne vrijeme.- Šta sadrži Playwright trag? – Svaki korak testa sa slikama ekrana, DOM, mrežne zahtjeve i poruke konzole.
Dio 3 – Organizacija, preglednici i pristupačnost
13.7 Page Object
U test_web.py svaki test sam zna da se dugme zove „Dodaj Pizza Margarita” i da polje ima data-testid="udaljenost". Kad dizajner promijeni natpis na „Dodaj u korpu: Pizza Margarita”, treba mijenjati svaki test. Obrazac Page Object rješava to tako što stranicu predstavi klasom s metodama za radnje kupca. Testovi pozivaju metode, a samo klasa zna HTML.
Slika iz života: daljinski upravljač. Pritisnete „glasnije” i ne zanima vas kakav je čip u televizoru. Ako proizvođač promijeni čip, novi daljinski ima isto dugme „glasnije”.
Fajl tests_web/stranica.py:
class DeliveryAppStranica:
def __init__(self, page: Page, adresa: str):
self.page = page
self.adresa = adresa
def otvori(self):
self.page.goto(self.adresa)
return self
def dodaj(self, jelo, puta=1):
for _ in range(puta):
self.page.get_by_role("button", name=f"Dodaj {jelo}").click()
return self
def udaljenost(self, km):
self.page.get_by_label("Udaljenost (km)").fill(str(km))
return self
def ocekuj_dostavu(self, tekst):
expect(self.page.get_by_test_id("dostava")).to_have_text(tekst)
...Metode vraćaju self, pa se radnje mogu nizati. Testovi u tests_web/test_web_po.py čitaju se kao rečenice:
def test_n1001_kroz_page_object(deliveryapp):
deliveryapp.dodaj("Pizza Margarita", 2).dodaj("Sok").udaljenost(4.2)
deliveryapp.ocekuj_dostavu("3,00 €")
deliveryapp.ocekuj_ukupno("24,50 €")
@pytest.mark.parametrize("korpa, dostava", [
([("Pizza Capricciosa", 2), ("Sok", 3)], "3,00 €"), # 22,00 + 7,50 = 29,50 € (najbliže ispod granice)
([("Pizza Margarita", 2), ("Pizza Capricciosa", 1)], "0,00 €"), # 19,00 + 11,00 = tačno 30,00 € (PP-4)
])
def test_granica_besplatne_dostave(deliveryapp, korpa, dostava):
for jelo, puta in korpa:
deliveryapp.dodaj(jelo, puta)
deliveryapp.udaljenost(5)
deliveryapp.ocekuj_dostavu(dostava)Primijetite drugi test. Granica od 30,00 € (poglavlje 8) na stranici se ne može testirati sa 29,99 €, jer su sve cijene u jelovniku višestruke od 0,50 €. Najbliži iznos ispod granice koji kupac može složiti je 29,50 €, a tačno 30,00 € daju dvije Margarite i jedna Capricciosa. Granične vrijednosti uvijek treba prilagoditi onome što korisnik stvarno može unijeti. Ovaj test na v0 pada za 30,00 € (D-01).
Ukratko.
- Page Object predstavlja stranicu klasom s metodama za radnje korisnika i provjere.
- Samo klasa zna HTML, pa promjena stranice traži izmjenu na jednom mjestu.
- Testovi s Page Objectom čitaju se kao rečenice: dodaj, upiši udaljenost, očekuj ukupno.
- Granične vrijednosti se prilagođavaju onome što korisnik stvarno može unijeti, npr. 29,50 € i 30,00 €.
13.8 Više preglednika i ekran telefona
Isti testovi pokreću se u drugom pregledniku jednom opcijom:
playwright install firefox webkit
pytest tests_web --browser chromium --browser firefox --browser webkit
Svaki test se izvrši tri puta, a ime u izvještaju kaže gdje: test_n1001_ukupno[firefox]. WebKit je osnova Safarija, pa ovako na Windowsu i Linuxu dobijamo dobru aproksimaciju Safarija bez Apple računara.
Više od polovine posjeta na webu danas dolazi s telefona. Test na ekranu telefona pravi poseban kontekst preglednika s malim ekranom i dodirom:
def test_mobilni_ekran(browser):
"""Ista stranica na ekranu telefona (390 × 844): dugme Naruči mora biti vidljivo i upotrebljivo."""
kontekst = browser.new_context(viewport={"width": 390, "height": 844}, is_mobile=True, has_touch=True)
page = kontekst.new_page()
page.goto(ADRESA)
page.get_by_role("button", name="Dodaj Pizza Margarita").tap()
naruci = page.get_by_role("button", name="Naruči")
naruci.scroll_into_view_if_needed()
expect(naruci).to_be_visible()
expect(naruci).to_be_enabled()
kontekst.close()Umjesto click koristi se tap (dodir prstom). Playwright ima i gotove profile poznatih telefona (playwright.devices["iPhone 13"]), a pytest-playwright opciju --device "iPhone 13".
Emulacija nije isto što i pravi telefon: ekran i dodir se glume, ali procesor, mreža i stvarni Safari na iPhoneu nisu isti. Zato se uz automatske testove u emulaciji, prije izdanja, stranica proba i ručno na bar jednom pravom telefonu.
Ukratko.
- Opcija
--browserpokreće iste testove u Chromiumu, Firefoxu i WebKitu.- WebKit omogućava aproksimaciju Safarija na Windowsu i Linuxu.
- Novi kontekst s malim ekranom i dodirom provjerava stranicu na telefonu.
- Emulacija ne zamjenjuje ručnu provjeru na bar jednom pravom telefonu.
13.9 Pristupačnost
U poglavlju 10 rekli smo da stranicu treba da mogu koristiti i ljudi s invaliditetom. Standard WCAG ima stotine kriterija, ali tri najvažnija za početak mogu se testirati automatski:
- Svako dugme i polje ima ime koje čitač ekrana izgovori. Dugme „+” bez opisa čitač pročita kao „plus, dugme”, i slijepi korisnik ne zna uz koje jelo ide.
- Sve se može uraditi tastaturom. Ljudi koji ne mogu koristiti miš kreću se tipkom Tab i aktiviraju Enterom ili razmakom.
- Polja imaju vidljivu oznaku (
<label>), a ne samo sivi tekst unutar polja koji nestane kad se počne kucati.
Testovi iz test_web_po.py:
def test_samo_tastaturom(page: Page):
"""Pristupačnost: kupac koji ne koristi miš mora moći dodati jelo i vidjeti cijenu."""
page.goto(ADRESA)
dugme = page.get_by_role("button", name="Dodaj Pizza Margarita")
dugme.focus()
page.keyboard.press("Enter")
page.keyboard.press("Enter")
expect(page.get_by_test_id("artikli")).to_have_text("19,00 €")
def test_polja_imaju_vidljive_oznake(page: Page):
"""Pristupačnost: čitač ekrana mora znati šta je koje polje."""
page.goto(ADRESA)
expect(page.get_by_label("Udaljenost (km)")).to_be_visible()
expect(page.get_by_label("Kod popusta")).to_be_visible()
for dugme in page.get_by_role("button").all():
assert dugme.get_attribute("aria-label") or dugme.inner_text().strip()Drugi test prolazi kroz sva dugmad na stranici i provjerava da svako ima ime, bilo kao vidljiv tekst („Naruči”) ili kao opis za čitač ekrana (aria-label). Kad neko sutra doda novo dugme bez imena, test padne.
Za detaljniju provjeru postoje alati kao axe (biblioteka axe-core, koja se može pozvati iz Playwrighta) i Lighthouse u Chromeu (kartica Lighthouse u alatima za programere). Oni provjeravaju i kontrast boja, redoslijed naslova, jezik stranice i desetine drugih pravila. Ali ni oni ne mogu reći da li je stranica zaista upotrebljiva slijepom korisniku: za to je potrebno probati je s čitačem ekrana (NVDA na Windowsu, VoiceOver na Macu i iPhoneu), a najbolje s osobom koja ga svakodnevno koristi.
Iz stvarnog svijeta. Pristupačnost nije samo dobra volja. Evropski akt o pristupačnosti (European Accessibility Act), čija se pravila primjenjuju od juna 2025. godine, traži da mnoge digitalne usluge u EU, među njima i online prodaja, budu pristupačne. Firme koje prodaju u EU, uključujući one iz BiH, moraju to provjeravati.
Ukratko.
- Tri osnovne provjere pristupačnosti su: svako dugme i polje ima ime, sve radi tastaturom, polja imaju vidljivu oznaku.
- Playwright testovi mogu provjeriti rad tastaturom i imena svih dugmadi na stranici.
- Alati axe i Lighthouse provjeravaju desetine pravila, uključujući kontrast boja.
- Stvarnu upotrebljivost za slijepe potvrđuje tek proba s čitačem ekrana.
Provjeri se.
- Šta je Page Object i koja je njegova korist? – Klasa koja predstavlja stranicu i njene radnje; kad se stranica promijeni, mijenja se samo ta klasa, a ne svi testovi.
- Kako se isti testovi pokreću u tri preglednika? – Opcijom
--browser chromium --browser firefox --browser webkit.- Zašto dugme „+” mora imati
aria-label? – Da čitač ekrana izgovori šta dugme radi, npr. „Dodaj Pizza Margarita”; tada ga i test može naći po imenu.
Praktična nastava – Playwright i stranica DeliveryApp
Cilj je automatizovati ručne test slučajeve iz poglavlja 3, organizovati ih obrascem Page Object, pokrenuti ih u više preglednika i na ekranu telefona, i provjeriti pristupačnost. Radi se u parovima. Prije početka: pip install pytest-playwright, pa playwright install chromium firefox webkit.
Korak 1 – Prvi testovi (40 minuta)
- U
primjeri/deliveryapppokrenitepytest tests_webnad ispravnom i nad prvom verzijom. Zapišite koji testovi padaju i koju grešku hvata svaki. - Pokrenite jedan test sa
--headed --slowmo 500i gledajte preglednik. - Pokrenite
playwright codegennad stranicom i snimite narudžbu 4 × Capricciosa na 2,5 km (stranica ima samo jelovnik Picerije). Uredite snimljen kod u test s provjerama (expect): artikli 44,00 €, dostava 0,00 € (PP-4), ukupno 44,00 €.
Korak 2 – Ručni testovi postaju automatski (50 minuta)
- Uzmite svoje test slučajeve TS-KOR-01 … TS-KOR-06 iz poglavlja 3. Za svaki napišite metodu ili test koristeći
DeliveryAppStranica. Ako nekoj radnji fali metoda (npr.ocekuj_poruku), dodajte je ustranica.py. - Za svaki test prvo zapišite očekivani rezultat iz pravila, pa tek onda pokrenite.
- Dodajte test za kod
" STUDENT10 "s razmacima i za nepoznat kodSTUDENT20.
Korak 3 – Kad test padne (30 minuta)
- Pokrenite nad v0:
pytest tests_web --screenshot only-on-failure --tracing retain-on-failure. - Otvorite trag jednog palog testa naredbom
playwright show-trace …i prođite korak po korak. U kojem koraku se prvi put vidi pogrešna vrijednost? - Napišite izvještaj o defektu za UI-02 (negativna količina) sa snimkom ekrana iz
test-results/.
Korak 4 – Preglednici, telefon, pristupačnost (60 minuta)
- Pokrenite sve web testove u tri preglednika. Da li neki test prolazi u jednom, a pada u drugom? Ako da, istražite zašto.
- Pokrenite testove sa
--device "iPhone 13". Šta se mijenja? - Napišite test u kojem kupac samo tastaturom napravi cijelu narudžbu: doda dvije Margarite, upiše udaljenost, i klikne Naruči (koristite
page.keyboard.press("Tab")i"Enter"). Uspijeva li? Ako ne, zapišite nalaz pristupačnosti. - Otvorite stranicu u Chromeu, alati za programere (F12), kartica Lighthouse, kategorija „Accessibility”. Zapišite ocjenu i tri najvažnije preporuke.
- U svojoj kopiji
index.htmluklonitearia-labels jednog dugmeta. Koji test pada?
Rezultat koji se predaje: fajl rezultati-13.md s tabelom web testova nad obje verzije i greškom koju hvata svaki; prošireni stranica.py i testovi za TS-KOR-01 … TS-KOR-06; izvještaj o defektu UI-02 sa slikom ekrana; rezultati u tri preglednika i na telefonu; test samo tastaturom i nalazi Lighthousea.
Vježbe
Vježba za studenta 1 – lokatori.
Poredajte lokatore od najboljeg ka najgorem i objasnite: a) page.locator("div.pregled > button.glavno"); b) page.get_by_role("button", name="Naruči"); c) page.get_by_test_id("naruci"); d) page.locator("//section[3]/button[1]").
Rješenje. b) uloga i ime, kako dugme vidi korisnik i čitač ekrana; c) test oznaka, stabilna ali bez provjere pristupačnosti; a) CSS putanja, puca kad se promijene klase ili omot; d) XPath po rednom broju sekcije i dugmeta, najkrhkiji: puca čim se doda nova sekcija.
Vježba za studenta 2 – čekanje.
Prepravite test tako da ne koristi sleep:
page.get_by_role("button", name="Naruči").click()
time.sleep(3)
assert page.get_by_test_id("stanje").inner_text() == "NOVA"Rješenje.
page.get_by_role("button", name="Naruči").click()
expect(page.get_by_test_id("stanje")).to_have_text("NOVA")expect čeka dok stanje ne bude NOVA (do 5 sekundi), pa je test brz kad je stranica brza i stabilan kad je spora.
Vježba za studenta 3 – Page Object.
Dodajte u DeliveryAppStranica metodu ocekuj_poruku(tekst) i napišite test za 11 km koji je koristi.
Rješenje.
def ocekuj_poruku(self, tekst):
expect(self.page.get_by_test_id("poruka")).to_contain_text(tekst)
def test_izvan_zone(deliveryapp):
deliveryapp.dodaj("Pizza Margarita", 2).udaljenost(11)
deliveryapp.ocekuj_poruku("izvan zone")Na v0 test pada, jer stranica pokazuje „Greška 422” (UI-01).
Vježba za studenta 4 – granice na stranici.
Na stranici se mogu naručiti samo Margarita (9,50 €), Capricciosa (11,00 €) i Sok (2,50 €). Koje korpe biste izabrali za granicu PP-1 (najmanje 5,00 €)?
Rješenje. Ispod granice: 1 × Sok = 2,50 € (najveći iznos ispod 5,00 € koji se može složiti je 2,50 €, jer su sve cijene višestruke od 0,50 €, a 4,50 € nije moguće). Na granici: 2 × Sok = 5,00 €. Očekivano: 2,50 € odbijeno s porukom o minimalnoj narudžbi; 5,00 € prihvaćeno. Iznos 4,99 € iz poglavlja 8 testira se na nivou API-ja i funkcije, gdje se može unijeti.
Vježba za studenta 5 – pristupačnost.
Dizajner želi da polje za kod popusta nema oznaku, nego samo sivi tekst „npr. STUDENT10” unutar polja, „da bude čistije”. Šta odgovarate i koji test bi to otkrio?
Rješenje. Sivi tekst (placeholder) nestane čim kupac počne kucati, a mnogi čitači ekrana ga ne čitaju kao oznaku; ljudi s lošijim vidom ga teško vide zbog slabog kontrasta. Polje mora imati pravu oznaku (<label>). Test test_polja_imaju_vidljive_oznake bi pao, jer get_by_label("Kod popusta") ne bi našao polje.
Sažetak u pet rečenica
- Ticketmaster je 2022. dobio oko četiri puta više zahtjeva nego ikada ranije, a priča pokazuje koliko dijelova mora raditi zajedno da bi jedan klik na web stranici uspio.
- Web stranica je HTML, CSS i JavaScript koji stalno mijenja DOM, a testiraju se funkcionalnost, unos, tok stanja, preglednici, telefon, pristupačnost, performanse i sigurnost.
- Playwright upravlja pravim preglednikom, a najbolji lokatori su po ulozi i oznaci, jer opisuju element kako ga vide korisnik i čitač ekrana.
- Playwright sam čeka da element bude spreman, provjere
expectponavljaju se do 5 sekundi umjesto nestabilnogsleep, a pad se istražuje porukom, slikom ekrana i tragom. - Page Object čuva detalje stranice na jednom mjestu, isti testovi rade u tri preglednika i na ekranu telefona, a testovi tastature i imena dugmadi provjeravaju osnove pristupačnosti; na prvoj verziji DeliveryApp pada 9 od 15 web testova.