後輩くんに「E2Eテストなんか怖い😣」と言われたので「ソンナコトナイヨー☀」を体験してもらうために書く。
Table of Contents Playwright Fast and reliable end-to-end testing for modern web apps | Playwright とりあえず、今回はこのPlaywrightってやつを使ってみよう。 まずは「なんか怖い」を払拭するためだから理由とかは脇においておこう。 でも軽快だし、クロスブラウザできるし、スクリーンショットやビデオも取れるし、いいぞ。
Playwrightをインストール Docker使ってくぞ。まずは準備だ。
インストールは公式ドキュメント見てこう。
Installation | Playwright $ docker compose run playwright yarn create playwright
? Do you want to use TypeScript or JavaScript ?
? Where to put your end-to-end tests ?
? Add a GitHub Actions workflow ?
? Install Playwright browsers ( can be done manually via 'yarn playwright install' ) ?
? Install Playwright operating system dependencies ( requires sudo / root - can be done manually via 'sudo yarn playwright install-deps' ) ?
いろいろなディレクトリやファイルが生成されているな。
こんな感じになってるはず。
browsersとoperating system dependenciesはほしいので、Dockerfile
に書いてこう。
COPY package.json $WORKDIR
RUN yarn playwright install && yarn playwright install-deps
CMD [ "yarn" , "playwright" , "test" ]
Dockerfile
いじったのでもう一度ビルドしておく。
準備はこんなとこでOKかな。
テストを実行してみる 最初からtests/sample.spec.ts
ってサンプルテストコードがあるじゃないか。
import { test, expect } from '@playwright/test' ;
test ( 'has title' , async ({ page }) => {
await page. goto ( 'https://playwright.dev/' );
// Expect a title "to contain" a substring.
await expect (page). toHaveTitle ( / Playwright / );
test ( 'get started link' , async ({ page }) => {
await page. goto ( 'https://playwright.dev/' );
// Click the get started link.
await page. getByRole ( 'link' , { name: 'Get started' }). click ();
// Expects the URL to contain intro.
await expect (page). toHaveURL ( / . * intro / );
test()
ってのが2つある。これがテストケースだな。 その後に'has title'
、'get started link'
ってテキストが付いてるけど、テストケース名だろう。 コメントアウトで説明も書かれているけど、なんかコードからある程度わかりそうだな。
has title page.goto()
で括弧内のURLにアクセスしてそう。 page.goto('https://playwright.dev/')
は https://playwright.dev/ にアクセスしてるんだろう。
expect(page).xxx
で何かを検証していそうだな。 例えばexpect(page).toHaveTitle(/Playwright/)
は、ページのタイトルに「Playwright」が含まれていることを検証していそうだ。 このページのタイトルは「Fast and reliable end-to-end testing for modern web apps | Playwright」みたいだからパスしそう。
get started link page.goto('https://playwright.dev/')
はhas title
のテストと同じだ。
page.getByRole('link', { name: 'Get started' }).click()
は、「Get strted」ってテキストを持つリンクをクリックしているんだろう。ページトップにあるボタンだな。
expect(page).toHaveURL(/.*intro/)
でURLがintro
で終わるか見てるな。 実際遷移先のURLはhttps://playwright.dev/docs/intro
だからこれもパスしそう。
これを回してみよう。
パスした。 ちなみにtests/sample.spec.ts
にはtest()
は2つしかないけど6つのテストがパスしてる。 そしてコンソールを眺めてると[chromium]
,[firefox]
,[webkit]
の文字が見えた。 そう、すでにクロスブラウザでテストしてやがる。やりやがる。
この辺は、playwright.config.ts
を眺めるとなんとなくわかる。
export default defaultConfig ({
use: { ... devices[ 'Desktop Chrome' ] },
use: { ... devices[ 'Desktop Firefox' ] },
use: { ... devices[ 'Desktop Safari' ] },
/* Test against mobile viewports. */
// name: 'Mobile Chrome',
// use: { ...devices['Pixel 5'] },
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
/* Test against branded browsers. */
// name: 'Microsoft Edge',
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
// name: 'Google Chrome',
// use: { ..devices['Desktop Chrome'], channel: 'chrome' },
DesktopのChrome、Firefox、Saferiでテストしたようだ。 そしてコメントアウトにさらなる夢を感じる。
テストを書いてみる 自分でもテストを追加してみたい。
Writing tests | Playwright 公式ドキュメントが丁寧。
https://playwright.dev/ にはページトップに「Playwright enables reliable end-to-end testing for modern web apps.」ってヒーロータイトルがある。これを検証してみよう。
test ( 'has hero title' , async ({ page }) => {
await page. goto ( 'https://playwright.dev/' )
await expect (page. getByRole ( 'heading' , { name: 'Playwright enables reliable end-to-end testing for modern web apps.' })). toBeVisible ()
要素はLocatorsというもので指定するらしい(page.getByRole('header', { name: xxx })
のとこ)。 toBeVisible()
で存在していること(見えていること)を検証している。 詳しくは、公式ドキュメントを参照。
Locators | Playwright ちなみにclass
を使ったりして指定もできる。
test ( 'has hero title' , async ({ page }) => {
await page. goto ( 'https://playwright.dev/' )
await expect (page. locator ( '.hero__title' )). toHaveText ( 'Playwright enables reliable end-to-end testing for modern web apps.' )
どちらの書き方にせよ、9つのテストがパスしたはず。
おぉ...なんかこんな感じでなんだってできそうだな..。
Locatorに対する操作もいろいろ..。
Locator | Playwright Assertionもいろいろ..。
PageAssertions | Playwright LocatorAssertions | Playwright これ、なんでもできるんじゃないの...??
失敗も見とく ちゃんと失敗するのかも見ておこう。
test ( 'has hero title' , async ({ page }) => {
await page. goto ( 'https://playwright.dev/' )
await expect (page. getByRole ( 'heading' , { name: 'Playwright enables reliable end-to-end testing for modern web apps.' })). toBeVisible ()
await expect (page. getByRole ( 'heading' , { name: 'Playwright enables reliable end-to-end testing for modern web apps.' })).not. toBeVisible ()
.toBeVisible()
の前に.not
をつけた。これで「存在しない(見えない)」ことを検証することになる。 でも実際はあるから失敗するはず。
[chromium] › example.spec.ts:20:5 › has hero title
[firefox] › example.spec.ts:20:5 › has hero title
[webkit] › example.spec.ts:20:5 › has hero title
3つ失敗してる。期待通り。
ちなみにplaywrightはテストのレポートも作ってくれる。 playwright-report/index.html
というファイルが生成されているので、ブラウザで開いて見てみよう。
うわぁ。見やすい..。
詳細まで見られるんですか..。
失敗時のオプションを少し追加 でも失敗時どうだったのか、このレポートからではわからない。 と思ったらテストオプションがめっちゃ豊富。
TestOptions | Playwright import { defineConfig, devices } from '@playwright/test' ;
export default defineConfig ({
video: 'retain-on-failure' ,
失敗時にスクリーンショットとビデオを撮ることにしてみた。 もう一度テストを失敗させて、レポートを見ると..。
便利すぎ!
怖くないよね? ということで、怖くなかったよね? むしろめっちゃ味方。頼れるやつやE2E。Playwrightすげぇ。 公式ドキュメント見るとページありすぎて「沼...。今はやめておこう...。」となるレベル。 でもやりたいことはコレくらいの労力で達成できますね。 それでちょっとずつ沼にハマれば、この公式ドキュメントの量は期待感しかない!
ということで、沼にはまろう!