2019.04.30

BrowserStackとSeleniumを使って自動ブラウザテストをしてみた


最近、私の関わっている案件で、ブラウザテストを自動化しようという話が出てきました。

それで色々と調べてみたところ、どうやらSeleniumを使った自動テストをBrowserStack上で動かすのが良さそうだ、ということになったので、実際にサンプルコードを書いて、どんなものか検証してみました。

この記事では、そこで得られた知見を共有したいと思います。

ツールの紹介

はじめに、今回の記事の主役である、SeleniumとBrowserStackについて紹介します🎉

Selenium

Selenium-logo

Seleniumは、ブラウザの操作を自動化するツールです。

従来のブラウザテストでは、同じような操作(例えば、「フォームを記入して送信ボタンを押す」というような操作)を何度も人の手で行わなければなりませんでした。なかなかつらい作業ですよね😅

Seleniumはこれらの作業を全て自動で行ってくれます!
もちろんテストコードを書く必要はありますが、クロスブラウザテストや回帰テストなどで同じテストを繰り返し実施する労力は、かなり削減できるのではないでしょうか。

Seleniumは、ChromeやSafari、IE、FireFox、Operaなど、主要なブラウザを操作することができます。また、JavaやC#、Python、Ruby、JavaScriptなど、様々な言語に対応しています。

今回のサンプルではJavaScript(Node.js)でコードを書いていきます。
また、Selenium自体はあくまでブラウザ操作のためのツールであり、テスト機能は持ち合わせていません。 テストを書くにあたって、今回は、JavaScriptのテストフレームワークであるMochaを併用します。

BrowserStack

BrowserStack-logo

BrowserStackは、様々なブラウザ環境を提供してくれるクラウドサービスです。

ブラウザテストを実施するにあたって意外と手間がかかるのが、ブラウザ環境の用意ではないでしょうか。
Safariでの動作を確認するためにMacを用意したり、IEでの確認のためにWindows機を用意したりと、結構、大変です。しかもIEの場合、一つのマシンに一つのバージョンしか入れられないため、IE9、10、11をテストしようとしたら、PCなりVMなりを3つ用意しなければならなかったりします😥

このような課題を解決してくれるのがBrowserStackです!
BrowserStackは2000以上のデバイスとブラウザをクラウド上で提供しており、ユーザーはそれらの環境を自由に利用することができます(提供されているOSとブラウザの一覧はこちら)。

しかもそれだけではなく、テスト中の画面のスクリーンショットや動画を自動で撮ってくれたりといった、便利な機能もついています。また今回は扱いませんが、自動テストだけでなく、手動でのテストにも対応しています。

このように至れり尽くせりなサービスなのですが・・・有料です😅
自動テストプランの場合、1か月1ユーザーにつき、129ドルかかります(年額購入の場合。詳しくはこちら)。

今回のデモでは無料トライアルプランを利用します。無料でも100分の自動テストと100枚のスクリーンショットが取れますので、ちょっと試してみる分には十分でしょう。

デモ概要

それではさっそくデモに移りましょう。
今回のデモでは、こちらのフォーム画面のIE11動作テストを自動化します。

以下、

  • BrowserStackへのユーザー登録
  • テストコード作成
  • テスト実施

の順で説明していきます😉

BrowserStackユーザー登録

テストコードを書く前に、BrowserStackのユーザー登録を行っておきます。
BrowserStackトップ画面Get started freeもしくはFREE TRIALボタンからアカウント登録ができます。

ログインすると、下のようなダッシュボード画面が表示されます(表示されない場合はメニューのProductsからAutomateを選択してみてください)。

BSdashboard

テストのログやスクリーンショット、動画はこのダッシュボード画面から確認することができます。

テストコード作成

テストコードを書いていきます。
上でも述べたように、今回はSeleniumと合わせて、テストフレームワークのMocahを使用し、JavaScript(Node.js)でコードを書いていきます。Node.jsがない方はインストールしておきましょう。

ディレクトリの作成

まず適当な場所にテストコードを格納するディレクトリ(今回のデモではdemo-test)を作成します。
ディレクトリ構造は任意ですが、今回のデモでは以下のようにします。

demo-test/
      ├ conf/  BrowserStackを使うための設定ファイルを格納
      └ test/  テストコードを格納

demo-testに移動し、npm init -yコマンドを実行します。

cd /Users/MyName/Project/demo-test
npm init -y

このコマンドを実行することで、ディレクトリ内にプロジェクトの情報等が記されたpackage.jsonファイルが作成されます。

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

SeleniumとMochaを使用するために、以下のコマンドでインストールします。

npm i -D selenium-webdriver mocha

package.jsonを確認して、次のような行が追記されていればOKです!

