その他

【Playwright】動的挙動も画面キャプチャできるフレームワーク!

その他
この記事は約14分で読めます。

はじめに

みなさんこんにちは。インプルの岩崎です。

本日はいつもの記事とすこし変わって、技術調査で調べたフレームワークのお話です。

Playwrightとは

今回紹介するPlaywrightとは、Microsoft が開発した E2E(End-to-End)テスト自動化フレームワークです。

Fast and reliable end-to-end testing for modern web apps | Playwright
Cross-browser end-to-end testing for modern web apps

一番の特徴は、ブラウザを自動で操作することができ、以下のことが可能です。

  • 画面キャプチャ(スクリーンショット)
  • 動画・トレース記録
  • 各ブラウザ(Chromium / WebKit / Firefox)対応
  • モバイル相当のデバイスでの動作確認
  • hover・クリック・フォーム入力などの操作
  • ポップアップや新規タブの検知と操作
  • 高速で安定した動作(Seleniumより安定)

特に今回、技術して注目した点が、画面キャプチャ(スクリーンショット)モバイル相当のデバイスでの動作確認hover・クリック・フォーム入力などの操作、の3点に注目しています。今回は、これらの情報をAIに渡して、画面の分析をしてもらうために、このフレームワークに着目しました。

Playwrightのスクリーンショットの撮り方

Playwrightでは、スクリーンショットを撮影するために、コードが必要です。コードで実行する際には、2つのキャプチャ方法があります。

1つ目は、Playwright Test Runner を使う方式です。
E2Eテストの標準的な書き方に従っており、テスト形式でコードがきれいに整理されます。ブラウザの設定・並列実行などが自動で整うようになっています。
npx playwright test で実行し、キャプチャを行うためのコードはtests/xxx.spec.ts に配置します。

2つ目は、Node.js の通常スクリプトとして実行する方式です。
フォルダ名などは自由(scripts/など)にすることができ、Playwright Test Runner を使わないので柔軟にキャプチャなどを実行することができます。自作のプログラムなどを組み込むのであれば、こちらの方が良さそうですね。
node capture.js のように直接実行することができます。

それぞれの手法は、下記のような用途に向いています。

方法向いている用途
① Playwright Test Runnerテスト、UI動作チェック、動的操作
② Node.js スクリプトスクショ大量生成、AI比較、ツール構築

今回のAIと連携して画像解析までをさせる、となると、2つ目のNode.js の通常スクリプトとして実行する方式の方が良さそうですが、今回は練習の意味も込めて、Playwright Test Runner を使う方式も試してみましょう!

① Playwright Test Runner

早速ですが、使ってみましょう。ここでは、まずPlaywrightプロジェクトの構築を行い、実際にAIに画像を渡して分析をしてもらう流れをやってみます。

Playwrightプロジェクトの構築

まずはPlaywightを操作するフォルダを作成します。

mkdir playwright-project
cd playwright-project

続いて、Node.js プロジェクトを作成します。

npm init -y

さて、いよいよPlaywrightをインストールします。
この時点で、Playwright が、Chromium、Webkit、Firefoxの3つを自動インストールします。

npm install -D @playwright/test
npx playwright install

続いて、スクリーンショットを実行するコードを保管しておくファイル(後ほど説明)と、スクリーンショットを保管しておくフォルダを準備しておきましょう。

mkdir tests screenshots

ここまで準備できると、スクリーンショットを取得する準備ができました。一旦ファイル構成のおさらいです。

project-root/
│
├─ package.json
|
├─ node_modules/
│   └─ ...
|
├─ tests/                     ← Playwright が自動で読み込むフォルダ
│   └─ ...
│
└─ screenshots/               ← 撮影した画像を保存(あなたの出力場所)

静的なスクリーンショットを撮影する

まずは静的なスクリーンショットを撮影することで、正しくコードが動作しているいか確認して進めてきましょう!

今回は弊社HPをスクリーンショットしてみることにします。かなりアニメーションが入っていますが、全体がとりあえず撮影されるはずです。

札幌のウェブシステム/スマートフォンアプリ開発会社|株式会社インプル-IMPL
React、ReactNativeのリーディングカンパニー 先進技術を利用したスマートフォンアプリ、ウェブシステムで企業のデジタルトランスフォーメーション、課題解決に取り組みます。

