ã2026幎çãPlaywrightã®å§ãæ¹ â ã€ã³ã¹ããŒã«ããæåã®E2Eãã¹ããŸã§å®å šã¬ã€ã
- Playwrightã®ã€ã³ã¹ããŒã«ãšãã©ãŠã¶ã»ããã¢ãã
- ããŒãžæäœïŒã¯ãªãã¯ã»å ¥åã»ã¢ãµãŒã·ã§ã³ïŒã®åºæ¬
- ãã¹ãã®å®è¡ãšãã¬ãŒã¹ãã¥ãŒã¢ã§ã®ãããã°
- GitHub ActionsïŒCIïŒãžã®çµã¿èŸŒã¿
ã³ãã³ãæ©èŠè¡š
# ã€ã³ã¹ããŒã«
npm init playwright@latest
# â ãã¹ãèšèªããã©ãŠã¶ãCIã¯ãŒã¯ãããŒãéžæ
# ãã¹ãå®è¡
npx playwright test # å
šãã¹ãå®è¡
npx playwright test --headed # ãã©ãŠã¶ã衚瀺ããªããå®è¡
npx playwright test example.spec.ts # ç¹å®ãã¡ã€ã«ã®ã¿
npx playwright test --trace on # ãã¬ãŒã¹åéããŠå®è¡
npx playwright show-report # HTMLã¬ããŒãã衚瀺
npx playwright show-trace trace.zip # ãã¬ãŒã¹ã衚瀺
// tests/example.spec.ts
import { test, expect } from '@playwright/test';
test('ãããããŒãžã®ã¿ã€ãã«ç¢ºèª', async ({ page }) => {
await page.goto('https://example.com');
await expect(page).toHaveTitle(/Example/);
});
test('ãã°ã€ã³ãã©ãŒã ã®ãã¹ã', async ({ page }) => {
await page.goto('/login');
// ãã©ãŒã ã«å
¥å
await page.getByLabel('ã¡ãŒã«ã¢ãã¬ã¹').fill('user@example.com');
await page.getByLabel('ãã¹ã¯ãŒã').fill('password');
await page.getByRole('button', { name: 'ãã°ã€ã³' }).click();
// ãã°ã€ã³åŸã®URLã確èª
await expect(page).toHaveURL('/dashboard');
});
// playwright.config.tsïŒãã«ããã©ãŠã¶èšå®ïŒ
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
],
reporter: 'html',
use: {
screenshot: 'only-on-failure',
video: 'retain-on-failure',
trace: 'on-first-retry',
},
});
ããããè©°ãŸããã€ã³ã
Q. SeleniumãCypressãšã®éãã¯ïŒ Seleniumã¯ãã©ãŠã¶ããšã«ãã©ã€ããŒã®èšå®ãå¿ èŠã§ãAPIãå€ããŠæžãæ¹ãåé·ãªããšãå€ãããCypressã¯APIãã·ã³ãã«ã§äººæ°ã ãã©ãChromiumã®ã¿ã»è€æ°ãªãªãžã³ã®ãã¹ããèŠæã»Node.jsããã»ã¹å€ã®æäœãé£ãããšããå¶éãããããPlaywrightã¯ãããã®èª²é¡ãè§£æ¶ããŠããŠã2024幎以éã®æ°èŠãããžã§ã¯ãã§ã¯Playwrightãéžã¶ã±ãŒã¹ãå¢ããŠãããã ã
Q. ãã¹ããäžå®å®ïŒFlakyïŒã«ãªããã©ãããã°å®å®ããïŒ
äžçªå€ãåå ã¯ãèŠçŽ ããŸã æç»ãããŠããªãã®ã«ã¯ãªãã¯ããããšãããã¿ã€ãã³ã°åé¡ã ããPlaywrightã®Locatorã¯èªåãªãã©ã€ãããã©ãããã§ãäžå®å®ãªã await page.waitForLoadState('networkidle') ã§ãããã¯ãŒã¯ã鿢ãããŸã§åŸ
ã€ããexpect(locator).toBeVisible() ã§è¡šç€ºã確èªããŠããã¢ã¯ã·ã§ã³ãããšããããpage.waitForTimeout(1000) ã¿ãããªåºå®ã¹ãªãŒãã¯æåŸã®ææ®µã«ããŠãã
Q. ãããã¬ã¹ã¢ãŒãã§ãªããšé
ããCIã§ã¯å¿
ãheadlessã«ãã¹ãïŒ
--headed ãªãã·ã§ã³ïŒãã©ãŠã¶è¡šç€ºããïŒã¯ãããã°ç®çã§äœ¿ããã®ã§ãCI/CDã§ã¯headlessã¢ãŒãïŒããã©ã«ãïŒã§åããã®ãæ£è§£ã ãããã©ãŠã¶GUIã®æç»ããªãåã ãã¶éããªãããããŒã«ã«ã§ããããã°ãäžèŠãªéåžžå®è¡ã¯headlessã«ããŠããã¹ãã倱æãããšãã ã --headed ã --debugïŒPlaywright Inspectorèµ·åïŒã§åå ã調ã¹ãã®ãå¹ççã ãã
Playwrightã£ãŠãã©ãŠã¶ãèªåã§æäœã§ããããŒã«ãªã®ïŒ
ããã ããMicrosoftãéçºããE2EïŒEnd-to-EndïŒãã¹ããã¬ãŒã ã¯ãŒã¯ã§ãChromiumãFirefoxã»WebKitãã³ãŒãã§èªåæäœã§ãããã ãããã¿ã³ãã¯ãªãã¯ããããã°ã€ã³ã§ããããããã©ãŒã ãéä¿¡ãããæ£ããããŒãžã«é·ç§»ããããã¿ãããªãŠãŒã¶ãŒèŠç¹ã®ãã¹ããèªååã§ãããã
Seleniumã¯å€ããã䜿ãããŠãããèšå®ãè€éã§é ããCypressã¯ã·ã³ãã«ã ãã©ãã©ãŠã¶ãChromiumã®ã¿ã§ãè€æ°ã¿ããå¥ãªãªãžã³ã®æ±ãã«å¶éãããããPlaywrightã¯Chromiumã»Firefoxã»WebKitã®3ãšã³ãžã³å¯Ÿå¿ã§ã䞊åå®è¡ãéããMicrosoftè£œã§æŽ»çºã«ã¡ã³ããããŠããã®ã匷ã¿ã ãã
ã€ã³ã¹ããŒã«ã¯ã©ãããã®ïŒ
`npm init playwright@latest` ãå®è¡ãããšå¯Ÿè©±åœ¢åŒã§ã»ããã¢ããããŠããããããã¹ãèšèªïŒTypeScript/JavaScriptïŒã»ãã©ãŠã¶ã®éžæã»CIã¯ãŒã¯ãããŒã®çæãŸã§èªåã§ãã£ãŠãããããã©ãŠã¶ã®ãã€ããªãèªåããŠã³ããŒããããããæåã€ã³ã¹ããŒã«ã¯äžèŠã ãããã²è©ŠããŠã¿ãŠïŒ
ãã¹ãã£ãŠã©ããã£ãŠæžãã®ïŒ
`test('ãã¹ãå', async ({ page }) => { })` ãšããåœ¢ã§æžããã`page.goto(URL)` ã§ããŒãžãéããŠã`page.getByRole('button', { name: 'ãã°ã€ã³' }).click()` ã§ã¯ãªãã¯ã`expect(page).toHaveURL('/dashboard')` ã§çµæãæ€èšŒãããã ãè±èªã«è¿ãèªç¶ãªæžãæ¹ã§ãã¹ãã®æå³ãèªã¿ããããã
èŠçŽ ãæ¢ããšãã¯ã©ãæžãã°ããã®ïŒ
Playwrightã§ã¯Locatorãšããä»çµã¿ã§èŠçŽ ãæå®ãããã`getByRole`ïŒARIAããŒã«ïŒã»`getByLabel`ïŒã©ãã«ïŒã»`getByText`ïŒããã¹ãïŒã»`getByTestId`ïŒdata-testid屿§ïŒã®4ã€ãäž»ãªã¡ãœããã ããCSSã»ã¬ã¯ã¿ããæå³ãäŒãããããããããŒãžæ§é ãå€ãã£ãŠãå£ãã«ããããç©æ¥µçã«äœ¿ããšãããã
ãã¹ãã倱æãããšãã«ã©ã調ã¹ãã®ïŒ
Playwrightã®ãã¬ãŒã¹ãã¥ãŒã¢ã匷åã ãã`--trace on` ãªãã·ã§ã³ãä»ããŠãã¹ããå®è¡ãããšãå šæäœã®é²ç»ã»ã¹ã¯ãªãŒã³ã·ã§ããã»ãããã¯ãŒã¯ãã°ã `trace.zip` ã«ä¿åããããã ã`npx playwright show-trace trace.zip` ã§å°çšUIãéããŠã倱æããç¬éã®ç»é¢ã確èªã§ãããã
è€æ°ãã©ãŠã¶ã§äžåºŠã«ãã¹ãã§ããã®ïŒ
ã§ãããã`playwright.config.ts` ã® `projects` ã§äœ¿ããã©ãŠã¶ãæå®ãããã ã`chromium` `firefox` `webkit` ãå šéšåæããã°ãäžåºŠã® `npx playwright test` ã§3ãã©ãŠã¶åã®ãã¹ãã䞊åã§èµ°ãããSafariïŒWebKitïŒã§ã®ã¬ã€ã¢ãŠã厩ããèªåæ€åºã§ãããããã¯ãã¹ãã©ãŠã¶å¯Ÿå¿ã«åœ¹ç«ã€ãã ã
ã¹ã¯ãªãŒã³ã·ã§ãããåç»ã®èšé²ãã§ããã®ïŒ
ã§ãããã`screenshot: 'only-on-failure'` ãšèšå®ãããšå€±ææã ãã¹ã¯ãªãŒã³ã·ã§ãããä¿åãããã`video: 'retain-on-failure'` ã«ãããšå€±æãããã¹ãã®æäœåç»ãä¿åããããã ãHTMLã¬ããŒããèŠããšç»åã»åç»ä»ãã§çµæã確èªã§ããŠãããã°ããšãŠã楜ã«ãªããã
GitHub Actionsã§CIã«çµã¿èŸŒãã«ã¯ã©ãããã®ïŒ
`npm init playwright@latest` ã®èšå®æã«ãAdd GitHub Actions workflowããéžã¶ãš `.github/workflows/playwright.yml` ãèªåçæãããããããã·ã¥ã®ãã³ã«èªåã§E2Eãã¹ããèµ°ãã倱æãããPRã®ããŒãžããããã¯ã§ãããã ããã©ãŠã¶ã®ãã€ããªãã£ãã·ã¥ãèšå®ããŠãããããå®è¡æéãçããªããã
JestãšPlaywrightã¯ã©ã䜿ãåããã®ïŒ
Jestã¯ãŠããããã¹ãã»ã³ã³ããŒãã³ããã¹ãåãã§ããã©ãŠã¶ãªãã§é«éã«åãããPlaywrightã¯å®éã®ãã©ãŠã¶ãåããE2Eãã¹ãå°çšãªãã ãã颿°ãã³ã³ããŒãã³ãã®åäœåäœãæ€èšŒããã â Jestããç»é¢é·ç§»ããŠãŒã¶ãŒæäœã®ãããŒãæ€èšŒããã â Playwrightããšäœ¿ãåããã®ãåºæ¬ã ãã
ãã¹ããã©ã³ãã ã«å€±æããïŒFlakyïŒã®ã¯ãªãïŒ
éåæåŠçã®ã¿ã€ãã³ã°ããããããšãäž»ãªåå ã ããPlaywrightã¯Locatorã«èªåãªãã©ã€æ©èœããã£ãŠãèŠçŽ ãçŸãããŸã§äžå®æéåŸ ã£ãŠããããã ãããã§ãäžå®å®ãªã `page.waitForSelector` ã `page.waitForResponse` ã§æç€ºçã«åŸ ã€ãšãããã`sleep` ã䜿ã£ãåºå®åŸ æ©ã¯ç°å¢ã«ãã£ãŠé ããããéããããããããé¿ããŠãã