Pleasanterでは、JavaScriptやCSSなどをカスタマイズして標準ではサポートされていない機能を追加できます。何かしらのカスタマイズを行った場合、エンジニアであれば十分なテストをしてからリリースしますが、Pleasanterでは現場の方も巻き込んでプログラミングできる方も開発に参加するケースがあります。そのような時でも最低限の動作を保証したり、不具合に早期に気づけるような仕組みとしてE2Eテストを導入することが有効です。
また、主要な業務プロセスを2E2テストでカバーすることにより、新しいバージョンがリリースされた際に、そのバージョンが正常に動作するかどうかを確認すできます。新しいバージョンを素早く顧客に提供ができますし、問題が発生した場合には素早く対応できます。
他にも手動での動作確認では、回帰テストなどが担当者の負担となったり、テストの網羅性が担保されないこともあります。そのため、E2Eテストを自動化することで、テストの網羅性を高め、テストの効率化を図ることができます。
早速、Playwrightを使ってPleasanterのE2Eテストをやってみましょう。
Playwrightとは
Playwrightは、ブラウザの自動化を行うためのツールです。Playwrightを使うことで、ブラウザの操作を自動化できます。Playwrightは、Chromium、Firefox、WebKitの3つのブラウザエンジンをサポートしており、クロスプラットフォームのブラウザテストも効率的に行うことができます。
環境構築
初期化
Playwrightには初期化コマンドが用意されているので、それを使って初期化します。
npm init playwright@latest
初期化コマンドを実行すると、いくつかの質問が表示されます。以下のように回答します。
? Do you want to use TypeScript or JavaScript? … ❯ TypeScript JavaScript
使用する言語を選択します。今回はTypeScriptを選択します。
? Where to put your end-to-end tests? › tests
テストコードを配置するディレクトリを指定します。今回はtests
ディレクトリを指定します。
? Add a GitHub Actions workflow? (y/N) › false
GitHub Actionsのワークフローを追加するかどうかを尋ねられます。今回は追加しないのでfalse
を選択します。
? Install Playwright browsers (can be done manually via 'npx playwright install')? (Y/n) › true
Playwrightのブラウザをインストールするかどうかを尋ねられます。今回はインストールするのでtrue
を選択します。
テストの実行
Playwrightの初期化が完了したら、始めから用意されているサンプルコードを実行して主要なコマンドを確認します。
ヘッドレスモードでテストを実行する
npx playwright test
UIモードでテストを実行する
npx playwright test --ui
特定のブラウザでテストを実行する
npx playwright test --project=chromium
特定のテストファイルを実行する
npx playwright test example
デバッグモードでテストを実行する
npx playwright test --debug
テストコードの自動生成
npx playwright codegen
Pleasanterのログインしてみよう
codegenコマンドを使って、Pleasanterのログイン画面を自動生成します。コードが生成されたら、example.spec.ts
を以下のように修正します。
import { test, expect } from '@playwright/test'; test('test', async ({ page }) => { await page.goto('{{PleasanterのURL}}'); await page.getByPlaceholder('ログインID').click(); await page.getByPlaceholder('ログインID').fill('{{PleasanterのログインID}}'); await page.getByPlaceholder('パスワード', { exact: true }).click(); await page.getByPlaceholder('パスワード', { exact: true }).fill('{{Pleasanterのパスワード}}'); await page.getByRole('button', { name: 'ログイン' }).click(); await expect(page.getByRole('link', { name: 'image', exact: true })).toBeVisible(); await expect(page.getByRole('link', { name: 'トップ' })).toBeVisible(); });
多少冗長なコードは生成されますが、基本的な操作は自動生成されるので、それを元に整えるだけでテストコードを作成できます。
実際に実行してみたらデフォルトの言語設定が英語になっていたので、日本語に変更しました。
playwright.config.ts
に以下の設定を追加します。
import { defineConfig, devices } from '@playwright/test'; export default defineConfig({ ... use: { ... + locale: 'ja-JP', + timezoneId: 'Asia/Tokyo', ... }, });
共通の認証処理を作成しよう
Playwrightには毎回実施するログイン処理を共通化する機能が用意されています。
auth.setup.ts
というファイルを作成し、example.spec.ts
からログイン処理を切り出します。
import { test, expect } from '@playwright/test'; import path from 'path'; const authFile = path.join(__dirname, '../playwright/.auth/user.json'); test('authenticate', async ({ page }) => { await page.goto('{{PleasanterのURL}}'); await page.getByPlaceholder('ログインID').click(); await page.getByPlaceholder('ログインID').fill('{{Pleasanterのパスワード}}'); await page.getByPlaceholder('パスワード', { exact: true }).click(); await page.getByPlaceholder('パスワード', { exact: true }).fill('{{Pleasanterのパスワード}}'); await page.getByRole('button', { name: 'ログイン' }).click(); await expect(page.getByRole('link', { name: 'image', exact: true })).toBeVisible(); await expect(page.getByRole('link', { name: 'トップ' })).toBeVisible(); await page.context().storageState({ path: authFile }); });
playwright.config.ts
に以下の設定を追加します。
import { defineConfig, devices } from '@playwright/test'; export default defineConfig({ ... projects: [ + { name: 'setup', testMatch: /.*\.setup\.ts/ }, { name: 'chromium', use: { ...devices['Desktop Chrome'], + storageState: 'playwright/.auth/user.json', }, + dependencies: ['setup'], }, { name: 'firefox', use: { ...devices['Desktop Firefox'], + storageState: 'playwright/.auth/user.json', }, + dependencies: ['setup'], }, { name: 'webkit', use: { ...devices['Desktop Safari'], + storageState: 'playwright/.auth/user.json', }, + dependencies: ['setup'], }, ... });
環境変数
今のままではソースコードに直接ログインIDやパスワード記載することになってしまい、セキュリティ上の問題が発生します。そのため、Playwrightで使用するログインIDやパスワードなどは環境変数として.env
ファイルに記述しておくと便利です。
.env
ファイルを作成し、以下のように記述します。
npm install dotenv
import { test, expect } from '@playwright/test'; import path from 'path'; + import dotenv from 'dotenv'; + dotenv.config(); const authFile = path.join(__dirname, '../playwright/.auth/user.json'); test('authenticate', async ({ page }) => { + const pleasanterLoginId = process.env.PLEASANTER_LOGIN_ID; + + if (!pleasanterLoginId) { + throw new Error('PLEASANTER_LOGIN_ID is not set'); + } + + const pleasanterPassword = process.env.PLEASANTER_PASSWORD; + + if (!pleasanterPassword) { + throw new Error('PLEASANTER_PASSWORD is not set'); + } await page.goto('{{PleasanterのURL}}'); await page.getByPlaceholder('ログインID').click(); await page.getByPlaceholder('ログインID').fill( - '{{Pleasanterのパスワード}}' + pleasanterLoginId ); await page.getByPlaceholder('パスワード', { exact: true }).click(); await page.getByPlaceholder('パスワード', { exact: true }).fill( - '{{Pleasanterのパスワード}}' + pleasanterPassword ); await page.getByRole('button', { name: 'ログイン' }).click(); await expect(page.getByRole('link', { name: 'image', exact: true })).toBeVisible(); await expect(page.getByRole('link', { name: 'トップ' })).toBeVisible(); await page.context().storageState({ path: authFile }); });
.env
ファイルに以下のように記述します。
PLEASANTER_LOGIN_ID={{PleasanterのログインID}} PLEASANTER_PASSWORD={{Pleasanterのパスワード}}
おわりに
今回はシンプルなパターンでE2Eテストを実行してみました。 動作の中でも面倒なテストパターンの上位に入るのが、権限ごとの動作確認です。 Playwrightを使って、権限が異なる複数アカウントのテストを自動化できると動作確認の効率が上がりますね。