E2Eテストで良く使われるツールPlaywrightを2年半ぶりに使ったら、とても使いやすいツールになっていました! 🎭
Bing Image Creatorが生成した画像を元にしています
Playwrigthを使ったE2Eテストの例
いつものReactで書かれたジャンケン・アプリのE2EテストをPlaywrigthを使って書いてみました。
コードの説明は省略しますが、かなりシンプルだと思います。インストールも npm install -save-dev @playwright/test
と設定ファイルを1つ書くだけで済みます。
import { test, expect } from "@playwright/test";
test.describe("pages/index.tsx", () => {
test.beforeEach(async ({page}) => {
await page.goto('http://localhost:3000');
});
test("アクセスすると「じゃんけん ポン!」と表示されている", async ({page}) => {
await expect(page.getByRole("heading")).toContainText(/じゃんけん ポン!/);
});
test("グーをクリックすると対戦が行われ、対戦結果が表示される", async ({page}) => {
await page.getByRole("button", { name: "グー" }).click();
const [_time, human, computer, judgment] = await page.getByRole("cell")
.allTextContents();
expect(human).toBe("グー");
expect(computer).toMatch(/^(グー|チョキ|パー)$/);
expect(judgment).toMatch(/^(勝ち|引き分け|負け)$/);
});
test("グーをクリックした後に対戦成績をクリックすると、対戦成績が表示される",
async ({page}) => {
await page.getByRole("button", { name: "グー" }).click();
await page.getByText("対戦成績").click();
const [win, lose, draw] = await page.getByRole("row").allTextContents();
expect(win).toMatch(/勝ち[01]/);
expect(lose).toMatch(/負け[01]/);
expect(draw).toMatch(/引き分け[01]/);
});
test("2回クリックすると、対戦結果が2行表示される", async ({page}) => {
await page.getByRole("button", { name: "グー" }).click();
await page.getByRole("button", { name: "グー" }).click();
const scores = await page.getByRole("row").filter({hasNotText: /時間/})
.allTextContents();
expect(scores.length).toBe(2)
})
});
アサーション(Assertions)機能が含まれるようになった
初期のPlaywrightは画面なしのブラウザー機能を実現したもので、クリックや文字入力のような操作や、ブラウザーに表示されている文字等を確認する機能のみを持ったツールでした。E2Eテストを書くにはJest等のテスティング・フレームワークと組み合わせる必要がありましたが、現在はアサーション機能が含まれ、他のテスティング・フレームワークが不要になりました。
const text = await page.$eval("h1", (e: Element) => e.textContent);
expect(text).toMatch(/じゃんけん ポン!/);
初期版では上のようにPlaywrightで画面上の表示文字列をJSの文字列として取得し、Jestのアサーションに渡す形になっていました。しかし、現在は下のように専用のアサーションがあるのでテストがすっきり書けるようになりました。
await expect(page.getByRole("heading")).toContainText(/じゃんけん ポン!/);
また、getByText(), getByRole()などのTesting Libraryと同じような問合せAPIが追加されたのも良いですね。
test()の引数にpageオブジェクトがある
初期版では、ブラウザーの起動、ページの取得などの初期コードが必要でpageオブジェクトを自前で準備していました。
let browser: Browser;
let page: Page;
beforeAll(async () => {
browser = await playwright['chromium'].launch({headless: true});
const context = await browser.newContext();
page = await context.newPage();
});
しかし、現在は下のテストコードのように、test()の引数page
を使う事で直ぐにテストが書けます。
test("アクセスすると「じゃんけん ポン!」と表示されている", async ({page}) => {
await expect(page.getByRole("heading")).toContainText(/じゃんけん ポン!/);
});
サーバーの自動起動もできる
現在のPlaywrightの設定ファイル playwright.config.ts
に以下のようにwebServer
項目でアプリを動かすサーバーの自動起動も出来ます!
import type { PlaywrightTestConfig } from "@playwright/test";
import { devices } from "@playwright/test";
const baseURL = "http://localhost:3000";
const config: PlaywrightTestConfig = {
testDir: "./e2e",
webServer: {
command: "npm run dev",
url: baseURL,
timeout: 120 * 1000,
reuseExistingServer: !process.env.CI,
},
use: {
baseURL,
},
projects: [
{
name: 'Desktop Chrome',
use: { ...devices['Desktop Chrome'] },
},
],
};
export default config;
また、projects:に複数の(サポートしている)ブラウザーを追加することで、複数のブラウザーでテストを実行できます。
まとめ
今回は説明出来ませんでしたが、UI Modeでインタラクティブにテストを実行したり、VS Codeと連携したり、人間が行ったブラウザー操作を記録してテストコードを生成する機能もあるようです。→ Test generator
結論として、Playwrightは高機能で使いやすいE2Eテストツールです。 🎭