PLAY DEVELOPERS BLOG

HuluやTVerなどの日本最大級の動画配信を支える株式会社PLAYが運営するテックブログです。

HuluやTVerなどの日本最大級の動画配信を支える株式会社PLAYが運営するテックブログです。

E2E テストツールの Playwright を試してみた

皆さん、こんにちは。
SaaS 事業部の林と申します。

今回は会社の案件で、E2E (End-to-End) テスト の導入について検討する機会がありましたので、自動 E2E テストツールのひとつである Playwright について簡単にご紹介させていただきます。

E2E (End-to-End) テストとは

E2E (End-to-End) テスト とは、ユーザーがシステムを実際に操作する時の手順を再現して、フロントエンドとバックエンドが期待通りに動作することを検証するテストです。具体的には、お客様の観点から考えて、以下のような操作を行います。

例えば、ユーザー認証を行うシステムの場合:

  • 新規登録フォームから、ユーザーの新規登録ができる。
  • 認証に成功すると、ユーザーのマイページが表示される。
  • パスワードの入力を間違えると、認証エラーが表示される。

上記をブラウザ操作により再現して、システムが期待通りに動作することを検証します。

E2E テストを行うことで、単体テストや結合テストでは見つかりにくいバグを見つけることができます。また、E2E テストを自動化することで、検証時間の短縮や、検証者による個人差のない安定した検証ができます。さらに、複数のブラウザをまとめてテストできるため、ブラウザ固有の問題を検出しやすくなります。

Playwright とは

よく使われる自動 E2E テストツールとして、PlaywrightNightwatch.jsCypress などがあります。今回は Playwright の使い方を紹介します。

Playwright は、ブラウザで自動テストを行うための Node.js ライブラリです。複数ブラウザの WebDriver (Chromium、Firefox、WebKit など) を統一された API で操作できます。テストコードを書いたら、yarn playwright test などのコマンドを実行することにより、テストを実行できます。

Playwright のインストール

今回使用した環境は以下の通りです。

  • OS: macOS Monterey 12.5
  • Node.js: v16.16.0
  • yarn: 1.22.19

まず、以下のコマンドを実行します。

yarn create playwright

今回は JavaScript を選択して、その後 Enter キーを連打します。

 ? Do you want to use TypeScript or JavaScript? ...
   TypeScript
 ❯ JavaScript

インストールが終わると、ディレクトリの中身は以下のようになります。

package.json
playwright.config.js
yarn.lock
tests/
  example.spec.js
tests-examples/
  demo-todo-app.spec.js

上の example.spec.js は実際に Playwright の公式サイトをテストするサンプルテストコードになっています。

以下のコマンドを実行することで、tests/ ディレクトリの下にあるテストコードが実行されます。

yarn playwright test

Playwright の設定

playwright.config.js を開いて、中身を見てみましょう。

