今回は、テストの自動化についてお話させて頂きます。

規模等にもよるかと思いますが、全部の自動化は無理でもコア部分の確認を自動化することで、担当者の負荷を下げる効果はあると思います。

実作業で必要なものとして、環境構築、サンプルコードを紹介したいと思います。

本記事で使用するもの

本記事で使用するものは、以下の通りです。

  • node
  • seleniumu
  • mocha
  • chromedriver

nodeを選んだ理由

linux、mac、windowsで利用する事ができるため実行環境を用意しやすい。
実行環境もコマンド一つで出来る等、他の方に展開するもの楽です。
また、javascriptで作成できるため、web技術者であれば大体の方はご理解頂ける言語かと思われます。

事前準備

プロジェクト作成

CIで、作業ディレクトリに移動し、以下のコマンドを実行する。

npm init -y

各種モジュールのインストール

seleniumuとmochaをインストールするため、以下のコマンドを実行

npm i selenium-webdriver mocha

ソースコード例(EC-CUBE4系のデフォルト環境を想定)

const fs = require('fs');
const { promisify } = require('util');
const webdriver = require('selenium-webdriver');
const { Builder, By, until } = webdriver;
const assert = require("assert");

const capabilities = webdriver.Capabilities.chrome();
capabilities.set('chromeOptions', {
    args: [
        '--headless',
        '--no-sandbox',
        '--disable-gpu',
        `--window-size=1200,1024`
    ]
});

const ec_cube_url = 'http://192.168.56.106/eccube-4.0.3/';

const unit_test_ss_save_path = 'ss/';

describe("EC-CUBEテスト自動化", () => {
    let driver;

    before(() => {
        // ブラウザ立ち上げ
        driver = new Builder().withCapabilities(capabilities).build();
        process.on("unhandledRejection", console.dir);
    });

    after(() => {
        return driver.quit();
    });
 
    it("TOPページ確認", async () => {
        // TOPへ移動
        await driver.get(ec_cube_url);

        // 検索アイコンが表示されるまで待つ
        await driver.wait(until.elementLocated(By.className('ec-headerSearch__keywordBtn')), 10000);

        // 表示されたページを画像保存する
        await screenshotSave(driver, 'top.jpg');
    });

    it("商品一覧確認", async () => {
        // TOPへ移動
        await driver.get(ec_cube_url);

        // 検索アイコンが表示されるまで待つ
        await driver.wait(until.elementLocated(By.className('ec-headerSearch__keywordBtn')), 10000);

        // 検索アイコンをクリック
        await driver.findElement(By.className('ec-headerSearch__keywordBtn')).click();
        
        // 商品一覧が表示されるまでまつ
        await driver.wait(until.elementLocated(By.className('ec-topicpath__item')), 10000);

        // 商品一覧のURLを確認し遷移できているか判定
        assert.strictEqual(await driver.getCurrentUrl(), ec_cube_url + 'products/list?category_id=&name=');

        // 表示されたページを画像保存する
        await screenshotSave(driver, 'products_list.jpg');
    });

    it("カート画面確認", async () => {
        // TOPへ移動
        await driver.get(ec_cube_url);

        // 検索アイコンが表示されるまで待つ
        await driver.wait(until.elementLocated(By.className('ec-headerSearch__keywordBtn')), 10000);

        // 検索アイコンをクリック
        await driver.findElement(By.className('ec-headerSearch__keywordBtn')).click();
        
        // 商品一覧が表示されるまでまつ
        await driver.wait(until.elementLocated(By.className('ec-topicpath__item')), 10000);

        // カートに入れるボタンを押下
        await driver.findElement(By.className('add-cart')).click();

        // カートに進むボタンを押下
        await driver.wait(until.elementLocated(By.className('ec-inlineBtn--action')), 10000);
        await driver.findElement(By.className('ec-inlineBtn--action')).click();

        // カートのURLを確認し遷移できているか判定
        assert.strictEqual(await driver.getCurrentUrl(), ec_cube_url + 'cart');

        // 表示されたページを画像保存する
        await screenshotSave(driver, 'cart.jpg');
    });


});

async function screenshotSave(driver, fileName) {
    let base64 = await driver.takeScreenshot();
    let buffer = Buffer.from(base64, 'base64');
    // bufferを保存
    await promisify(fs.writeFile)(unit_test_ss_save_path + fileName, buffer);
}

実行方法

「package.json」の「scripts」を以下のように登録します。

"scripts": {
    "test": "mocha unitTest/*.js --timeout 10000"
  }

scripts登録後、CIで以下のコマンドを実行

npm test

実際のコンソールログ

> mocha unitTest/*.js --timeout 10000

EC-CUBEテスト自動化

DevTools listening on ws://127.0.0.1:63901/devtools/browser/da8d4c24-957c-4b9b-b1de-ac29bffd9cd8
√ TOPページ確認 (4836ms)
√ 商品一覧確認 (1010ms)
√ カート画面確認 (1504ms)

3 passing (7s)

正常に処理されますと、それぞれの実行結果が表示されます。「√」は正常終了となります。

ソースコード解説

mochaの詳しい内容については公式https://mochajs.org/を参照ください。

1.前処理、後処理について

mochaのフックとなりますが、テスト実行前(before)、テスト実行後(after)に、処理を記述することが出来ます。
今回は、テスト実行前に、ブラウザを立ち上げ、テスト実行後に生成したブラウザのウィンドウを全て閉じるを記述しています。

before(() => {
        // ブラウザ立ち上げ
        driver = new Builder().withCapabilities(capabilities).build();
        process.on("unhandledRejection", console.dir);
    });

    after(() => {
        return driver.quit();
    });

2.指定したURLへの移動

webdriverの「get」メソッドにURLを渡し、遷移させます。
コード例:

 await driver.get(URL);

3.指定したものが来るまで待機

ページ遷移または、何かしらアクションした後、ページが更新されるまで待機させます。
その際、特定の要素を指定することで、上手くいくことが多いです。

コード例:

await driver.wait(until.elementLocated(By.className('ec-headerSearch__keywordBtn')), 10000);

例では、DOMのクラス名を指定してますが、id、name、xpath等も使用できます。

4.DOM操作

検索ボタンを押下するといった操作もできます。
例では、EC-CUBEのTOP画面に表示されている検索ボタンを押下するコードとなります。

コード例:

await driver.findElement(By.className('ec-headerSearch__keywordBtn')).click();

例では、DOMのクラス名を指定してますが、上記の「3.」と同様、id、name、xpath等も使用できます。

5.判定

ページ遷移が上手くいったかどうか、判断要素は多々あるかと思いますが、例では、urlで判定しました。

コード例:

assert.strictEqual(await driver.getCurrentUrl(), ec_cube_url + 'products/list?category_id=&name=');

assertで失敗した場合、不一致の内容がコンソールに出力されます。
assertには、様々なメソッドがあります、詳細は以下の公式サイトを参照ください。
https://nodejs.org/api/assert.html

上記の遷移、要素の待機、操作、判定、これらを組み合わせることで
様々な操作を自動で処理し、判定することが可能となります。

毎回同じ操作するの大変…という方は自動化に挑戦されてみてはいかがでしょうか!