はじめに
今回はE2EテストツールであるPlaywrightとPupeteerをGithub Actionsのワークフロー上で動くように設定した際の手順の整理です。PlaywrightとPupeteerどちらも使ってみましたが、テストコードに使う関数や設定周りほとんど同じような印象でした。
1. Typescript + Jest + Playwright/Pupeteerの設定
まずはTypescriptでPlaywright/Pupeteerのテストを実行するのに必要な設定周りです。
1.1 Playwright
必要なライブラリのインストール
npm i -D playwright jest ts-jest jest-playwright-preset jest-image-snapshot @types/jest-image-snapshot
jest-playwright.config.js
serverOptions
に別プロセスで実行するコマンドを指定することができる(下記 npm start
でPlaywrightがアクセスする、フロントエンドのリソースを返すWebサーバを起動)
module.exports = {
launchOptions: {
headless: true,
},
serverOptions: {
command: "npm start",
port: 3000,
},
browsers: ["chromium"],
};
jest.config.js
module.exports = {
preset: "jest-playwright-preset",
transform: {
"^.+\\.ts?$": "ts-jest",
},
setupFilesAfterEnv: ["<rootDir>/jest.setup.ts"],
};
jest.setup.ts
jest.setTimeout
は各テスト実行に必要な時間に応じて変更。
import { toMatchImageSnapshot } from "jest-image-snapshot";
jest.setTimeout(30000);
expect.extend({ toMatchImageSnapshot });
tsconfig.json
{
"compilerOptions": {
"types": [
"@types/jest",
"@types/jest-image-snapshot",
"jest-playwright-preset",
"expect-playwright"
],
...
}
}
1.2 Pupeteer
必要なライブラリのインストール
npm i -D puppeteer jest ts-jest jest-puppeteer jest-image-snapshot @types/puppeteer @types/jest-environment-puppeteer @types/jest-image-snapshot
jest-puppeteer.config.js
module.exports = {
launch: {
dumpio: true,
headless: process.env.HEADLESS !== "false",
},
server: {
command: "npm start",
port: 3000,
},
}
jest.config.js
module.exports = {
preset: "jest-puppeteer",
transform: {
"^.+\\.ts?$": "ts-jest",
},
setupFilesAfterEnv: ["<rootDir>/jest.setup.js"],
globalSetup: "./jest.global-setup.js",
};
jest.global-setup.js
const { setup: setupPuppeteer } = require("jest-environment-puppeteer");
module.exports = async function globalSetup(globalConfig) {
await setupPuppeteer(globalConfig);
};
jest.setup.js
jest.setTimeout
は各テスト実行に必要な時間に応じて変更。
require("expect-puppeteer");
const { toMatchImageSnapshot } = require("jest-image-snapshot");
jest.setTimeout(30000);
expect.extend({ toMatchImageSnapshot });
2. テストコードを書く
jest-image-snapshot を使ってページのレンダリング結果のスナップショット生成し、前回同じテストが走った際とスナップショットに差異があればエラーが発生するようにします。デフォルトの設定だと __image_snapshots__
ディレクトリにスナップショットのpngと差異があった際のdiffのpngが保存されます。
beforeAll(async () => {
await page.goto("https://www.example.com/")
})
test("Should display the page correctly", async () => {
const image = await page.screenshot({
fullPage: true,
});
expect(image).toMatchImageSnapshot({
customSnapshotIdentifier: "ExamplePage",
});
});
3. Playwright/Pupeteer用のDockerの準備
最初にDockerを使わずにMacのローカルでテストを実行してスナップショットを生成し、GithubのレポジトリにpushしてGithub Actions上で同じテストを実行してみました。しかしOSが違うことによりフォントのレンダリングに微妙な差異が出てテストがfailしてしまい、同じ環境を確保するためDockerを使用する必要がありました。ここから先はPlaywrightしか試していないのですが、Pupeteerも基本同様の設定で問題ないはずです。
Playwrightには公式のDockerイメージがあるのですが、こちら日本語のフォントがインストールされていないため、そのまま使うと日本語の文字が豆腐文字になってしまいます。そのため日本語フォントのインストールをDockerfileに含めます。
Dockerfile
FROM mcr.microsoft.com/playwright:v1.5.1-bionic
# 日本語フォントのインストール
RUN apt-get install -y curl fontconfig fonts-noto-cjk \
&& fc-cache -fv
ARG UPDATE_SNAPSHOTS
ENV UPDATE_SNAPSHOTS "$UPDATE_SNAPSHOTS"
...
# スナップショットを更新する際は UPDATE_SNAPSHOTS=true を環境変数で渡す
CMD sh -c "if $UPDATE_SNAPSHOTS == 'true'; then npm run test:update; else npm run test; fi"
4 Github Actionsの設定
upload-artifactを使ってテスト失敗時にスナップショットのDiffがダウンロードできるようにします。
...
- run npm e2e # 上記DockerfileでE2Eテストを実行
- if: failure()
uses: actions/upload-artifact@v1
with:
name: image_snapshots_${{ github.sha }}
path: __tests__/medium/e2e/__image_snapshots__
まとめ
以上、Github ActionsでPlaywright/PupeteerのE2Eテストを行った際の手順でした。ご参考になればと思います。