先ほど作った tests/ フォルダに、下記のようなファイルを作成します。ファイル名は basic-cap.spec.ts としておきましょう。await page.goto('https://www.impl.co.jp/'); のURLは、みなさんの任意のURLへ書き換えてください。

import { test } from '@playwright/test';

test('basic screenshot', async ({ page }) => {
  await page.goto('https://www.impl.co.jp/');

  await page.screenshot({
    path: 'screenshots/basic.png',
    fullPage: true,
  });
});

ファイル名は基本的にお任せですが、Playwrightは全てのファイルを認識するわけではありません。ファイル名の後は、必ず下記の4ついずれかが含まれるようにしてください。

  • *.spec.ts
  • *.spec.js
  • *.test.ts
  • *.test.js

その後、下記のコマンドで実行させてみましょう。すると、screenshots/ フォルダに全体のキャプチャが格納されます。

npx playwright test

しかし、よくよくみてみると、アニメーションの発火が遅くうまく動作していませんね。01の左上など、ひどいですね・・・。
しかし、Playwrightでは、これを柔軟に調節することができます。キャプチャするときに数秒待つコードを追加することで、発火後に撮影できるようにしています。先ほどの上記コードを下記のように書き換えてみましょう。コメントアウトを追加した部分が新たに追加したプログラムです。

import { test } from '@playwright/test';

test('basic screenshot', async ({ page }) => {
  await page.goto('https://www.impl.co.jp/');
  await page.waitForLoadState('networkidle'); // ページ内のリソースが完全に読み込まれるまで待つ

  await page.mouse.wheel(0, 500); // 500pxスクロール
  await page.waitForTimeout(1000); // エフェクトが発火する時間待つ。


  await page.screenshot({
    path: 'screenshots/basic2.png',
    fullPage: true,
  });
});

すると、先ほどは表示されていなかった文字が出てきましたね。代わりにヘッダーがついてきてしまいましたが、これも先ほどのような調節で解決することができます。
とりあえず撮影できたようでよかったです。このように、柔軟に調節できる点がいいところですね。

動的なスクリーンショットの撮り方

下記コマンドを実行しましょう。
https://www.impl.co.jp/ の部分は、みなさんのスクリーンショットを撮影したい任意のHPのURLを入れてください。

npx playwright codegen https://www.impl.co.jp/

すると、ChromiumというブラウザとPlaywright Inspectorというエディターのような画面が起動します。
動的な挙動の場合、何をすると(クリックやホバー)どんな実行結果になるのか、それをすべて明らかにしなければなりません。そのために、ここでどのようなスクリーンショットを撮影したいのか、コード化していきます。

Chromiumは、Playwrightの用ブラウザで、先ほどURLを記載したサイトが表示されています。(今回の場合では、弊社公式サイト)
例えば下記の画像の場合、左下の白い枠(locator 表示)は、「ここを操作したらコードを生成するよ」というPlaywright の機能です。

Playwright Inspectorは、操作ログが自動でコードになる場所 です。いま表示されているコードは、「impl.co.jp にアクセスした」という操作だけが記録された状態です。ここから操作するだけで コードが自動追加されます。

この状態(Playwright Inspector の 左上が Recordになっている状態)で、Chromiumのヘッダーのボタンをぽちぽちしてみましょう。すると、Playwright Inspectorのエディタに、コードが自動で追加されていきます。

await page~ 2行目からの部分が追加された部分で、”Company” をクリックしたということがここからわかるかと思います。

このクリックの動作が、コードをとして自動生成する機能で、「動的に操作した流れを、そのまま自動化するコード」が作られたということです。これをまるっとコピーして、下記のように、画面をキャプチャするプログラムをくっつけることで、動的動作に対してキャプチャが取れるようになっています。(今回はアニメーションの遅延も加味し、待機時間も追加)

import { test, expect } from '@playwright/test';

test('company page capture', async ({ page }) => {
  await page.goto('https://www.impl.co.jp/');  // TOPへ
  await page.locator('#header').getByRole('link', { name: 'Company' }).click();  // Companyへ移動

  await page.waitForTimeout(1200); // 1.2秒待つ(必要に応じて調整)  // ページのアニメーションや表示を待つ

  // スクリーンショット
  await page.screenshot({
    path: 'screenshots/hover.png',
    fullPage: true
  });
});

