この記事はニフクラ 等を提供している、富士通クラウドテクノロジーズ Advent Calendar 2022 の7日目の記事です。
前日は@heriet
さんの trivy+conftestで柔軟にライセンスポリシーをチェックする でした。
ライセンスポリシーのチェックをより容易に、汎用的にできるというのは魅力的で私自身すごく勉強になりました。
はじめに
初めまして!
私は富士通クラウドテクノロジーズ2年目の社員で、基幹システムの運用・開発をしております。
今回は実際に私が部署で管理しているWEBアプリのE2EテストをPlaywightとGitlab CI/CDで自動化した経験から、自動化までの簡単な流れを書こうと思います。
E2Eテストとは
E2E(エンドツーエンド)テストは、User Interface Testとも呼ばれております。
WEBアプリにおいて、ユーザの想定される操作に対し、WEBアプリが正しく動作してくれることを確認する 上流工程のテストになります。
ユーザの動作に基づいてテストケースを作成し実施していくためアプリの正常性を確認するのにとても重要な工程ですが、それが故にテストケースの作成から実施まで時間がかかってしまうという問題点もあります。
なんで自動化するのか
E2Eテストに限らず、システムは大きくなればなるほどテストも肥大化し、エンハンスをしたつもりが気づいたらデグレを引き起こすといったことは往々にしてあります。
そのため、さあテストをしていくぞとなったとき、「本当は全機能テストしたいけど工数が、、」といった悩みに苦しむ人はたくさんいると思います。
しかし、ボタン1つ押すと勝手にテストをやってくれて、その証拠(スクリーンショットとか動画)まで採取してくれたらどうでしょう。 工数の削減・デグレ防止 につながるだけでなく、どうしても単純作業で憂鬱になってしまう(個人差あり)テスト工程をやらなくて済むと良いこと尽くしです。
また、ヒューマンエラーというのはどうしても発生してしまいます。それはテスト工程でも同じように見逃しなどは起きてしまうでしょう。
上記などの理由で皆さん自動化を試みるんだろうと、私は勝手に想像しております。
Playwrightについて
PlaywrightはNodeのライブラリでブラウザ操作をコマンドラインで実現できるものであり信頼できるE2Eテスト実施のために作られたものです。
公式での特徴として以下が挙げられています。
- クロスブラウザ、クロスプラットフォームでのテストが可能
- イベントが豊富に用意されており、不安定なE2Eテストの原因の一つである人為的なタイムアウトを作る必要がなくなる
- テスト再試行を行う上での画面キャプチャや動画ファイルの作成、実行ログ等が豊富
私がこのライブラリを知ったのは1年ほど前で、その当時は比較的新しいものであまりドキュメントもなかったですが触ってみたいという気持ちも込めてPlaywrightで実装を行いました。
手順
では、実際にGitlab CIでE2Eテストを自動化する流れを書いていきます。
フォルダ構成
以下がフォルダ構成です。 testcodes
の中にplaywrgihtのテストコードを置いていきます。
Gitlabプロジェクト
├── .gitlab-ci.yml
├── docs
├── playwright.config.js
└── testcodes
├── 01-01-01.spec.js
├── 01-01-02.spec.js
├── ・
├── ・
├── ・
Gitlab CI/CD
以下の.gitlab-ci.ymlを用意しました。
image: mcr.microsoft.com/playwright:focal
stages:
- test
e2e:
stage: test
script:
- cd docs/
- npm install playwright
- npm install @playwright/test
- npx playwright test
retry:
max: 2
when:
- runner_system_failure
only:
- web
artifacts:
when: always
name: "results"
paths:
- docs/*
exclude:
- docs/testcodes/*
- docs/node_modules/*
- docs/*.js
-
image
: PlaywrightのDockerイメージがあったのでそれを使います。(https://hub.docker.com/_/microsoft-playwright) -
script
: 動作に必要なNodeのパッケージをインストールしてテストを実行します。 -
retry
: 失敗時のリトライ制御です。 -
only
: いつジョブが作成(実行)されるかを制御します。今回はUIからの実行のみにします。 -
artifacts
: ジョブ実行後に、指定されたパス配下のファイルをzip形式で画面からダウンロードします。exclude
を指定すればダウンロードする対象ファイルから指定されたものを除外することが可能です。(今回はPlaywrightの機能で保存されたスクショや動画のみをダウンロードするようにその他を除外している)
詳しくは公式リファレンス参照
playwrgiht
設定ファイルとして playwright.config.js
を用意します。実行フォルダに playwright.config.js
もしくは playwright.config.ts
を置けば勝手に読み込んでくれるみたいです。
module.exports = {
timeout: 100000,
workers: process.env.CI ? 1 : undefined,
testDir:'testcodes',
projects: [
// use Chromium browser.
{
name: 'chrome',
use: {
launchOptions:{
//args:['--proxy-server=' ],
headless: true,
},
baseURL: '<テストするアプリのURL>',
browserName: 'chromium',
viewport: { width: 1280, height: 720 },
video: 'retain-on-failure',
},
},
// use firefox browser.
{
name: 'firefox',
use: {
launchOptions:{
//args:['--proxy-server=' ],
headless: true,
},
baseURL: '<テストするアプリのURL>',
browserName: 'firefox',
viewport: { width: 1280, height: 720 },
video: 'retain-on-failure',
},
},
// use webkit browser
{
name: 'webkit',
use: {
launchOptions:{
//args:['--proxy-server=' ],
headless: true,
},
baseURL: '<テストするアプリのURL>',
browserName: 'webkit',
viewport: { width: 1280, height: 720 },
video: 'retain-on-failure',
},
},
],
};
timeout
: テストの制限時間を設定できます。
testDir
: テストコードがあるディレクトリを指定します。
projects
: こちらに各ブラウザの設定をそれぞれ配列で格納することで、各ブラウザでのテストが実行されます。(上記では chrome,firefox,webkit(safari)で実行されます)
launchOptions
: プロキシの設定や、headlessでのテスト実行などの設定ができます。
video
: 録画ファイルをどのような場合に作成するか設定します。上記の設定は テストが失敗した場合 録画ファイルが保存されるような設定です。
次にテストコードです。
上記で設定したtestcodes
というフォルダにテストコードを保存していきます。
以下にその一例を載せます。
const { test, expect } = require('@playwright/test');
test('[01-01-01-a]アカウント1でのログイン', async ({ page, baseURL,browserName }) => {
// Go to baseURL
await page.goto(baseURL);
// Click [placeholder="アカウント名"]
await page.click('[placeholder="アカウント名"]');
// Fill [placeholder="アカウント名"]
await page.fill('[placeholder="アカウント名"]', 'account1');
// Click [placeholder="パスワード"]
await page.click('[placeholder="パスワード"]');
// Fill [placeholder="パスワード"]
await page.fill('[placeholder="パスワード"]', 'password');
// Click input:has-text("ログイン")
await Promise.all([
page.waitForNavigation(),
page.click('input:has-text("ログイン")')
]);
await page.waitForSelector('text=ロゴイン成功');
expect(page.url()).toBe('<遷移後のURL>');
await page.screenshot({ path: `screenshots/01-01-01-a/${browserName}/1.png`, fullPage: true,});
});
上記のテストコードは、account1
というユーザでログインするというテストです。
以下が流れとなります。
-
page.goto(baseURL);
でplaywright.config.js
に設定したbaseURLにアクセスしますが、認証画面にリダイレクト - プレスホルダーにアカウント名とあるテキストボックスに
account1
,プレスホルダーにパスワードとあるテキストボックスにpassword
と入力します -
waitForNavigation
でページ遷移を待ちつつ、page.click('input:has-text("ログイン")')
でログインと記載されているボタンをクリック -
waitForSelector
でログイン後のページのテキストにある ログイン成功という文字が読み込まれるまで待ち、page.screenshot
でスクショを撮影する(スクショはtestcodes
ディレクトリから相対パスで、screenshots
ディレクトリ > テストNoごとのディレクトリ > ブラウザごとのディレクトリに置いていきます)
また、テストコードを自動で生成してくれるような機能も存在します。
今回は詳細については触れませんので、気になる方はこちらをご確認ください。
動作確認
では実際に動かします!
Gitlabで上記ファイル群を保存したプロジェクトで、CI/CD
> Pipelines
に移動し、 Run pipeline
を押下します
するとテストが実施されます。(実施の様子はe2eジョブの実行時のコンソールを確認してください)
成功すると以下のようにStages
部分にレ点がつきますので
その右のダウンロードっぽいボタンを押してみると、e2eジョブのarchive、、つまりテストで撮影したスクショなどがダウンロードできます!
もちろん失敗した場合も、失敗するまでのスクショと合わせて録画ファイルもダウンロードできるのでなぜ失敗したのか簡単に追うことができます。
以下は実際に失敗したときのコンソールログの様子です。なぜ失敗したか・どこで失敗したかも一目瞭然ですし、ログで分からなくても録画ファイルがあるので確認できますね。
最後に
今回はGitlab CI/CDとPlaywrightを利用して、E2Eテストを自動化してみました。
やってみた感想として、Playwrightはクロスブラウザでのテストが可能だったり、関数がたくさん用意されていて実装に迷いにくいと思いました。
また、私が実際にPlaywrightでE2Eテストを作成していた1年前から、この記事を作成した間に公式のリファレンス・WEB記事ともに充実していて、期待されていて進化を続けているライブラリの一つだと感じました。
今回の成果物を発展させて、デプロイ起点で自動でCIジョブが起動したり、マージリクエストを発行したらコンテナ上でWEBアプリ起動・そのままE2Eテストが走って成功しないとマージできないようにしたりできたらいいなとも思いました。
これからも機会があれば進化を追い続けていきたいのと、それをまた記事にできればと思います。
この記事は富士通クラウドテクノロジーズ Advent Calendar 2022 の7日目の記事でした。
明日は @nakanosikaさんの「Istioでカスタムメトリクスの取得をやってみた」です。
私自身Istrioを知らなかったのですが、マイクロサービスのネットワーク管理のフレームワークということで楽しみにしています。