const config = {
  testDir: './tests',
  /* Maximum time one test can run for. */
  timeout: 30 * 1000,
  expect: {
    /**
     * Maximum time expect() should wait for the condition to be met.
     * For example in `await expect(locator).toHaveText();`
     */
    timeout: 5000,
  },
  projects: [
    {
      name: 'chromium',
      use: {
        ...devices['Desktop Chrome']
      },
    },
    {
      name: 'firefox',
      use: {
        ...devices['Desktop Firefox'],
      },
    },

// 以下省略

各パラメータの意味は以下の通りです。

testDir

yarn playwright test を実行したとき、そのパスの下にあるテストコードを全て実行します。特定のファイルのみを実行したい場合は、以下のように、コマンドの実行時に後ろに path を付けます。

yarn playwright test ./tests/example.spec.js 
timeout

expct() のタイムアウト時間をミリ秒で指定します。指定した時間内に条件が満たされなかった場合、そのテストは失敗となります。

headless

config オブジェクト内に headless: false を追加すると、ブラウザを表示しながらテストを実行できます。

projects

テストを実行するとき、設定したデバイス(ブラウザ)を全て起動して、検証します。特定のブラウザのみ検証したい場合は、以下のように、コマンドの実行時に後ろに projectname を付けます。

yarn playwright test --project=firefox

テストコード

インストールと設定はここまでです。

次に、実際にブラウザで実行するテストコードについて説明します。今回は、とあるウェブサイトのログイン画面を開き、メールアドレスとパスワードを入力して「ログイン」ボタンをクリックすることで、マイページに遷移することをテストします。

const { test, expect } = require('@playwright/test');

test.describe('とあるウェブサイト', () => {
 
  test('ログイン後にマイページに遷移すること', async ({ page }) => {
    // ログイン画面 URL に遷移
    await page.goto('ログイン画面の URL');

    // メールアドレスとパスワードを入力
    await page.locator('input[type="email"]').fill('メールアドレス');
    await page.locator('input[type="password"]').fill('パスワード');

    // ログインボタンをクリック
    await page.locator('button#login').click();

    // スクリーンショットを取得
    await page.screenshot({ path: 'screenshot.png', fullPage: false });

    // 遷移後のページのタイトルが /マイページ/ という正規表現にマッチすることを確認
    await expect(page).toHaveTitle(/マイページ/);
  });
});

上記コードの内容を説明します。

要素の指定方法について

page.locator('セレクタ');

locator() で CSS Selector や XPath を使用して、要素を指定することができます。指定した要素に対して、 click()fill() などの API を使用して操作を行うことができます。

// 特定の要素に対しクリック動作を実行します
await page.locator('セレクタ').click();

// 特定の要素(input 要素など)に対しテキストを入力します
await page.locator('セレクタ').fill('メールアドレス');

ちなみに、セレクタの取得方法についてですが、例えば Safari の場合、Web インスペクタの「要素」タブで、任意の要素を右クリックして、「コピー」→「セレクタのパス(または XPath)」をクリックすることで、クリップボードにパスがコピーされます(ブラウザによりパスは異なる場合があります)。

スクリーンショットの取得

await page.screenshot({ path: 'ファイル名', fullPage: false });

画面に表示されている部分のスクリーンショットを撮影して、画像ファイルとして保存します。fullPage が true の場合、画面に表示されている部分だけでなく、ページ全体を撮影できます(ただし、モバイル端末の場合 fullPage 画像がうまく取得できない場合があるようです)。

fullPage: false の場合

fullPage: true の場合

テスト実行中の動画

headless: false オプションを指定してブラウザを表示させながらテストを実行したときの PC の画面を録画しました。yarn playwright test コマンドを実行することでブラウザが起動し、自動で操作が行われています。

Android でテストを実行するための準備

Android の実機で Playwright のテストを実行するには、以下のようにします。

  1. Android 側の開発者向けオプションを有効にします。
  2. USB ケーブルで Android 端末を PC に接続します。
  3. Android 側で転送を許可します。
  4. Anrdoid 側の Chrome で chrome://flags を開き、Enable command line on non-rooted devices の設定値を Enabled に変更します。

デバイスが接続されていることを確認するため、以下の adb(Android Debug Bridge)コマンドを実行します。

adb devices

以下のように PC に接続されているデバイスが表示されます。

List of devices attached
RF8NA052RAY device

Android テストコード

先ほどと同様のテストを Android の Chrome ブラウザ上で実行するテストコードです。

const { _android: android } = require('playwright');

test.describe('とあるウェブサイト', () => {
 
  test('ログイン後にマイページに遷移すること', async () => {
    // PC に接続されているデバイスを取得
    const [device] = await android.devices();

    // ブラウザを起動(引数にブラウザを指定しない場合は Chrome が起動)
    const context = await device.launchBrowser();
    const [page] = await context.pages();

    // ログイン画面 URL に遷移
    await page.goto('ログイン画面の URL');

    // メールアドレスとパスワードを入力
    await page.locator('input[type="email"]').fill('メールアドレス');
    await page.locator('input[type="password"]').fill('パスワード');

    // ログインボタンをクリック
    await page.locator('button#login').click();

    // スクリーンショットを取得
    await page.screenshot({ path: 'screenshot.png', fullPage: false });

    // 遷移後のページのタイトルが /マイページ/ という正規表現にマッチすることを確認
    await expect(page).toHaveTitle(/マイページ/);
  });
});

スクリーンショットの取得

await page.screenshot({ path: 'ファイル名', fullPage: false });

PC ブラウザと同様に、画面に表示されている部分のスクリーンショットを撮影して、画像ファイルとして保存できます。ただし、モバイル端末の場合 fullPage: true を指定してもページ全体の画像がうまく取得できない場合があるようです(端末やページの実装にも因ると思います)。

テスト実行中の動画

Android の実機でテストを実行している時の様子を撮影しました。

Nightwatch.js との比較

実は以前、Nightwatch.js で自動 E2E テストを実行していたことがあるのですが、今回 Playwright を触ってみて、両者の違いなど感じたことをまとめてみました。

テストコードの書き方について

両者のテストコードの書き方は似ていますが、Nightwatch.js の場合は、expect API の後ろで before() などを使って猶予時間を設定しておかないと、直ちに検証が実行されてしまうため、対象の HTML 要素が描画される前に操作や検証を実行しようとしてしまい、その結果、検証に失敗するということがよくあります。

Playwright の場合、expect() のタイムアウト時間は playwright.config.js ファイルで設定しています。Nightwatch.js とは違い、すべての操作や検証が非同期なので、expect() を実行するときにいちいち猶予時間を設定する必要がありません。そのため、Playwright のほうが楽だと思います。

// Nightwatch.js
browser.expect.element('セレクタ').text.to.contain('文字列').before(5000);

// Playwright
const locator = page.locator('セレクタ')
await expect(locator).toHaveText(/文字列/);

スクリーンショット機能について

Nightwatch.js はページ全体のスクリーンショットを撮影することができませんが、Playwright は前述の通り、ページ全体のスクリーンショットを撮影することができます。

対応デバイス(ブラウザ)について

Playwright は現時点では iOS でのテストをサポートしていないので、iOS で検証する必要がある場合は Nightwatch.js のほうが良いと思います。

Chrome (win) Firefox (win) Edge (win) Chrome (mac) Firefox (mac) Safari (mac) Safari (iOS) Chrome (android)
Playwright ×
Nightwatch.js

まとめ

今回は自動 E2E テストツールの Playwright についてご紹介しました。自動テストに関心のある方や、検証の精度や所要時間を改善したいと考えている方は、ぜひ導入を検討してみてはいかがでしょうか。