Oduvijek sam volio gledati kako moji jedinični testovi rade (i prolaze). Brzi su, a polaganje testova mi daje sigurnost da se moji pojedinačni komadi ponašaju kako bi trebali. Suprotno tome, često sam se borio da odredim prioritete end-to-end testova za pretraživač jer je njihovo pisanje i pokretanje bilo strašno sporo.
Srećom, alati za end-to-end testiranje u pretraživaču su postali mnogo bolji i brži tokom godina. A sa podešavanjem pretraživača bez glave, mogu pokrenuti svoje testove pretraživača kao dio svog CI.
Nedavno sam naišao na ovaj Heroku blog post koji govori o automatizaciji testiranja u pretraživaču sa bezglavim Chromeom u Heroku CI. Heroku ima buildpack koji instalira Chrome bez glave, koji možete pozvati za svoje testove u CI pipelineu.
Primjer podešavanja iz objave na blogu bila je React aplikacija testirana sa Puppeteer i Jest . To je sjajan početak… ali šta ako koristim Dramski pisac umjesto Puppeteer? Da li je moguće?
Odlučio sam da istražim. Kako se ispostavilo — da, to možete učiniti i sa Playwrightom! Dakle, snimio sam korake koji će vam biti potrebni da pokrenete Playwright testove na bezglavom Chrome pretraživaču koji se koristi u Heroku CI. U ovom postu ću vas provesti kroz korake za postavljanje.
Testiranje s kraja na kraj bilježi kako korisnici zapravo komuniciraju s vašom aplikacijom u pregledniku, potvrđujući potpune tokove posla. Playwright čini ovaj proces prilično besprijekornim testiranjem u Chromeu, Firefoxu i Safariju. Naravno, pokretanje čitavog niza testova pretraživača u CI je prilično teško, zbog čega bezglavi način rada pomaže.
Chrome for Testing buildpack od Herokua instalira Chrome na Heroku aplikaciju, tako da možete pokrenuti svoje Playwright testove u Heroku CI uz stvarno lagano postavljanje.
Pošto sam ovo upravo isprobavao, razdvojio sam GitHub repo koji je prvobitno bio referenciran u Heroku blog postu. Aplikacija je bila jednostavna React aplikacija s vezom, unosom teksta i gumbom za slanje. Bila su tri testa:
Prilično jednostavno. Sada sam samo trebao promijeniti kod da koristim Playwright umjesto Puppeteer and Jest. Oh, i također sam htio koristiti pnpm umjesto npm. Evo linka na moj račvasti GitHub repo .
Hajde da prođemo kroz korake koje sam preduzeo da modifikujem kod. Počeo sam sa svojim račvanim repo, identičnim heroku-examples
repo.
Htio sam koristiti pnpm umjesto npm. (Lične preferencije.) Dakle, evo šta sam prvo uradio:
~/project$ corepack enable pnpm ~/project$ corepack use pnpm@latest Installing [email protected] in the project… … Progress: resolved 1444, reused 1441, downloaded 2, added 1444, done … Done in 14.4s ~/project$ rm package-lock.json ~/project$ pnpm install # just to show everything's good Lockfile is up to date, resolution step is skipped Already up to date Done in 1.3s
Zatim sam uklonio Puppeteer i Jest, a dodao sam Dramatičara.
~/project$ pnpm remove \ babel-jest jest jest-puppeteer @testing-library/jest-dom ~/project$ $ pnpm create playwright Getting started with writing end-to-end tests with Playwright: Initializing project in '.' ✔ Do you want to use TypeScript or JavaScript? · JavaScript ✔ Where to put your end-to-end tests? · tests ✔ Add a GitHub Actions workflow? (y/N) · false ✔ Install Playwright browsers (can be done manually via 'pnpm exec playwright install')? (Y/n) · false ✔ Install Playwright operating system dependencies (requires sudo / root - can be done manually via 'sudo pnpm exec playwright install-deps')? (y/N) · false Installing Playwright Test (pnpm add --save-dev @playwright/test)… … Installing Types (pnpm add --save-dev @types/node)… … Done in 2.7s Writing playwright.config.js. Writing tests/example.spec.js. Writing tests-examples/demo-todo-app.spec.js. Writing package.json.
Također sam uklonio dio konfiguracije Jest iz package.json
.
Svoje Playwright testove možete pokrenuti u Chromeu, Firefoxu i Safariju. Pošto sam bio fokusiran na Chrome, uklonio sam ostale pretraživače iz odjeljka projects
generiranog playwright.config.js
fajla:
/* Configure projects for major browsers */ projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] }, }, // { // name: 'firefox', // use: { ...devices['Desktop Firefox'] }, // }, // // { // name: 'webkit', // use: { ...devices['Desktop Safari'] }, // }, ], …
Originalni kod je imao Puppeteer test fajl na src/tests/puppeteer.test.js
. Premjestio sam taj fajl u tests/playwright.spec.js
. Zatim sam ažurirao test da koristim Playwrightove konvencije, koje su prilično jasno mapirane. Novi test fajl je izgledao ovako:
const ROOT_URL = 'http://localhost:8080'; const { test, expect } = require('@playwright/test'); const inputSelector = 'input[name="name"]'; const submitButtonSelector = 'button[type="submit"]'; const greetingSelector = 'h5#greeting'; const name = 'John Doe'; test.beforeEach(async ({ page }) => { await page.goto(ROOT_URL); }); test.describe('Playwright link', () => { test('should navigate to Playwright documentation page', async ({ page }) => { await page.click('a[href="https://playwright.dev/"]'); await expect(page.title()).resolves.toMatch('| Playwright'); }); }); test.describe('Text input', () => { test('should display the entered text in the text input', async ({ page }) => { await page.fill(inputSelector, name); // Verify the input value const inputValue = await page.inputValue(inputSelector); expect(inputValue).toBe(name); }); }); test.describe('Form submission', () => { test('should display the "Hello, X" message after form submission', async ({ page }) => { const expectedGreeting = `Hello, ${name}.`; await page.fill(inputSelector, name); await page.click(submitButtonSelector); await page.waitForSelector(greetingSelector); const greetingText = await page.textContent(greetingSelector); expect(greetingText).toBe(expectedGreeting); }); });
start-server-and-test
, koristeći umjesto toga Playwrightov webServer Da bih testirao svoju React aplikaciju, morao sam je prvo pokrenuti (na http://localhost:8080
) u zasebnom procesu, a zatim sam mogao pokrenuti svoje testove. To bi bio slučaj bez obzira da li sam koristio Puppeteer ili Dramaturg. Sa Puppeteer-om, Heroku primjer je koristio paket start-server-and-test
.
Međutim, možete konfigurirati Playwright da pokrene aplikaciju prije pokretanja testova. Ovo je prilično zgodno!
Uklonio sam start-server-and-test
iz svog projekta.
~/project$ pnpm remove start-server-and-test
U playwright.config.js
, dekomentirao sam odjeljak webServer na dnu, modifikujući ga da izgleda ovako:
/* Run your local dev server before starting the tests */ webServer: { command: 'pnpm start', url: 'http://127.0.0.1:8080', reuseExistingServer: !process.env.CI, },
Zatim sam uklonio test:ci
skriptu iz originalne datoteke package.json
. Umjesto toga, moja test skripta je izgledala ovako:
"scripts": { … "test": "playwright test --project=chromium --reporter list" },
Playwright instalira najnovije binarne datoteke pretraživača koje koristi za svoje testove. Dakle, na mojoj lokalnoj mašini, trebao mi je Playwright da instalira svoju verziju Chromiuma.
~/project$ pnpm playwright install chromium Downloading Chromium 130.0.6723.31 (playwright build v1140) from https://playwright.azureedge.net/builds/chromium/1140/chromium-linux.zip 164.5 MiB [====================] 100%
Napomena: Chrome for Testing buildpack na Herokuu instalira preglednik koji ćemo koristiti za testiranje. Postavićemo naš CI tako da Playwright koristi taj pretraživač umjesto da troši vrijeme i resurse na instaliranje vlastitog.
S tim sam bio spreman. Bilo je vrijeme da isprobam svoje testove lokalno.
~/project$ pnpm test > playwright test --project=chromium --reporter list Running 3 tests using 3 workers ✓ 1 [chromium] > playwright.spec.js:21:3 > Text input > should display the entered text in the text input (911ms) ✘ 2 [chromium] > playwright.spec.js:14:3 > Playwright link > should navigate to Playwright documentation page (5.2s) ✓ 3 [chromium] > playwright.spec.js:31:3 > Form submission > should display the "Hello, X" message after form submission (959ms) ... - waiting for locator('a[href="https://playwright.dev/"]') 13 | test.describe('Playwright link', () => { 14 | test('should navigate to Playwright documentation page', async ({ page }) => { > 15 | await page.click('a[href="https://playwright.dev/"]'); | ^ 16 | await expect(page.title()).resolves.toMatch('| Playwright'); 17 | }); 18 | });
Oh! Tako je. Izmijenio sam svoj test kako bih očekivao da će me veza u aplikaciji odvesti do Playwrightove dokumentacije umjesto do Puppeteerove. Trebao sam ažurirati src/App.js
u redu 19:
<Link href="https://playwright.dev/" rel="noopener"> Playwright Documentation </Link>
Sada je došlo vrijeme da ponovo izvršimo testove…
~/project$ pnpm test > playwright test --project=chromium --reporter list Running 3 tests using 3 workers ✓ 1 [chromium] > playwright.spec.js:21:3 > Text input > should display the entered text in the text input (1.1s) ✓ 2 [chromium] > playwright.spec.js:14:3 > Playwright link > should navigate to Playwright documentation page (1.1s) ✓ 3 [chromium] > playwright.spec.js:31:3 > Form submission > should display the "Hello, X" message after form submission (1.1s) 3 passed (5.7s)
Testovi su prošli! Zatim je došlo vrijeme da nas odvedemo na Heroku CI.
Slijedio sam upute u Heroku blog postu kako bih postavio svoju aplikaciju u Heroku CI kanal.
U Herokuu sam kreirao novi pipeline i povezao ga sa svojim račvanim GitHub repo.
Zatim sam dodao svoju aplikaciju u staging.
Zatim sam otišao na karticu Testovi i kliknuo na Omogući Heroku CI .
Konačno, modificirao sam app.json
datoteku da uklonim testnu skriptu koja je bila postavljena da poziva npm test:ci
. Već sam uklonio test:ci
skriptu iz mog package.json
fajla. test
skripta u package.json
je sada bila ta koja se koristila, a Heroku CI bi je tražio po defaultu.
Moj app.json
fajl, koji se pobrinuo da koristi Chrome for Testing buildpack, izgledao je ovako:
{ "environments": { "test": { "buildpacks": [ { "url": "heroku-community/chrome-for-testing" }, { "url": "heroku/nodejs" } ] } } }
Gurnuo sam svoj kod na GitHub, i to je pokrenulo probno pokretanje u Heroku CI.
Probni rad nije uspio, ali nisam bio zabrinut. Znao sam da će biti potrebno napraviti neku konfiguraciju dramaturga.
Kopajući po test logu, našao sam ovo:
Error: browserType.launch: Executable doesn't exist at /app/.cache/ms-playwright/chromium-1140/chrome-linux/chrome
Dramatičar je tražio instancu preglednika Chrome. Mogao bih ga instalirati pomoću naredbe playwright install chromium
kao dio svog CI testnog podešavanja. Ali to bi poništilo cijelu svrhu postojanja paketa gradnje Chrome for Testing. Chrome je već instaliran; Samo sam trebao da ukažem na to kako treba.
Osvrćući se na svoj dnevnik podešavanja testa za Heroku, pronašao sam ove redove:
Installed Chrome dependencies for heroku-24 Adding executables to PATH /app/.chrome-for-testing/chrome-linux64/chrome /app/.chrome-for-testing/chromedriver-linux64/chromedriver Installed Chrome for Testing STABLE version 130.0.6723.91
Dakle, pretraživač koji sam želeo da koristim bio je na adresi /app/.chrome-for-testing/chrome-linux64/chrome
. Samo bi mi trebao dramaturg da ga potraži tamo.
Napomena: Ako vas ovdje ne zanimaju sitni detalji, možete preskočiti ovaj odjeljak i jednostavno kopirati cijeli app.json
dolje. Ovo bi vam trebalo dati ono što vam je potrebno da počnete i radite s Playwrightom na Heroku CI.
U Playwrightovoj dokumentaciji, otkrio sam da možete postaviti varijablu okruženja koja govori Playwrightu da li ste koristili prilagođenu lokaciju za sve njegove instalacije u pretraživaču . Ta varijabla env je PLAYWRIGHT_BROWSERS_PATH
. Odlučio sam da počnem tamo.
U app.json
, postavio sam env
varijablu ovako:
{ "environments": { "test": { "env": { "PLAYWRIGHT_BROWSERS_PATH": "/app/.chrome-for-testing" }, ...
Prebacio sam svoj kod na GitHub da vidim šta će se desiti sa mojim testovima u CI.
Očekivano, opet je propao. Međutim, greška dnevnika je pokazala ovo:
Error: browserType.launch: Executable doesn't exist at /app/.chrome-for-testing/chromium-1140/chrome-linux/chrome
To me je prilično približilo. Odlučio sam da uradim ovo:
mkdir -p "$PLAYWRIGHT_BROWSERS_PATH/chromium-1140/chrome-linux"
ln -s \ $PLAYWRIGHT_BROWSERS_PATH/chrome-linux64/chrome \ $PLAYWRIGHT_BROWSERS_PATH/chromium-1140/chrome-linux/chrome
Međutim, bio sam zabrinut da li će ovo biti održivo u budućnosti. Na kraju, Playwright bi koristio novu verziju Chromiuma i više ne bi izgledao kao mapa chromium-1140
. Kako bih mogao shvatiti gdje će Dramski pisac gledati?
Tada sam otkrio da možete izvršiti instalaciju pretraživača na suho.
~/project$ pnpm playwright install chromium --dry-run browser: chromium version 130.0.6723.31 Install location: /home/alvin/.cache/ms-playwright/chromium-1140 Download url: https://playwright.azureedge.net/builds/chromium/1140/chromium-linux.zip Download fallback 1: https://playwright-akamai.azureedge.net/builds/chromium/1140/chromium-linux.zip Download fallback 2: https://playwright-verizon.azureedge.net/builds/chromium/1140/chromium-linux.zip
Ta linija “Instaliraj lokaciju” bila je ključna. A, ako postavimo PLAYWRIGHT_BROWSERS_PATH
, evo šta bismo vidjeli:
~/project$ PLAYWRIGHT_BROWSERS_PATH=/app/.chrome-for-testing \ pnpm playwright install chromium --dry-run browser: chromium version 130.0.6723.31 Install location: /app/.chrome-for-testing/chromium-1140 ...
To je ono što želim. Uz malo awk
magije, uradio sam ovo:
~/project$ CHROMIUM_PATH=$( \ PLAYWRIGHT_BROWSERS_PATH=/app/.chrome-for-testing \ pnpm playwright install --dry-run chromium \ | awk '/Install location/ {print $3}' ) ~/project$ echo $CHROMIUM_PATH /app/.chrome-for-testing/chromium-1140
Kada sam sve to shvatio, jednostavno sam trebao dodati skriptu test-setup
u app.json
. Pošto je PLAYWRIGHT_BROWSERS_PATH
već postavljen u env
, moja skripta bi bila malo jednostavnija. Ovo je bio moj konačni app.json
fajl:
{ "environments": { "test": { "env": { "PLAYWRIGHT_BROWSERS_PATH": "/app/.chrome-for-testing" }, "buildpacks": [ { "url": "heroku-community/chrome-for-testing" }, { "url": "heroku/nodejs" } ], "scripts": { "test-setup": "CHROMIUM_PATH=$(pnpm playwright install --dry-run chromium | awk '/Install location/ {print $3}'); mkdir -p \"$CHROMIUM_PATH/chrome-linux\"; ln -s $PLAYWRIGHT_BROWSERS_PATH/chrome-lin ux64/chrome $CHROMIUM_PATH/chrome-linux/chrome" } } } }
Ukratko ću proći kroz šta radi test-setup
:
Računajući za PLAYWRIGHT_BROWSERS_PATH
, koristi playwright install -- dry-run
sa awk
da bi se odredio korijenski folder u kojem će Playwright tražiti Chrome pretraživač. Postavlja ovo kao vrijednost za varijablu CHROMIUM_PATH
.
Kreira novu fasciklu (i sve potrebne roditeljske fascikle) u CHROMIUM_PATH/chrome-linux
, što je stvarna fascikla u kojoj će Playwright tražiti chrome
binarni fajl.
Kreira simboličku vezu u tom folderu za Chrome da ukazuje na Heroku buildpack instalaciju Chromea ( /app/.chrome-for-testing/chrome-linux64/chrome
).
Sa mojom ažuriranom datotekom app.json
, Playwright bi trebao moći koristiti instalaciju Chromea iz paketa za izgradnju. Bilo je vrijeme da još jednom izvršimo testove.
Uspjeh!
Skripta test-setup
radila je kako se očekivalo.
Dramaturg je uspeo da pristupi chrome
binarnoj verziji i pokrene testove, koji su prošli.
End-to-end testiranje za moje web aplikacije postaje sve manje glomazno, pa mu sve više dajem prioritet. Posljednjih dana to je značilo i više korištenja Playwrighta. Fleksibilan je i brz. I sada kada sam obavio posao (za sebe i za vas !) da ga pokrenem i pokrenem sa paketom gradnje Chrome for Testing u Heroku CI, mogu ponovo početi sa izgradnjom svojih testnih paketa za automatizaciju pretraživača.
Kod za ovo uputstvo je dostupan u mom GitHub repozitorijumu .
Sretno kodiranje!