はじめに
こんばんわ。今日はEC-CUBEアドベントカレンダーの20日目です。
アドベントカレンダーというものに初めて参加するため、何書いたらいいのか先輩方のを参考に悩んでました。
いろいろ考えてたら何やら、E2Eテストについての声が聞こえて来ました。
Playwrightというのがあるらしい。
気になった経緯
一番気になっている理由は、非同期処理に強いことです。
現在のE2Eテストはcodeceptionで書かれているのですが、不安定なことがあります。
ページの要素が見つからないという理由で落ちている事が多く、再実行したらクリアするという謎現象。。。
テストコードを見ていると、Sleep関数がいくつかあります。
上記から、非同期処理に強いPlaywrightが気になりました。
(ちなみにTypeScriptはよくわからないので、雰囲気で書きます。)
Playwrightについて
Microsoftさんが主体となって開発しているツールです。
一時期、GitHubのトレンドにもなりました。
機能について、ざっとまとめると以下になります。
- 対象ブラウザ
- Chrome, Firefox, Safariなど
- デバイスのViewport や Geolocation、権限、タッチ操作など、モダンブラウザやモバイルデバイスで使われる機能のエミュレートができる
- テストを安定させるためにsetTimeout(Sleepなど)に依存しない自動化の推奨と、それを推進するためのAPIを提供している
前提
デフォルトでEC-CUBEをインストールして、フロントの表示確認まで済み。
npmのインストール済み。
インストールしてない場合はnpm install npm
環境は以下の通りです。
Mac: Sonoma14.1.1
PHP: 7.4.33
EC-CUBE: 4.2.3
npm: 10.2.3 (更新します。。)
PlayWrigthのインストール
公式のREADMEを参照して進めます。
# Run from your project's root directory
npm init playwright@latest
いろいろ質問されますが、基本はEnterで良いと思います。
Getting started with writing end-to-end tests with Playwright:
Initializing project in '.'
✔ Do you want to use TypeScript or JavaScript? · TypeScript
✔ Where to put your end-to-end tests? · e2e
✔ Add a GitHub Actions workflow? (y/N) · N
✔ Install Playwright browsers (can be done manually via 'npx playwright install')? (Y/n) · true
しばらく待ってHappy hacking! 🎭
が表示されれば、無事インストール完了となります。
インストールしたファイルツリーはこんな感じ。
設定したフォルダ(デフォルトだとe2e)以下のspecファイルが、自動で認識され実行されます。
- ec-cube
- tests-examples
- demo-todo-app.spec.ts #todoアプリをテストするための例
- e2e
- example.spec.ts #簡単なブラウザテストの実行例
- playwright.config.ts #設定ファイル
実際にPlaywrithを実行して、成功するのを念のため確認してみます。
> npx playwright test
Running 6 tests using 5 workers
6 passed (9.4s)
To open last HTML report run:
npx playwright show-report
ちゃんと成功してますね。
この時点でブラウザ別(Chrome, Firefox, Safari)でテストしてくれました。すごい。
レポートが見たい場合は npx playwright show-report
コマンドを入力すると、ブラウザが立ち上がりレポートが表示されるとのこと。
実際見てみると、なかなか便利そうです↓
簡単なテストケースを作成
次に簡単なケースでテストを作成してみましょう。
-
https://127.0.0.1:8000/
にアクセス(EC-CUBEが立ち上がっているIPアドレス) - h1タグに「EC-CUBE SHOP」があることを確認
- スクリーンショットを撮る
こんな感じで実装してみます。
import { test, expect } from '@playwright/test';
test('has shop name', async ({ page }) => {
// goto localhost
await page.goto('https://127.0.0.1:8000/');
// Get the h1 element and expect it
const h1Text = await page.innerText("h1");
expect(h1Text).toBe("EC-CUBE SHOP");
// Get a Screenshot
await page.screenshot({ path: 'example.png' });
});
ここで特徴的なのがexpect関数です。
非同期マッチャーを使用しているため、自動で表示を待つ仕様になっています。(デフォルトでは5000ms)
テストを走らせてみましょう。npx playwright test
コマンドを実行します。
また特定のテストだけの実行もできます。
> npx playwright test ec-cube
Running 3 tests using 3 workers
3 passed (5.2s)
To open last HTML report run:
npx playwright show-report
正常に完了したようです。
以下のスクリーンショットは実際に撮影されたものです。
ナビまでしか表示されてないですが、スクリーンショット自体は撮れていますね!
Playwrightでは特定の要素の表示を待つ事ができるので、ここにSleepを入れなくても取得できます。
EC-CUBEのE2Eを書いてみる
試しにトップページのテスト(EF01TopCest:topページ_初期表示
)を1部書いてみたいと思います。
テストの中身の処理は2つになります。
- カテゴリ選択ボックス(キーワード検索用)、キーワード検索入力欄、虫眼鏡ボタンが表示チェック
- カテゴリ名(カテゴリ検索用)が表示チェック
それぞれの行の説明はコードに記載します。
test('default display for top', async ({ page }) => {
// goto localhost
await page.goto('https://127.0.0.1:8000/');
// カテゴリ選択ボックス(キーワード検索用)、キーワード検索入力欄、虫眼鏡ボタンが表示されている
/* combobox(SelectBox)に含まれる要素を取得して、該当のワードが入っているのかをみている。*/
await expect(page.getByRole('combobox')).toContainText('全ての商品');
await expect(page.getByRole('combobox')).toHaveValue('');
/* キーワード検索入力欄の表示チェック。*/
await expect(page.getByRole('searchbox', { name: 'キーワードを入力' })).toBeVisible();
/* 虫眼鏡(検索ボタン)の表示チェック。*/
await expect(page.getByRole('banner').getByRole('button')).toBeVisible(); // 本家テストの虫眼鏡ボタンは何処へ...?
// カテゴリ名(カテゴリ検索用)が表示されている
/* カテゴリの配列を指定して、ループで回して検査する */
const categories: string[] = ['全ての商品','新入荷','ジェラート','彩のデザート','CUBE','アイスサンド','フルーツ']
for (const category of categories) {
await expect(page.getByRole('combobox')).toContainText(category);
}
});
最後に
実際に書いて思ったのは、locaterの種類が多く難しく感じました。
命名規則は直感的で覚えやすいので、スグに慣れそうなのは良いと思いました。
locaterに関しては、もっと良い方法がありそうなので、引き続き見ていきたいと思います。
参考サイト