はじめに
はじめまして、河村康治です。HITOTSUアドベントカレンダーの11日目担当します!!
普段はバックエンドを主に担当しているのですが、テスト基盤構築に力をいれて行こうと思い、今回のアドベントカレンダーではフロントのテストに関して記載して行こうと思います!!!
今回は、Playwrightを活用したE2Eテストの記事を書いて行きます!!
Playwrightとは??
Microsoft開発中のE2Eのテストライブラリです。もう少しイメージしやすく言うと、SeleniumやPuppeteerなどのスクレイピング実行やコード生成を実行できるツールです。最近の開発では採用される事が増えており、リグレッションテストや受け入れテストを自動化し、テスト工数を削減し品質を高める事に一役買っています!!
Playwrightの強みは??
結局、SeleniumやPuppeteerと比べて何がいいかと言うと、一番はコードを自動生成してくれる所です。スクレイピングを実施する場合、Domツリーを解析しコードに落とし込むのが大変。やった人ならばわかるのですが、開発者ツール開いて、class名は〜〜で、idは〜〜みたいな感じでコード解析し、コードに落とし込む。で、トライ&エラーを繰り返しながら作る。ただ、PlaywrightならばGUIでポチポチしていく事でコードが自動生成されます。百聞は一見にしかずなので、下記動画をご覧ください。
■サンプル動画(iphoneの購入サイトへの画面遷移)
E2Eテスト
では、実際にPlaywrightを利用しE2Eテストの実装をしていきましょう!!今回は、Redmineを元にテストを実施していきたいと思います。
Redmineの準備
version: '3.8'
services:
redmine:
image: redmine
container_name: redmine
ports:
- 3010:3000
volumes:
- ./data/plugins:/usr/src/redmine/plugins
- ./data/themes:/usr/src/redmine/public/themes
environment:
REDMINE_DB_MYSQL: redmine-db
REDMINE_DB_PASSWORD: redmine
depends_on:
- redmine-db
restart: always
redmine-db:
image: mariadb
container_name: redmine-db
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: redmine
MYSQL_DATABASE: redmine
volumes:
- ./data/db:/var/lib/mysql
command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
restart: always
これでOK!!
http://localhost:3010/
でアクセスし、ユーザIDとパスワード共に、adminで入れます。
その後、パスワード変更やプロジェクト作成やトラッカー作成などの準備が必要です。
成果物は下記動画の様になります。
ソースコード
yarn create playwright ←これすると、Playwrightで必要な定義ファイルを作ってくれます。
~/develop/react/playwright_test$ tree -I node_modules
.
├── README.md
├── docker-compose.yml
├── package.json
├── playwright-report
│ ├── data
│ │ └── 9e7d941236a5e77523b746a304baf6cab737bbc8.webm
│ └── index.html
├── playwright.config.ts
├── prettier.config.js
├── tests
│ ├── example.spec.ts
│ └── redmine.spec.ts
├── tsconfig.json
└── yarn.lock
7 directories, 15 files
/* eslint-disable testing-library/prefer-screen-queries */
import { test, expect } from '@playwright/test'
import * as dotenv from 'dotenv'
dotenv.config()
test('test', async ({ page }) => {
const userName = process.env.REACT_APP_USER_NAME || ''
const password = process.env.REACT_APP_PASSWORD || ''
await page.goto('http://localhost:3010/')
await page.getByRole('link', { name: 'ログイン' }).click()
await page.getByLabel('ログインID').click()
await page.getByLabel('ログインID').fill(userName)
await page.getByLabel('ログインID').press('Tab')
await page.getByLabel('パスワード\n パスワードの再設定').fill(password)
await page.getByRole('button', { name: 'ログイン' }).click()
await page.locator('#top-menu').getByRole('link', { name: 'プロジェクト' }).click()
await page.getByRole('link', { name: 'test' }).click()
await page.locator('#main-menu').getByRole('link', { name: 'チケット' }).click()
await page.getByRole('link', { name: '新しいチケット' }).click()
await page.getByLabel('題名 *').fill('PlayWright test')
await page.getByLabel('説明').click()
await page.getByLabel('説明').fill('PlayWright test')
await page.locator('input[name="commit"]').click()
await page.waitForTimeout(3000) // 確認様に3秒待機
const actual = await page.locator('h2').first().innerText() // ①データ取得
console.log('actual:', actual)
await expect(actual).toContain('テスト') // ②値比較
})
ソースコード実装時のPoint
基本的に、npx playwright codegen localhost:3010
を利用して記載していきます。
ただ、データ取得や値の比較は実装する必要があるため、記載していきます。
①データ取得
ブラウザの開発者モードを開き、DOMツリーを解析。解析結果を当てはめます。
②実行値と期待値の検証
今回はチケットのタイトルが「テスト」であるかを検証項目としています。タイトルは「テスト #19」のように余計な値が含まれており、#19
はチケット番号を含むため、可変の値となります。そのため、完全一致ではなく、部分一致するかを確認する検証としています。
Appendix
Playwrightの設定ファイル
import type { PlaywrightTestConfig } from '@playwright/test';
import { devices } from '@playwright/test';
const config: PlaywrightTestConfig = {
testDir: './tests',
/* Maximum time one test can run for. */
timeout: 30 * 1000,
expect: {
timeout: 5000,
},
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
actionTimeout: 0,
headless: false, // ブラウザを表示するかどうか
/* Base URL to use in actions like `await page.goto('/')`. */
launchOptions:{
slowMo: 1000, // テスト実行時のスローモーション
},
trace: 'on-first-retry',
},
projects: [
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
locale: 'ja-JP', // ロケールを日本語に設定
},
},
],
};
export default config;
覚えておきたい事は下記。
①ヘッドレスモードの有無。テスト実行時にブラウザ表示するか。デバッグ時には必須機能!!
②テスト実行時の速度設定。デフォルト設定の場合実行速度が速すぎるため、デバッグ時はスローモーション設定必須。
③ローケールの設定
use: {
actionTimeout: 0,
headless: false, // ブラウザを表示するかどうか
/* Base URL to use in actions like `await page.goto('/')`. */
launchOptions:{
slowMo: 1000, // テスト実行時のスローモーション
},
trace: 'on-first-retry',
},
projects: [
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
locale: 'ja-JP', // ロケールを日本語に設定
},
},
Playwrightで覚えておきたい関数
①何秒か待つ
Debug時や処理を待ちたい時に利用する関数
await page.waitForTimeout(3000)
②動きを止める
Debug時に開発者ツールでセレクターや値を確認する。
await page.pause()
test実行時に覚えておきたいオプション
①ブラウザ表示有りで実行
playwright.config.tsでも定義できますが、開発時はブラウザあり、リグレッションテスト時はブラウザ無し等の要望に答えるため、実行時パラメータで制御可能です!!
~/develop/react/playwright_test$ npx playwright test redmine.spec.ts --headed
②デバッグモードでのテスト実行
ブレークポイントを利用したテストが可能となります。
~/develop/react/playwright_test$ npx playwright test redmine.spec.ts --debug
実行部分がStepByStepで確認でき、赤いポインターが出てどこのセレクターを指しているのかわかりやすいです!!
③show-traceの活用
え、こんなこともできるの、PlayWrightって感じだった機能です。テスト実行時に動作毎にスクショを撮り、後でどんな動きをしたのかを確認できる機能です。事前にコードを仕込む必要があるので、それも記載しておきます。
~/develop/react/playwright_test$ npx playwright show-trace ./trace.zip
test('test', async ({ page, context }) => {
await context.tracing.start({ screenshots: true, snapshots: true }) ←最初に記載する。
const userName = process.env.REACT_APP_USER_NAME || ''
const password = process.env.REACT_APP_PASSWORD || ''
await page.goto('http://localhost:3010/')
~~~~~~~~~~~~~~~~~~~~~割愛~~~~~~~~~~~~~~~~~~~~~~~~~~~
await expect(actual).toContain('テスト')
await context.tracing.stop({ path: 'trace.zip' }) ←最後に記載する。
})
上記画像の様に、各スクリーンショットに対し、実行時間やSelector、値等のさまざまな情報が含まれており、DebugやTrobuleシューティングですごい役立ちそうな機能です!!しかも、Before、Action、Afterのスクショがならんでいるので、ここで何したっていうのが一目瞭然なんですよ!!
SIerで働いてた時、こんな風にスクショ取ってExcelにペタペタ貼ってたので、これは感動しました😭
最後に
Playwrightの学習は、Youtubeを中心にやりました。公式サイトや海外Youtuberの方が懇切丁寧に解説してくれているため、効果的に利用すると学習しやすいですよ!!!ちなみに僕は下記で学習しております。