LoginSignup
4
0

More than 1 year has passed since last update.

PuppeteerでUIテストを試してみた

Posted at

はじめに

PuppeteerというAPIを利用して画面操作のテストを行うサンプルを作成したことを備忘として残します。
今回はローカルサーバーの掛け算を行う画面にアクセスし、値の入力と計算結果の検証までを自動化するテストコードを作成しました。
(本来のやりたかったことはSPAの画面操作を自動化することでしたが、簡単に動きを確認するために作成しました)

Puppeteerとは

Googleで開発されて、DevToolsプロトコルを介してChromiumやChromeを制御するための高レベルなAPIを提供するNodeライブラリ
とのこと。
Google Chromeのヘッドレスブラウザ(GUIを必要としないブラウザ)機能であるヘッドレスChromeを操作するものがこのPuppeteerになります。
GitHubのスター数は8万以上, 最新バージョンは13日前(本記事執筆時点)と今後も盛り上がりを見せそうなライブラリです。
Puppeteerが登場する以前はPhantomJSがヘッドレスブラウザの主流だったようです。

実行環境

バージョン
node v18.12.1
npm v8.19.2
puppeteer v19.2.2
http-server v14.1.1

手順

最終的なディレクトリ構成

puppeteer-sample
├── node_modules
|       ︙
|
├── package-lock.json
├── package.json
└── test.js

1. セットアップ

mkdir puppeteer-sample
cd puppeteer
npm init
npm install puppeteer
︙
npm install http-server
︙

2. テスト対象のページ作成

テスト対象ページ
index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Puppeteer UI Test</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
</head>
<body>
<section class="section">
    <div class="container">
        <h1 class="title">
            Puppeteer Test Form
        </h1>
        <div class="field">
            <label class="label">かける数</label>
            <div class="control">
                <input id="first" class="input" type="number">
            </div>
        </div>
        <div class="field">
            <label class="label">かけられる数</label>
            <div class="control">
                <input id="second" class="input" type="number">
            </div>
        </div>
        <div class="field is-grouped">
            <div class="control">
                <button class="button is-link" onclick="multiply()">計算する</button>
            </div>
        </div>
        <div class="field">
            <label class="label" id="out">掛け算の答え:</label>
        </div>
    </div>
</section>
<script>
    function multiply() {
        const first = document.querySelector('#first');
        const second = document.querySelector('#second');
        const out = document.querySelector('#out');

        const first_num = parseFloat(first.value);
        const second_num = parseFloat(second.value);

        const result = first_num * second_num;
        out.innerHTML = result;
    }
</script>
</body>
</html>

テスト対象の画面

かける数, かけられる数の入力後、「計算する」ボタンをクリックしてJS関数を実行。
画面に挿入された結果の検証を行います。
スクリーンショット 2022-11-16 18.05.56.png

3. テストコードを作成

テストコード
test.js
const assert = require('assert')
const puppeteer = require('puppeteer')

if (require.main === module) {
    main()
}

async function main () {
    try {

        const browser = await puppeteer.launch({
            headless: false, // falseにするとGUI表示して動作確認できるようになる
        })

        try {
            const page = await browser.newPage();       // 新規タブを開く

            await Promise.all([
                page.waitForNavigation({timeout: 1000}),
                page.goto('http://localhost:8080/'),    // localhost:8080にアクセス
            ]);

            await page.type('#first', '100');           // 値を入力する
            await page.type('#second', '50');
            await page.click('button.button.is-link');  // 「計算する」ボタンをクリックする

            // 要素内テキストを取得
            const actual = await page.$eval('#out', el => el.innerHTML);
            const expected = '5000';                    // 期待値

            console.info({actual, expected});
            assert.strictEqual(actual, expected);       // 乗算結果の検証
            await page.screenshot({path: 'example.png'}); // ページのスクリーンショットを撮る

            await new Promise(resolve => setTimeout(resolve, 1000));
        } finally {
            await browser.close() // タブを閉じる
        }
    } catch (err) {
        console.error(err)
    }
}

4. テスト実施

ローカルサーバーを立ち上げる

npx http-server

テスト実行

node test

テスト合格の場合は以下のように

{ actual: '5000', expected: '5000' }

不合格の場合は以下のように出力されます(期待値を変更してテスト実行)

{ actual: '5000', expected: '5001' }
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:

'5000' !== '5001'

    at main (/Users/xxx/puppeteer-sample/test.js:31:20)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
  generatedMessage: true,
  code: 'ERR_ASSERTION',
  actual: '5000',
  expected: '5001',
  operator: 'strictEqual'
}

参考

4
0
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
0