
前編のおさらい
前編となる「事前準備編」では、自動化に必要なツールとして Node.js
VSCode
Playwright
の3つをインストールしました。この後編では、いよいよ自動化にトライしてみたいと思います。
▼前編はこちら
【第1回・前編】まずはやってみよう – Playwrightを使ったハンズオン(事前準備編)
テスト対象とテストケース
今回は、PlaywrightのWebサイトにあるデモ用のTODOアプリ https://demo.playwright.dev/todomvc/#/ を使ってみます。以下のような手順で、TODOアプリの基本的な動作をチェックすることにします。
テストケース:TODOアプリの基本操作
- TODOアプリにアクセスする
- 新しいTODO項目「買い物リストを作成」を追加する
- TODO項目「買い物リストを作成」が追加されていることを確認する
- 2つ目のTODO項目「牛乳を買う」を追加する
- TODO項目「牛乳を買う」が追加されていることを確認する
- 最初のTODO項目を完了状態にする
- 残りのTODO数が「1 item left」と表示されることを確認する
テストを記録する
E2E自動テストを作成するには、実際のWebサイトへの操作を 記録 してテストコードを出力する方法と、まっさらな状態からテストコードを 記述 する方法の2通りがあります。実務上は、完全にまっさらな状態からテストコードを記述するのはちょっと面倒なので、記録した内容を元にコードを微修正するのが手っ取り早いです。
テストコードの記録はVSCodeの拡張機能を使って行います。Playwrightをインストールすると、VSCodeの左側に表示されているフラスコのようなマークから、現在作成されているテストの一覧や、新しいテストの記録などができるようになります。

Record Newをクリックすると、新しいウィンドウが立ち上がり、ページ内で実施したアクションが記録されていきます。
また、レコーディングウィジェットを使うと、要素の情報を取得したり、ページに正しい情報が表示されているかどうかの検証をセットしたりできます。

- 🔴: レコーディングの停止。
- ▲: 要素の情報の取得。クリックした要素の情報がVSCodeの
Playwright
タブに表示される。 - 👁️: 要素が表示されていることを検証。
- ab: 表示されている文字列の検証。
- ⌨️: 値(value)の検証。
- <>: Ariaスナップショットの検証。
一連の操作と検証を記録すると、次のようなコードが生成されます。このうち、await page
から始まるものはページへの操作、 await expect
から始まるものは検証ステップです。
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('https://demo.playwright.dev/todomvc/#/');
await page.getByRole('textbox', { name: 'What needs to be done?' }).click();
await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('買い物リストを作成');
await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter');
await expect(page.getByTestId('todo-title')).toBeVisible();
await expect(page.getByTestId('todo-title')).toContainText('買い物リストを作成');
await page.getByRole('textbox', { name: 'What needs to be done?' }).click();
await page.getByRole('textbox', { name: 'What needs to be done?' }).fill('牛乳を買う');
await page.getByRole('textbox', { name: 'What needs to be done?' }).press('Enter');
await expect(page.locator('body')).toContainText('牛乳を買う');
await page.getByRole('listitem').filter({ hasText: '買い物リストを作成' }).getByLabel('Toggle Todo').check();
await expect(page.locator('body')).toContainText('1 item left');
});
記録したテストは、左側のツールバーから実行できます。

テストコードの解説
ここで、生成されたテストコードについて簡単に解説しておきます。
要素選択
テストコードの中で、繰り返し page.getByRole('textbox', { name: 'What needs to be done?' })
という表現が出てきました。これは、ページの中から特定の要素を探すための書き方です。要素とは、ページの中のある一部分を指します。ボタンやテキストボックスなどのパーツのことだと考えてください。
現代のE2Eテストでは、「要素がどんな意味を持っているか」を手がかりに画面内の要素(ボタン、入力フォームなど)を記述するのが一般的です。例えば、上記のコードでは以下のような意味を持つ要素を探しています。
- 役割が
textbox
である - 名前(この場合は書いてあるテキスト)が
What needs to be done?
である
余談ですが、以前自動テストにトライしたことがある人は、 getByRole
の代わりに getElementById
のようなコードを書いたことがあるかもしれません。以前は自動テストのコードを書くときに id
や class
などを用いるのが一般的だったのですが、技術の進歩や考え方の変化により、現代では getByRole
のように要素の役割やラベルなど「要素の持つ意味」を使ってテストコードを書くのが一般的になりました。こうした考え方の変遷については今後の連載で説明できればと思いますので、今の段階では一旦「最近は getElementById
は使わないんだ」と覚えておいてください。
検証
TODO項目「牛乳を買う」が追加されていることを確認する
が追加されていることを確認するために、次のようなコードが出力されています。
await expect(page.locator('body')).toContainText('牛乳を買う');
page.locator('body')
とは、ページ全体のことを指します。このステップは、ページ全体のテキストが「牛乳を買う」という文字列を含むことを確認しています。

個人的な好みでは、このような「XXという文字が表示されている」ことを確認する検証ステップについてはこのように「ページのどこかに存在すればOK」としてしまうことが多いです。理由は、一つ前の節「要素選択」で説明したように、ページに表示されている文言を元に要素を探すことが多いため、重複になってしまうためです。
一方で、全く無関係のところに表示されている文言を取得してしまうケースも無くはありません。より厳密に記述したい場合は、次のように listitem
ロールの中から探すようにすることもできます。
await expect(
page.getByRole("listitem").filter({ hasText: "牛乳を買う" })
).toBeVisible();
まとめ
前編・後編を通して、自動化に必要なツールの準備と、拡張機能を使った自動化の方法を学びました。
ここに取り上げたのはあくまで初歩の初歩ですので、もっと勉強すればより良い自動テストが実装できるようになります。一方で、前編の冒頭でも説明したように、いざ学ぼうとすると様々な時代の様々な手法が出てきてしまい、どのやり方が良いのか判断がつかないかもしれません。後編で紹介した id
や class
を使った要素探索が良い例で、ある時期のベストプラクティスが、その後アンチパターンとなってしまうことはままあります。
そこで次回は「E2Eテストの歴史」を取り上げ、なぜPlaywrightのようなモダンなツールが生まれたのか、過去のツールや手法との違いについて解説します。また、「レコードアンドリプレイ」や「ページオブジェクトモデル」、それに「テストピラミッド」など、E2Eテストの発展に影響を与えた重要な概念についても触れる予定です。