Playwrightの導入からGitHub Actions上でテストを実行するまで
はじめに
ちょくちょく Terraform を触る機会が増えた です。最近、E2E テストフレームワークを調査する機会がありました。E2E テストフレームワークは Playwright 以外にも Cypress などいくつかありますが、個人的には Playwright が1番しっくりきました。今回は Playwright の導入から GitHub Actions 上で実行するところまでを試したので、やったことを備忘録的に残しておこうと思います。
PlayWrightとは
E2E テストを自動化するフレームワークです。
個人的にはこの辺りが魅力的だと感じました。
- クロスブラウザ(WebKit も含む)をサポートしている
- モバイルデバイスをエミュレート(ビューポートなど)してテストできる
構築していく!
テスト用にサンプルアプリを作る
今回は Vite と React でサンプルアプリを作成します。
まずは、下記のコマンドを実行しましょう。
yarn create vite
...
✔ Project name: … sample-app
✔ Select a framework: › react
✔ Select a variant: › react-ts
...
念の為、動作確認しておきます。
yarn dev
http://localhost:3000/ を開いて下記のように表示されれば OK です。
次に、src/App.tsx を下記のように修正します。
import { useState } from 'react'
import logo from './logo.svg'
import './App.css'
function App() {
const [count, setCount] = useState(0)
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
- <p>Hello Vite + React!</p>
+ <p>{count}</p>
<p>
<button type="button" onClick={() => setCount((count) => count + 1)}>
- count is: {count}
+ count up
</button>
</p>
<p>
Edit <code>App.tsx</code> and save to test HMR updates.
</p>
<p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
{' | '}
<a
className="App-link"
href="https://vitejs.dev/guide/features.html"
target="_blank"
rel="noopener noreferrer"
>
Vite Docs
</a>
</p>
</header>
</div>
)
}
export default App
これでサンプルアプリの準備は終わりです。
Playwrightのセットアップ
Playwrightの導入
次は Playwright を導入していきましょう。
npm init playwright@latest
を実行することで、Playwright の設定ファイルやサンプルの spec などが追加されます。後ほど、CI で Playwright を実行するので、GitHub Actions のワークフローも追加しておきましょう。
npm init playwright@latest
...
✔ Do you want to use TypeScript or JavaScript? · TypeScript
✔ Where to put your end-to-end tests? · src/tests
✔ Add a GitHub Actions workflow? (Y/n) · true
...
yarn playwright test
Runs the end-to-end tests.
yarn playwright test --project=chromium
Runs the tests only on Desktop Chrome.
yarn playwright test src/tests/example.spec.ts
Runs the tests of a specific file.
yarn playwright test --debug
Runs the tests in debug mode.
...
よく見ると、実行後のログに使い方が記載されていますね。
yarn playwright test
はターゲットとしている全てのブラウザでテストします。
実行するブラウザは playwright.config.ts
の下記に列挙されているので、
必要に応じて修正すると良さそうです。
const config: PlaywrightTestConfig = {
...
/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
},
},
{
name: 'firefox',
use: {
...devices['Desktop Firefox'],
},
},
{
name: 'webkit',
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: {
// channel: 'msedge',
// },
// },
// {
// name: 'Google Chrome',
// use: {
// channel: 'chrome',
// },
// },
],
...
};
export default config;
yarn playwright test --project=chromium
は指定したブラウザでテストを実行します。
個人的にこの2つのコマンドはよく使いそうだなと思ったので、npm scripts
に登録しました。
{
"name": "sample-app",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite",
+ "e2e:all": "playwright test",
+ "e2e:chromium": "playwright test --project=chromium",
"build": "tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"devDependencies": {
"@playwright/test": "^1.20.2",
"@types/react": "^17.0.33",
"@types/react-dom": "^17.0.10",
"@vitejs/plugin-react": "^1.0.7",
"typescript": "^4.5.4",
"vite": "^2.9.0"
}
}
これでテストを実行できるようになったはずなので、試しにテストを流してみましょう。
yarn e2e:all
...
Running 75 tests using 3 workers
75 passed (13s)
To open last HTML report run:
npx playwright show-report
✨ Done in 13.40s.
うまく実行できたようです🎉
サンプルアプリのテストを追加する
今回は次の操作をした時の振る舞いをテストしてみます。
- count up ボタンを押す
- count が増加していること
まずは空の spec ファイルを追加しましょう。
touch src/tests/countUp.spec.ts
次に上記を確認するテストを追加します。
import { test, expect } from '@playwright/test';
// 各テストを実行する前に http://localhost:3000 に遷移する
test.beforeEach(async ({ page }) => {
await page.goto('http://localhost:3000');
});
test('カウントアップボタンをクリックすると、カウントが増加すること', async ({ page }) => {
// data-testid 属性が count-up-button な要素をクリックする
await page.locator('data-testid=count-up-button').click();
// data-testid 属性が count な要素のテキストが1になっていることを確認
await expect(page.locator('data-testid=count')).toContainText('1');
});
Playwright は data-testid 属性をサポートしているため、要素を data-testid=hoge
のような形で選択できます。他にもサポートしている属性があるので、気になる方はこちらを参照ください。
次はアプリケーション側で該当の要素に data-testid 属性を付与していきます。
import { useState } from 'react'
import logo from './logo.svg'
import './App.css'
function App() {
const [count, setCount] = useState(0)
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
- <p>{count}</p>
+ <p data-testid="count">{count}</p>
<p>
- <button type="button" onClick={() => setCount((count) => count + 1)}>
+ <button type="button" data-testid="count-up-button" onClick={() => setCount((count) => count + 1)}>
count up
</button>
</p>
<p>
Edit <code>App.tsx</code> and save to test HMR updates.
</p>
<p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
{' | '}
<a
className="App-link"
href="https://vitejs.dev/guide/features.html"
target="_blank"
rel="noopener noreferrer"
>
Vite Docs
</a>
</p>
</header>
</div>
)
}
export default App
これでサンプルアプリのテストを実行する準備が整いました。
今回は http://localhost:3000
に遷移してテストを実行するので、
yarn dev
した後に yarn e2e:all src/tests/countUp.spec.ts
を実行してみましょう。(後ほど設定を追加することで、yarn dev
の立ち上げは不要になります)
yarn e2e:all src/tests/countUp.spec.ts
...
Running 3 tests using 3 workers
[1/3] [webkit] › countUp.spec.ts:7:1 › カウントアップボタンをクリックすると、カ
[2/3] [chromium] › countUp.spec.ts:7:1 › カウントアップボタンをクリックすると、
[3/3] [firefox] › countUp.spec.ts:7:1 › カウントアップボタンをクリックすると、
3 passed (1s)
...
どうやらテストがパスしたようです。
念の為、わざとテストを失敗させてみましょう。
import { test, expect } from '@playwright/test';
test.beforeEach(async ({ page }) => {
await page.goto('http://localhost:3000');
});
test('カウントアップボタンをクリックすると、カウントが増加すること', async ({ page }) => {
await page.locator('data-testid=count-up-button').click();
- await expect(page.locator('data-testid=count')).toContainText('1');
+ await expect(page.locator('data-testid=count')).toContainText('2');
});
この状態で再度テストを流してみます。
yarn e2e:all src/tests/countUp.spec.ts
...
[1/3] [webkit] › countUp.spec.ts:7:1 › カウントアップボタンをクリックすると、カ
1) [webkit] › countUp.spec.ts:7:1 › カウントアップボタンをクリックすると、カウントが増加すること ===============================
Error: expect(received).toContainText(expected)
Expected string: "2"
Received string: "1"
...
ちゃんとエラーになりましたね👍
確認が終わったら戻してテストが通るようにしておきましょう。
GitHub Actions 上でテストを実行する
前準備
先ほどローカルで試した時は、yarn dev
した後にテストを流していました。CI 上でも同様の方法でテストしようとすると、テスト用に別途サーバーを立ち上げる必要があり面倒です...
でも安心してください、Playwright にはテスト実行前に dev server
を立ち上げる設定があります🙌
const config: PlaywrightTestConfig = {
...
/* Run your local dev server before starting the tests */
- // webServer: {
- // command: 'npm run start',
- // port: 3000,
- // },
+ webServer: {
+ command: 'yarn dev',
+ port: 3000,
+ },
...
};
これで、テスト実行前に webServer が立ち上がるので、yarn dev
を明示的に実行しなくて良くなります。この状態でテストを流すと yarn dev
を立ち上げなくてもテストできていることが確認できると思います。
ワークフローを修正する
次はワークフローを修正していきます。
name: Playwright Tests
- on:
- push:
- branches: [ main, master ]
- pull_request:
- branches: [ main, master ]
+ on: push
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '14.x'
- name: Install dependencies
run: yarn
- name: Install Playwright
run: npx playwright install --with-deps
- name: Run Playwright tests
- run: yarn playwright test
+ run: yarn e2e:all
- uses: actions/upload-artifact@v2
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
変更したのは次の2点です。
- main or master ブランチ以外を push した時もワークフローを実行する
- npm scripts を実行する
これまでの作業を commit & ブランチを push してみます。
ちゃんとテストが実行されていますね🎉
これで Playwright の導入から GitHub Actions 上でテストを実行するところまで終わりました。
おつかれさまでした!!
終わりに
今回は push 時に全てのブラウザでテストしていますが、毎回これだと時間がかかりすぎるので、いずれ下記のような形に修正したいと思っています。
- push 時 -> どれか 1 つのブラウザでのみテスト
- 週1のビルド時 -> サポートしている全てのブラウザでテスト
試したらまた記事にしようと思います!
参考
Author And Source
この問題について(Playwrightの導入からGitHub Actions上でテストを実行するまで), 我々は、より多くの情報をここで見つけました https://zenn.dev/keita_hino/articles/d38956a2f1880e著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Collection and Share based on the CC protocol