ディップのフロントエンド課でフロントエンドエンジニアをしている@e_fullです!
Playwrightの導入検証を行う中で発生した、Docker上で動かしたテストレポートが見れない現象と戦った話について書いていきます。初投稿ながら大変なボリュームかつ、Playwrightユーザーに向けたニッチな内容ですが誰かの参考になれば嬉しいです☺️
TL;DR
Playwrightのレポートは本番運用を想定していないため、Reactアプリのようにそれ単体で動かしても外部からアクセスできるようになっていません。
そのため、ローカルで起動したDocker上でPlaywrightのレポートを実行して、ホストOSからhttp://localhost:9323
にアクセスしてもアクセスできません。
対処方法としてはPlaywrightが起動しているDocker内にNginxでリバースプロキシの設定を行なってホストOSから通信可能にしてあげる必要があります。この投稿ではその過程と解決策について説明します!
はじめに
フロントエンド課ではLaravelによる本開発前にUIを確認できるよう、phpファイルによるスケルトンというテンプレートを作成しています。(スケルトンは社内用語)
スケルトンではアトミックデザインの概念を取り入れた構成となっているため、MoleculeやAtomなどの共通コンポーネントが存在します。
共通コンポーネントに手を入れた場合、対象外のスケルトンに意図しない変更が発生していないか確認する必要がありますが、これまではこうしたデグレの確認を個々人がキャプチャを作成して比較することで対応していました。
この確認作業改善のためにVRT導入を検討し、Playwrightの動作検証を行なっています。
PlaywrightはMicrosoftがPuppetterからフォークして開発しているテスト自動化フレームワークです。
前提
前提としてローカルでテスト対象のwebアプリが起動していることを想定しています。
また、今回のPlaywrightのインストール先はテスト対象のwebアプリのリポジトリ内です。
そもそもなぜDockerを利用してPlaywrightを動かしたかったのかというと、実施する環境によって結果がブレる場合があったためです。
当初はローカルに起動している開発環境であるDocker内にPlaywrightをインストールして・・・ということを画策して居ました。しかし、Playwrightが前提としているOSと開発環境のOSに乖離があったり、Docker起動時のコマンドが複雑になるなどの理由から諦めかけていたところ、他のチームの方から公式でDockerイメージが提供されていることを教わりました👏🏻
Playwrightの初期設定
まずは開発環境のリポジトリにnpm init playwright@latest
でplaywrightをインストール・初期構築します。
作成されたtestsフォルダ内にあるtests/example.spec.js
を以下の通り書き換えます。
テスト内容は、アクセスしたページ全体のキャプチャを撮ってキャプチャ元と比較するというものです。
"use strict"
// @ts-check
import { test, expect } from '@playwright/test';
const testURL = 'http://localhost:5173/'; //ローカルで起動しているテスト対象のwebアプリ
// テスト実行
test("test", async ({ page }) => {
await page.goto(testURL, { waitUntil: 'domcontentloaded' });
await expect(page).toHaveScreenshot({ fullPage: true });
});
この変更により、ローカルでnpx playwright test
コマンドによってテストの通過が確認できたかと思います。
初回はnpx playwright test -update-snapshots
としないと比較元のキャプチャがなく全てのテストがfailedになってしまいます。
テスト通過後、テストがfailedしていればそのままレポート閲覧のためのサーバーが起動しますが、すべてクリアした場合は処理が終了します。その場合は以下のコマンドでレポート閲覧のためのサーバーを起動します。
npx playwright show-report
ここまでの導入はとても簡単で、テストもjest等のようにnodeベースで記載することができました👏🏻
テスト結果のレポートは以下のように差分が確認できて少しの差もとてもわかりやすくなっています🥳
Docker上でテストを実行
続いてDocker環境を整備して、Docker上でレポートを実行、ホストOSのブラウザでレポートを表示していきます。
イメージは公式で提供されているmcr.microsoft.com/playwright:v1.35.0-jammy
を利用します。
手っ取り早く実行するには、以下のコマンドを投げればビルドされたDocker環境上でテストを実行してくれます。
docker run --rm --network host -v $(pwd):/work/ -w /work/ -it mcr.microsoft.com/playwright:v1.35.0-jammy /bin/bash -c 'npx playwright test'
ターミナル上ではレポートをhttp://localhost:9323
でサーブしたよとメッセージが出ていますが、ホストOSのブラウザからアクセスしてもアクセスできません。
Dockerコマンドでポートが通ってないからかな?と思ってportオプションを足してみたり、PlaywrightのDiscussionを見てみたりしたけど解決策がわからずしばらく彷徨い・・・
以下のページに行きつきました。
コンテナ内で起動しているサーバーがlocalhost指定でListenしている可能性があります。
そこでPlaywrightのコードを深掘りしてみたところ、確かにレポートのサーバーをlocalhostで建てているようでした。
※131行目で初期値がlocalhostなので、何かの設定でhostを変えられるんじゃないかと思いましたがそこまで追えませんでした。
docker-composeとNginxの設定
原因が見えてきたところで上記の参考サイトに記載の通り、コンテナ内でNginxを利用してリバースプロキシを置くことにしました。
docker run …
のコマンドで実行した場合、コンテナ起動後にコンテナに入り、Nginxをインストールしてdefault.confを設定して・・・とテスト実行毎に面倒なことになるので、docker-composeを利用してコンテナを立てることにしました。
まずはリポジトリ内に以下のファイルを用意します。
.
├── docker
│ └── playwright
│ ├── default.conf // Nginx用
│ └── dockerfile
└── playwright-test.yml
それぞれのファイルは以下のように記述します。
server {
listen 9333;
server_name localhost;
location / {
proxy_pass http://localhost:9323;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
FROM mcr.microsoft.com/playwright:v1.35.0-jammy
WORKDIR /app
# Nginxと簡易ファイアウォールのufwをインストール
RUN apt update && apt install -y sudo ufw nginx
# ufw利用のためのユーザーを作成
ARG DOCKER_UID=0333
ARG DOCKER_USER=playwright
ARG DOCKER_PASSWORD=playwright
RUN useradd -m --uid ${DOCKER_UID} --groups sudo ${DOCKER_USER} \
&& echo ${DOCKER_USER}:${DOCKER_PASSWORD} | chpasswd
RUN passwd -d ${DOCKER_USER}
# 作成したユーザーに切り替える
USER ${DOCKER_USER}
version: '3'
services:
playwright:
build: ./playwright
container_name: playwright
ports:
- "9323:9333" #`Playwright test result`
volumes:
- ./playwright/default.conf:/etc/nginx/conf.d/default.conf
- ../:/app/
command: sh -c "sudo ufw enable && sudo ufw allow 'Nginx HTTP' && sudo ufw allow 9333 &&sudo nginx && npx playwright test --trace on --workers 4"
cap_add:
- NET_ADMIN
ここまで環境を整えたら、Dockerを起動します。
docker-compose -f ./docker/playwright-test.yml up
これでDockerを起動するホストOSからhttp://localhost:9323
にアクセスすることでレポートを表示することができました🎉
最終的に以下の図のようなポートを辿ってレポートが表示されるようになりました!
上記のコマンドでテストがパスしてしまって処理が終わった場合は、./docker/playwright-test.ymlのcommand部分をsh -c "sudo nginx && npx playwright show-report"
に変更して動かしてみてください。
補足として、./docker/playwright/dockerfile
でufwを設定していますがなくても動きます。ただし、今後社内サーバーで動かしたいなどの変更があるかもしれないことを見込んで先にFWの設定を入れました。
まとめ
ここまではレポートの表示につまづいたりテスト先のページにアクセスできないなどの問題があったりしつつ、他チームの方に助けて頂きつつ🙏🏻、比較的簡単に導入できたと思っています。
しかし、実行回によって変更していない箇所のテストがfailedになるという実行結果のブレに現在悩まされているので、今後はこの辺りのTipsを共有できればと思っています。
とはいえ、Playwrightを入れることでも十分業務効率が改善する見込みがあります。まずはwebページ一枚っぺらの比較のみで小さく入れて、今後モーダルを動かしたり動的な部分のテストを育てていく予定です。
まだまだ英語情報ばかりですが、1次情報は比較的豊富な印象です。今後もテストを育てつつ業務効率改善していきます💪🏻