package.json
"devDependencies": {
  "mocha": "^6.1.4",
  "selenium-webdriver": "^4.0.0-alpha.1"
}

テストコードファイルの作成

testディレクトリにテストコード本体であるform-test.jsを、confディレクトリにBrowserStackを使用するのに必要な情報をまとめたtest.conf.jsをそれぞれ作成します。

以下、test.conf.jsform-test.jsの順で見ていきます。

test.conf.js

test.conf.js
require('dotenv').config();

exports.capabilities = {
    'browserstack.user': process.env.BROWSERSTACK_USERNAME || 'USERNAME',
    'browserstack.key': process.env.BROWSERSTACK_ACCESS_KEY || 'ACCESS_KEY',
    'build': 'mocha-browserstack',
    'name': 'form_test',
    'browserstack.debug': 'true',
  
    'browserName': 'internet explorer',
    'version': '11',
    'platform': 'WINDOWS'
  
  };

このファイルには、BrowserStackのユーザー名やアクセスキー、テストするOSやブラウザの種類といった、BrowserStack上でテストを動かすのに必要な情報が書かれています。

capabilitiesオブジェクトの下三行に注目してください。

test.conf.js
'browserName': 'internet explorer',
'version': '11',
'platform': 'WINDOWS'

ここでテストに使うブラウザとそのバージョン、OSを指定します。
他のブラウザでテストしたいときはここを変えればいいんですね。

続いて上二行に注目してください。

test.conf.js
'browserstack.user': process.env.BROWSERSTACK_USERNAME || 'USERNAME',
'browserstack.key': process.env.BROWSERSTACK_ACCESS_KEY || 'ACCESS_KEY',

ここにBrowserStackにアクセスするために必要なユーザー名とアクセスキーを記入します。
ユーザー名およびアクセスキーは、BrowserStackのダッシュボード画面左のUsername and Access Keysをクリックすると表示されます。

ここで一点、注意事項があります。
ユーザー名とアクセスキーの値をそのまま張り付けてしまっても動くのですが、こうしたセキュリティ上重要な情報をコードに書いてしまうのはちょっと心配です。
ローカルでコードを管理する分にはいいのですが、GitHub等で管理する場合、アクセスキーなどの情報がそのままネット上に公開されてしまいます。

これらの情報は環境変数として.envファイルにまとめて、gitの管理からも外してしまうのがよいでしょう。

.envファイルを作成するために、dotenvというモジュールをインストールします。

npm i dotenv

test.conf.jsの1行目でdotenvを読み込みます。

test.conf.js
require('dotenv').config();

demo-test直下に.envファイルを作成します。中身は以下のようにしてください。

.env
BROWSERSTACK_USERNAME=ユーザー名
BROWSERSTACK_ACCESS_KEY=アクセスキー

.gitignoreファイルに.envを追記します。

.gitignore
.env

これでユーザー名とアクセスキーを安全に使用することができます😊

以上、テストに使うブラウザ・OSの設定と、ユーザー名・アクセスキーの設定を行いました。
他のプロパティについては、公式ドキュメントを参照してみてください。

form-test.js

form-test.js
const { Builder, By } = require("selenium-webdriver");
const assert = require("assert");
const conf_file = 'conf/test.conf.js';
const caps = require('../' + conf_file).capabilities;

let driver;

describe("入力フォーム デモ", function() {
  before(function() {
    driver = new Builder()
      .usingServer('https://hub-cloud.browserstack.com/wd/hub')
      .withCapabilities(caps)
      .build();
    process.on("unhandledRejection", console.dir);
  });

  after(function() {
    return driver.quit();
  });

  it("コメントの必須入力チェック その1", async function() {
    // テスト対象のページへアクセス
    await driver.get(
      "http://glacial-dusk-36576.herokuapp.com/"
    );

    // 名前だけ入力してSubmitする
    await driver.findElement(By.name("name")).sendKeys("キャンディ太郎");
    await driver.findElement(By.id("submit-button")).click();

    // エラーメッセージを取得して、文言が正しいかチェックする
    const errorMsg = await driver
      .findElement(By.className("error-message"))
      .getText();

    assert.equal(errorMsg, "コメントを入力してください。");
  });

  it("コメントの必須入力チェック その2", async function() {
    // テスト対象のページへアクセス
    await driver.get(
      "http://glacial-dusk-36576.herokuapp.com/"
    );

    // 名前とコメントを入力してSubmitする
    await driver.findElement(By.name("name")).sendKeys("キャンディ太郎");
    await driver.findElement(By.name("comment")).sendKeys("こんにちは");
    await driver.findElement(By.id("submit-button")).click();

    // 成功メッセージを取得して、文言が正しいかチェックする
    const successMsg = await driver
      .findElement(By.className("success-message"))
      .getText();

    assert.equal(successMsg, "コメントを送信しました。");
  });
});

