4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

EC-CUBEAdvent Calendar 2023

Day 20

E2Eテストをより簡単に?!〜Playwrightってなんですか?~

Last updated at Posted at 2023-12-20

はじめに

こんばんわ。今日はEC-CUBEアドベントカレンダーの20日目です。
アドベントカレンダーというものに初めて参加するため、何書いたらいいのか先輩方のを参考に悩んでました。
いろいろ考えてたら何やら、E2Eテストについての声が聞こえて来ました。
Playwrightというのがあるらしい。

気になった経緯

一番気になっている理由は、非同期処理に強いことです。
現在のE2Eテストはcodeceptionで書かれているのですが、不安定なことがあります。
ページの要素が見つからないという理由で落ちている事が多く、再実行したらクリアするという謎現象。。。
テストコードを見ていると、Sleep関数がいくつかあります。

上記から、非同期処理に強いPlaywrightが気になりました。
(ちなみにTypeScriptはよくわからないので、雰囲気で書きます。:v:

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コマンドを入力すると、ブラウザが立ち上がりレポートが表示されるとのこと。
実際見てみると、なかなか便利そうです↓
スクリーンショット 2023-12-18 17.29.09.png

簡単なテストケースを作成

次に簡単なケースでテストを作成してみましょう。

  1. https://127.0.0.1:8000/にアクセス(EC-CUBEが立ち上がっているIPアドレス)
  2. h1タグに「EC-CUBE SHOP」があることを確認
  3. スクリーンショットを撮る

こんな感じで実装してみます。

ec-cube.spec.ts
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

正常に完了したようです。
以下のスクリーンショットは実際に撮影されたものです。
example.png

ナビまでしか表示されてないですが、スクリーンショット自体は撮れていますね!
Playwrightでは特定の要素の表示を待つ事ができるので、ここにSleepを入れなくても取得できます。

EC-CUBEのE2Eを書いてみる

試しにトップページのテスト(EF01TopCest:topページ_初期表示
)を1部書いてみたいと思います。
テストの中身の処理は2つになります。

  1. カテゴリ選択ボックス(キーワード検索用)、キーワード検索入力欄、虫眼鏡ボタンが表示チェック
  2. カテゴリ名(カテゴリ検索用)が表示チェック
    それぞれの行の説明はコードに記載します。
ec-cube.spec.ts
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に関しては、もっと良い方法がありそうなので、引き続き見ていきたいと思います。

参考サイト

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?