とことんDevOps | 日本仮想化技術のDevOps技術情報メディア

DevOpsに関連する技術情報を幅広く提供していきます。

日本仮想化技術がお届けする「とことんDevOps」では、DevOpsに関する技術情報や、日々のDevOps業務の中での検証結果、TipsなどDevOpsのお役立ち情報をお届けします。
主なテーマ: DevOps、CI/CD、コンテナ開発、IaCなど
読者登録と各種SNSのフォローもよろしくお願いいたします。

Playwrightを使ってPleasanterのE2Eテストをやってみよう

Pleasanterでは、JavaScriptやCSSなどをカスタマイズして標準ではサポートされていない機能を追加できます。何かしらのカスタマイズを行った場合、エンジニアであれば十分なテストをしてからリリースしますが、Pleasanterでは現場の方も巻き込んでプログラミングできる方も開発に参加するケースがあります。そのような時でも最低限の動作を保証したり、不具合に早期に気づけるような仕組みとしてE2Eテストを導入することが有効です。

また、主要な業務プロセスを2E2テストでカバーすることにより、新しいバージョンがリリースされた際に、そのバージョンが正常に動作するかどうかを確認すできます。新しいバージョンを素早く顧客に提供ができますし、問題が発生した場合には素早く対応できます。

他にも手動での動作確認では、回帰テストなどが担当者の負担となったり、テストの網羅性が担保されないこともあります。そのため、E2Eテストを自動化することで、テストの網羅性を高め、テストの効率化を図ることができます。

早速、Playwrightを使ってPleasanterのE2Eテストをやってみましょう。

Playwrightとは

Playwrightは、ブラウザの自動化を行うためのツールです。Playwrightを使うことで、ブラウザの操作を自動化できます。Playwrightは、Chromium、Firefox、WebKitの3つのブラウザエンジンをサポートしており、クロスプラットフォームのブラウザテストも効率的に行うことができます。

https://playwright.dev/

環境構築

初期化

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を使って、権限が異なる複数アカウントのテストを自動化できると動作確認の効率が上がりますね。