こちらがテストコード本体になります。上から順に見ていきましょう。

まず最初の4行で必要なモジュールを読み込んでいます。

form-test.js
const { Builder, By } = require("selenium-webdriver");
const assert = require("assert");
const conf_file = 'conf/test.conf.js';
const caps = require('../' + conf_file).capabilities;

2行目でrequire("assert")していますが、実はMochaにはアサーション機能がついていないため、ここでNode.jsのassertモジュールを読み込んでいます。
3、4行目では先ほど作成したtest.conf.jsを読み込んでいます。

Mochaの仕様で、テストはdescribeメソッドの中に書きます。
個々のテストはitの中に書いていきます。テスト実施前に行う処理はbefore、すべてのテストが終わった後の処理はafterの中に書きます。

form-test.js
before(function() {
  driver = new Builder()
    .usingServer('https://hub-cloud.browserstack.com/wd/hub')
    .withCapabilities(caps)
    .build();
  process.on("unhandledRejection", console.dir);
});

まず、beforeメソッド内で、capsの情報をもとにウェブドライバーを作成しています。

この後、二つのitテストが実行され、最後にafterメソッド内でブラウザを閉じ、テストを終了します。

form-test.js
after(function() {
  return driver.quit();
});

itテストの中身を見ていきましょう。

form-test.js
it("コメントの必須入力チェック その1", async function() {
  // テスト対象のページへアクセス
  await driver.get(
    "http://glacial-dusk-36576.herokuapp.com/"
  );

  // 名前だけ入力してSubmitする
  await driver.findElement(By.name("name")).sendKeys("キャンディ太郎");
  await driver.findElement(By.id("submit-button")).click();

  // エラーメッセージを取得して、文言が正しいかチェックする
  const errorMsg = await driver
    .findElement(By.className("error-message"))
    .getText();

  assert.equal(errorMsg, "コメントを入力してください。");
});

コードとコメントを見れば、大体の流れは把握できると思います😅
driver以下の部分がSeleniumが提供しているメソッドですね。

.findElement(By)でHTMLの要素を取得します。By以下は、idやname属性値、CSSクラス名等を指定することができます。
さらに.sendKeys.clickといったメソッドをチェーンすることができます。

最後にassert.equalで、出てきたエラーメッセージと第二引数の文字列が等しいかどうか判定しています。

以上が、今回のデモで使用するテストコードになります。

テスト実施

いよいよテストを実施します!

コマンドの設定

コマンドラインからテストを実行できるように、package.jsonscriptsに以下のように追記します。

package.json
"scripts": {
  "test:form": "mocha test/form-test.js --no-timeout"
}

コマンドラインでform-testコマンドを打つと、mochaを使ってtest\form-test.jsに書かれたテストが実行されます。
--timeout 10000のようにして、タイムアウト時間(ミリ秒)を設定することもできますが、今回はタイムアウト無しで実行します。

それではテストを走らせましょう。
以下のコマンドを実行してください。

npm run test:form

テストが実行されました!🥳
コマンドラインにテスト結果が表示されていることと思います。

result

BrowserStackで確認

BrowserStackのダッシュボード画面に行ってみましょう。

BSresult1

先ほど実施したテストが表示されています。テスト名をクリックします。

BSresult2

テスト実行結果の詳細が表示されます。テスト実行時の動画も撮られていますね。

BSresult3

ログもきちんと取れています。

BSresult4

操作ごとのスクリーンショットも撮られています。画像と動画はもちろんダウンロードできます。

とまあこんな感じです😁

自動でスクショを撮ってくれるのでエビデンス作成の手間が省けますし、動画を見ればどこでテストがつまづいたか簡単に確認できますね!

まとめ

以上、SeleniumとBrowserStackを使って、ブラウザテストを自動化してみました。

正直、これくらいのテストであれば手でやった方が早いのですが😅、今後、どんどんテストが増え、また繰り返し実行しなければならない状況になった時にはやはり、こうした自動化ツールが頼りになるのだと思います。

この記事を読んで、ちょっとでも「ブラウザテスト自動化してみようかな」と思っていただけたら幸いです😊

これからも一緒に勉強していきましょう!

参考

今回、テストコードを書くにあたって、以下のページを参考にしました。

Node.jsとSeleniumでWebアプリのUIテストを自動化(2018年版)
Selenium examples for Mocha and BrowserStack Automate


<!-- Font Awesome Free 5.0.13 by @fontawesome - https://fontawesome.com --><!-- License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) -->