Playwright

フロントエンドでE2Eテストと言えば、最近ではCypressやPlaywrightが有名です。 実際のブラウザで動作させることで、信頼度の高いテストを実現します。

どのテストを重視するかについては重要な話題ですがここではいったんおいておきます。

私が個人で開発しているとあるアプリでE2Eの自動テストを実施できるようにしましたので、それの備忘録です。

Playwrightについて

ほかにも機能はありますが、気になった特徴を記載しておきます。

  • クロスブラウザ対応
    Chromium(Chrome, Edge)、Firefox、Webkit (Safari)などに対応していることが売りです。FirefoxやWebkitについてはPlaywrightのチームが独自にパッチを当てたカスタムビルドが起動するようです。

  • 公式のVSCode拡張機能
    Playwright Test for VSCode
    テストのデバッグや、Locator(後述します)の選択などができます。 Playwrightの開発はMicrosoftが主導して行われています。VSCodeも同じです。そのため、積極的に利用していく理由になるでしょう。

    Playwright Test for VSCode
  • 記述を簡易化する機能が提供されている
    VSCode拡張機能や、Playwrightが提供しているguiツールでは、Locatorを自動選択する機能があります。Locatorとは、 page.getByRole('button', { name: 'テーマ変更' }) のように画面の要素を選択するコードのことです。公式が推奨している、ユーザから見える文言やアクセシビリティのロールなどで取得する記述を優先したセレクターを選んでくれます。この記法に慣れていない方や、慣れていても書くのが面倒な場合でも非常に有用です。

Playwright の導入

Playwrightは次のコマンドを使用することで、対話形式で現在の環境に合わせて設定をすることができます。 使用しているパッケージマネージャーに合わせてコマンドを使用してください。

# npm
npm init playwright@latest
# yarn
yarn create playwright
# pnpm
pnpm create playwright
  • TypeScriptかJavaScriptか
  • e2eテストコードを配置するフォルダ名
  • GitHub Actions workflowのコードを追加するか
  • Playwrightのテストを実行するブラウザをあわせてインストールするか

をそれぞれ聞かれます。

Playwrightのテストを実行するブラウザについては、package.jsonの管理外で端末ごとにインストールが必要ですが、
npx playwright installでインストールができます。もしテスト実行時にブラウザがインストールされていなければインストールが必要であるとのエラーメッセージがでますので、プロジェクトで使用する場合は、別途メンバーに案内しておくとよいでしょう。

インストールが完了すると、

  • package.json に @playwright/testの追加
  • .gitignoreの追記
  • playwright.config.tsの追加
  • サンプルテストコードの追加
  • (GitHub Actions workflowのコードを追加するを選択した場合) playwright.ymlの追加

playwright.config.tsの設定

テンプレートのままでも良さそうですが、最低限、以下の設定はしたほうがよいです。

  • アプリケーションのBaseURL
  • ローカル開発サーバ
playwright.config.ts
export default defineConfig({
  ... 省略 ...
  /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
  use: {
    /* Base URL to use in actions like `await page.goto('/')`. */
    // baseURL: 'http://127.0.0.1:3000',

    /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
    trace: 'on-first-retry',
  },
  /* Run your local dev server before starting the tests */
  // webServer: {
  //   command: 'npm run start',
  //   url: 'http://127.0.0.1:3000',
  //   reuseExistingServer: !process.env.CI,
  // },
  ... 省略 ...
});

use.baseURL には、テストで使用するアプリケーションのURLを指定します。

webServerの設定は、テスト実施時にローカルサーバを起動させることができるので、その設定です。

  • command: テスト用サーバの起動用コマンド
  • url: テスト用サーバのlisten url
  • reuseExistingServer: 開発サーバがすでに起動中の場合、再利用するか

テンプレートのコメントでは、commandにはnpm run startが入っていますが、ここは使用しているフレームワークに合わせたコマンドに変更するのがよいかと思われます。 私が個人で開発しているアプリケーションでは、ローカル開発では利便性を優先してnpm run devで起動を行い、CIで実行するときはnpm run buildでビルド後、npm run previewで起動しています。

レスポンシブのテスト設定

Playwrightは自分でブラウザの種類とテストを行うViewportの大きさなどの設定をすることもできるが、多様なプリセットが用意されています。

PC向けのView Portだけでなく、TabletやMobile向けのViewportをテストしたい場合、configファイルをPC用、mobile用にそれぞれ作成すると良いです。 playwrightのconfigの定義に使用する import { defineConfig } from '@playwright/test';defineConfigはconfigのマージ機能がもともとありますので、共通設定を作成した後、個別設定を作成できます。 playwright.config.tsには共通設定を記載して、playwright.pc.config.tsをPC用の設定に、playwright.mobile.config.tsをmobile用の設定として使うことにします。

ちなみに、playwrightのconfigファイルは、コマンド実行時の-cまたは--configオプションで読み込むことができますが、VSCodeの拡張機能に認識させるためには、**/*playwright*.config.{ts,js,mjs}'にマッチする名前にすると良いみたいです。 [拡張機能の該当ソース]

設定で特に重要なのは2つで、
1つ目はもちろんprojectsにテストするdeviceを設定しておくこと、2つ目はテストフォルダの指定です。

PCとmobileで共通のテストコードが一切ない場合は、それぞれのconfigのtestDirで直接PC用のテストコードフォルダ、mobile用のテストコードフォルダを設定すればよいですが、共通して実施したいテストコードもある場合は、すべてのテストコードが含まれるフォルダを共通設定で指定した後、mobileならPC、PCならmobileのフォルダを除外するという方針で行くとよさそうです。

フォルダ構成
playwright.config.ts
export default defineConfig({
  testDir: 'tests/e2e/test',
  ... 省略 ...
playwright.pc.config.ts
import { defineConfig, devices } from '@playwright/test';
import baseConfig from './playwright.config';

export default defineConfig(
  baseConfig,
  defineConfig({
    testIgnore: ['**/mobile/**'],
    projects: [
      /* Test against pc viewports. */
      {
        name: 'chromium',
        use: { ...devices['Desktop Chrome'] },
      },
      {
        name: 'firefox',
        use: { ...devices['Desktop Firefox'] },
      },
      {
        name: 'webkit',
        use: { ...devices['Desktop Safari'] },
      },
    ],
  }),
);
playwright.mobile.config.ts
import { defineConfig, devices } from '@playwright/test';
import baseConfig from './playwright.config';

export default defineConfig(
  baseConfig,
  defineConfig({
    testIgnore: ['**/pc/**'],
    projects: [
      /* Test against mobile viewports. */
      {
        name: 'Mobile Chrome',
        use: { ...devices['Pixel 5'] },
      },
      {
        name: 'Mobile Safari',
        use: { ...devices['iPhone 12'] },
      },
    ],
  }),
);

Playwrightのコーディングについてはぼちぼち記事を書いていこうかなと思います。