このファイルも、静的ページをキャプチャした時と同様に、tests/ フォルダに配置しましょう。ファイル名も注意してください。下記のコマンドで実行されます。

npx playwright test

すると、先ほどの静的キャプチャも再度実行されますが、tests/ 内にあるキャプチャのファイルが全て実行され、 hoverした際に表示されるヘッダーのメニューが出てきました!
これで、動的挙動についても問題なくキャプチャできたことがわかります。

② Node.js スクリプト

続けて、Node.jsから呼び出して画像解析できるようにしていきましょう。アプリなどに組み込む場合は、先ほども述べたように、こちらでやるのがいいです。

いきなりアプリに組み込むのも壊しそうで怖いので、まずはサンプルファイルを作って実験をしてみましょう。

実験環境を作る

まずは下記のようなファイル構成で、実験環境を作ってみます。

/playground/
  ├── capture.js
  ├── compare.js(任意)
  ├── package.json
  └── screenshots/

下記のコマンドで一気に作っちゃいましょう。

mkdir playground
cd playground
npm init -y
npm install playwright

Node.jsで動かす仕組みを作る

先ほどまでは、spec形式でtest runnerから実施をしてきましたが、今回はNode.jsからPlaywrightを直接叩く形式です。なので、何度も言っていますが、本番システムに組み込みやすい形式です。

簡単にですが、下記のようなコードをchatGPTに作ってもらいました。

const { chromium } = require('playwright');

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();

  await page.goto('https://www.impl.co.jp/');
  await page.waitForTimeout(1500); // 動的アニメーション待ち

  await page.screenshot({
    path: 'screenshots/test.png',
    fullPage: true
  });

  await browser.close();
})();

これを下記のコマンドで実行してみると、screenshots/test.png が生成されるのがわかるかと思います!

node capture.js

先ほどと違い、Node.jsから無事にスクリーンショットを撮ってくることができました。これで本番コードでも動く「Playwright単体モジュール」 が完成です!

ちょっとアレンジを加えてみる

せっかくなので、取得した画像をAIに解析してもらうこともしてみましょう。
簡単にGPTにプログラムを作ってみました。取得した画像をbase64としてGPTに画像を投げ、画像の内容を説明してもらうプログラムになっています。

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();

  await page.goto('https://www.impl.co.jp/');
  await page.waitForTimeout(1500);

  // キャプチャ
  const screenshotPath = 'screenshots/test.png';
  await page.screenshot({ path: screenshotPath, fullPage: true });

  // Playwright終了
  await browser.close();

  // 画像をbase64として読み込み
  const imageData = readFileSync(screenshotPath, { encoding: 'base64' });

  // AIに画像を投げる
  const result = await client.chat.completions.create({
    model: "gpt-4o-mini",
    messages: [
      {
        role: "user",
        content: [
          { type: "text", text: "この画像の内容を説明して。" },
          {
            type: "image_url",
            image_url: {
              url: `data:image/png;base64,${imageData}`
            }
          }
        ]
      }
    ]
  });

  console.log("AIの回答:", result.choices[0].message.content);
})();

これを実行させると、下記のような返答をしてくれました。弊社のサイトを分析してくれていますね笑。

AIの回答: この画像は、ウェブサイトのデザインまたはアプリケーションのインターフェースを示しています。主な内容は以下の通りです。

1. **技術革新**: テクノロジーを使って新しいことを実現するというメッセージが強調されています。

2. **セクション**: 「Strength」(強さ)や「Skill-Repo」(スキルリポジトリ)など、複数のセクションがあり、それぞれに説明が付いているようです。

3. **サービス内容**: モバイルアプリ、ウェブサービス、クラウドサービスなど、提供される具体的なサービスが列挙されています。

4. **連絡先情報**: おそらく、問い合わせのための連絡先情報(電話番号など)が含まれています。

5. **リクルート情報**: 求人情報や会社の情報も示されているようです。

全体的にモダンでシンプルなデザインが採用されており、情報が整理されている印象を受けます。

こんな感じで、他のプログラムともくっつけられるのが、Node.js でのメリットとなります。

おわりに

いかがだったでしょうか?
今回のプログラムはGitHubにもありますので、よければぜひご覧ください!

GitHub - iwasakiterukazuimpl/playwright-project
Contribute to iwasakiterukazuimpl/playwright-project development by creating an account on GitHub.

ご覧いただきありがとうございました。