- Published on
Playwright (2. díl) - První test
1. Úvod
V článku popíšu tyto body:
- jak Playwright nainstalovat,
- jak vypadá struktura testů,
- jak je spustit a vyhodnotit,
- a jak ladit chyby pomocí UI, tracingu a debugovacích nástrojů.
2. Instalace Playwrightu a příprava projektu
Playwright lze do projektu přidat dvěma způsoby:
- zjednodušená instalace pomocí
npm init playwright@latest - ruční instalace – postupné příkazy (
npm init -y,npm install @playwright/test, …)
1. Zjednodušená instalace
npm init playwright@latest
Co příkaz vykoná?
- spustí interaktivního průvodce v terminálu, kde lze zvolit programovací jazyk (TypeScript/Javascript), stáhnutí prohlížečů, vytvoření GitHub Actions workflow.
- vytvoří složku
tests/s ukázkovými testy - vytvoří
playwright.config.tss výchozím nastavením - nainstaluje
@playwright/test(test runner) - stáhne prohlížeče
Okamžitě po provedení příkazu můžu spustit ukázkové testy:
npx playwright test
2. Ruční instalace
Pokud chci plnou kontrolu nad instalací (resp. konfigurací) nebo přidávám Playwright do existujícího projektu, můžu ručně zadat příkazy:
mkdir playwright-demo
cd playwright-demo
npm init -y
npm install -D @playwright/test
npx playwright install
npm init -y- Tímto se vytvoří soubor package.json (inicializuje se nový Node.js projekt) uvnitř složky
playwright-demo. Bez přepínače-yby se spustilo interaktivní dotazování na název projektu, verzi, popis atd. S přepínačem budou všechny odpovědi nastavené na default.
- Tímto se vytvoří soubor package.json (inicializuje se nový Node.js projekt) uvnitř složky
npm install -D @playwright/test- nainstaluje Playwright test runner
npx playwright install- stáhne prohlížeče
Pak si můžu sám vytvořit složku tests/ a v něm soubory s testy např. prvni-test.spec.ts.
3. První test v Playwrightu
V adresáři tests vytvořím soubor prvni-test.spec.ts. Pro testy budu používat svojí testovací stránku https://users.projects.icanbreakit.eu V prvním testu jen ověřím title stránky.
import { test, expect } from '@playwright/test'
test('homepage has title "test API"', async ({ page }) => {
await page.goto('https://users.projects.icanbreakit.eu')
await expect(page).toHaveTitle('test API')
})
Uvedený kód sám o sobě říká, co se v testu bude dít. Možnosti, jak test spustit, jsou v následující kapitole.
Co je v uvedeném příkladu page?
V Playwrightu každý test běží v izolovaném prohlížečovém kontextu. Playwright automaticky vytvoří pro každý test novou stránku (tab) a předá ji jako argument. page je objekt reprezentující tuto aktuální stránku (tab).
Proč se používá destructuring { page }?
Funkce test v našem příkladu obsahuje dva parametry - název/popis testu (string "homepage has title "test API") a callback funkci - v našem případě:
;({ page }) => {
await page.goto('https://users.projects.icanbreakit.eu')
await expect(page).toHaveTitle('test API')
}
Každý callback testu dostává jako argument objekt s různými testovacími fixtures (ty si lze představit jako funkce integrované do test runneru - fixtures jsou Playwrightem předem připravené a dostupné v každém testu). Jednou z fixtures je právě page. V destructuring zápisu si test vezme jen ty fixtures, které mu poskytneme. Např. v tomto případě předáme tři fixtures:
test('něco', async ({ page, context, browserName }) => {
// v testu mám kromě fixture "page" k dispozici i "context" a "browserName"
})
Kdybych destructuring nepoužil, měl bych v testu k dispozici celý objekt a musel bych psát:
test('example', async (fixtures) => {
const page = fixtures.page
await page.goto('https://users.projects.icanbreakit.eu')
})
4. Spuštění testů
Spuštění všech testů:
npx playwright test
Po spuštění našeho testu vypíše terminál takovýto výsledek:
Running 3 tests using 3 workers 3 passed (10.2s)
Ve výchozím nastavení se každý test spustí ve všech třech podporovaných prohlížečích – Chromium, Firefox a WebKit (Playwright navíc testy spouští paralelně ve více workerech, což výrazně šetří čas). Toto lze změnit buď v konfiguračním souboru playwright.config.ts, a nebo můžeme při spouštění testu v příkazové řádce použít např. tuto volbu a testy poběží jen ve Firefoxu:
npx playwright test --project=firefox
Spuštění jen konkrétního testu podle jména:
npx playwright test --grep "homepage has title"
Jiná možnost, jak spustit jen jeden test (nebo několik vybraných testů) je použití test.only. Spustí se pak jen testy s tímto označením.
test.only('homepage has title', async ({ page }) => {
await page.goto('https://users.projects.icanbreakit.eu')
await expect(page).toHaveTitle('test API')
})
Spuštění v headed režimu (s viditelným prohlížečem):
npx playwright test --headed
Spuštění v UI módu
Běh testů lze sledovat i ve speciálním UI módu, který umožňuje spouštět jednotlivé testytesty, filtrovat je a sledovat výsledky v grafickém rozhraní. Spustíme ho:
npx playwright test --ui
UI mód umožňuje:
- zobrazí přehled všech testů v projektu (podle struktury složek a souborů projektu)
- umožňuje spouštět testy jednotlivé i celé skupiny testů
- filtrování testů podle názvu
- opakované ruční spouštění
- sledování testů v reálném čase
- ukazuje výsledek (passed/failed/skipped), čas běhu
- v případě chyby zobrazí stack trace, screenshoty, video
- upravovat kód a test ihned znovu spouštět
Zobrazení reportu:
npx playwright show-report
Report se otevře v novém okně prohlížeče.
Paralelní běh
Ve výchozím nastavení jsou testy spouštěny paralelně (ve více workerech), každý worker běží v odděleném browser contextu, takže testy jsou izolované a neovlivňují se.
Někdy je potřeba paralelní běh vypnout (např. když běží několik testů sdílející jednu databázi apod.):
npx playwright test --workers=1
Počet workerů je omezený na jeden, takže testy běží sekvenčně.
Shrnutí
npx playwright test # spustí všechny testy
npx playwright test --grep "title" # spustí jen testy obsahující "title"
npx playwright test --headed # běh s viditelným prohlížečem
npx playwright test --ui # ui mód
npx playwright test --reporter=html # vygeneruje HTML report
npx playwright test --workers=1 # vypne paralelní běh
npx playwright test --debug # spustí Inspector
5. Playwright UI, debugging a tracing
Jednou z největších výhod Playwrightu jsou jeho debugovací nástroje.
Playwright Inspector
Kdekoliv v kódu můžeme test zastavit a otevřít Playwright inspector. Test musí být spuštěn v headed režimu, aby se inspektor zobrazil.
await page.pause()
Test se pozastaví, otevře se okno se zdrojovým kódem testu, ve kterém můžeme krokovat jako v debuggeru, klikat na prvky (inspektor po kliknutí na element vygeneruje jeho lokátor), nahrávat další kroky, vidět aktuální stav DOMu apod.
Playwright inspector lze pro účely debuggování spustit i ručně z příkazové řádky:
npx playwright test --debug
Playwright inspector lze také spustit přímo pro nahrávání testů. Inspector pak vygeneruje kód testu podle toho, co na stránce děláte:
npx playwright codegen https://users.projects.icanbreakit.eu
Tracing
Tracing umožňuje záznam celého běhu testu (screenshots, network logy, DOM snapshoty). V tracingu vidíme krok po kroku, co se dělo, proč a kdy test selhal apod.
Zapnutí v konfiguraci:
use: {
trace: 'on-first-retry'
}
Pro tracing můžeme nastavit tyto hodnoty:
- off – tracing je vypnutý (defaultní nastavení)
- on – tracing je zapnutý pro každý běh testu
- retain-on-failure – tracing se uloží jen pokud test selže. Když test projde, tracing se zahodí. (ideální pro CI/CD)
- on-first-retry – tracing se zapne až při prvním opakovaném běhu testu (když je v konfiguraci povolené retries)
Po běhu testu můžeme otevřít uložený záznam:
npx playwright show-trace trace.zip
Otevře se přehrávač s časovou osou testu, všemi kroky (kliknutí, fill, navigace), screenshoty a DOM snapshoty v daném okamžiku, síťovými požadavky apod.
6. Příklady často používaných akcí
Interakce se stránkou
Kliknutí na tlačítko
await page.click('text=Submit')
Vyplnění formuláře
await page.fill('#username', 'my-name')
await page.fill('#password', 'secret-password')
await page.click('button[type=submit]')
Ověření textu na stránce
await expect(page.locator('h1')).toHaveText('Vítejte')
Získání textu z elementu
const title = await page.textContent('h1')
Získání atributu z elementu
const href = await page.getAttribute('a.download-link', 'href')
Screenshot stránky nebo elementu
await page.screenshot({ path: 'screenshot.png' })
await page.locator('#logo').screenshot({ path: 'logo.png' })
Navigace na jinou stránku a zpět
await page.goto('https://example.com/page1')
await page.goBack()
await page.goForward()
Kontrola URL adresy po přesměrování
await expect(page).toHaveURL(/.*dashboard/)
Pokročilejší scénáře
Práce s cookies
const cookies = await context.cookies()
await context.addCookies([
{ name: 'auth', value: 'my-token', url: 'https://users.projects.icanbreakit.eu/' },
])
Práce s lokálním úložištěm
await page.evaluate(() => localStorage.setItem('theme', 'dark'))
Čekání na síťovou odpověď
// spuštění akce, která pošle request
const response = await Promise.all([
page.waitForResponse('**/api/save'), // počká na odpověď z API
page.click('button[type=submit]'),
])
expect(response[0].ok()).toBeTruthy()
Otevření nové karty / okna
Pokud akce na stránce otevře nový tab nebo okno, je třeba na něj počkat:
const [newPage] = await Promise.all([
context.waitForEvent('page'), // čekáme na otevření nové stránky
page.click('a[target="_blank"]'), // otevře novou kartu
])
await newPage.waitForLoadState()
await expect(newPage).toHaveTitle('my-title')
Pozn. context je browser context aktuálního testu a každý test má svůj vlastní.
Regulární výrazy
Při používání metod jako locator, toHaveURL, toHaveText apod., lze místo obyčejného stringu použít regulární výraz v syntaxi /pattern/ – Playwright ho pozná automaticky.
Kdy využijeme regulární výrazy?
Obvykle tam, kde se text dynamicky mění:
- atributy s konzistentním prefixem
Např. chci vyhledat všechny elementy s atributem data-test-id, které začínají item- a zbytek jsou libovolné znaky:
// <button data-test-id="item-123">Item 123</button>
// <button data-test-id="item-abc">Item abc</button>
// ...
const myItems = page.locator('[data-test-id=/^item-/]')
- URL, kde část je proměnlivá (např. obsahuje parametry)
await expect(page).toHaveURL(/www\.my-page\.com\/item\/.*$/)
- v textu elementu se mění text (datumy, IDčka apod.)
const message = page.getByTestId('item-added-notif')
await expect(message).toHaveText(/Položka č\. \d* byla vytvořena/)
- v případě, že potřebuju dynamický regulární výraz, použiju
new RegExp():
const dynamicId = 123
await expect(page).toHaveURL(new RegExp(`/item/${dynamicId}$`))
7. Co bude příště?
Příště se podíváme na základní konfiguraci a organizaci testů.

