UIテストの自動化!Node.jsとSeleniumでWebアプリのUIテスト環境構築

UIテストの自動化!Node.jsとSeleniumでWebアプリのUIテスト環境構築

こんにちは。ICS渡邊です。

Webアプリケーションを開発する際、みなさんはどのようにテストを行っていますでしょうか?

Webアプリケーションは、ユーザーごとに異なるブラウザを使用しており、ユーザー操作も必要となるため、手作業でテストをされている方も多いと思います。また、機能改修やバグフィクス後に、リグレッションテスト(改修により既存機能への影響がないかを確認する回帰テスト)が必要となりますが、時間が取れずしっかりとテストができていない方も多いのではないでしょうか?

本記事では、これらのテストを自動化することのできる「Selenium Webdriver」(セレニウム ウェブドライバー)についてご紹介します。

デモ

簡単な入力フォームのバリデーション機能をチェックするデモです。入力値に対して期待するエラー文言が表示されているかのテストを実施しています。

Selenium Webdriver とは

Seleniumは、Webアプリケーションのテストを自動化するオープンソースソフトウェアです。2011年に、Google開発していた「WebDriver」と統合し、「Selenium WebDriver」としてリリースされました。「Selenium WebDriver」の大きな特徴としては、複数言語対応とマルチブラウザ対応の2点が挙げられます。

複数言語対応

様々な言語でSeleniumのテストコードを作成することができます。現在(2015年3月)時点では以下の言語に対応しているため幅広いユーザーに使いやすくなっています。

  • Java
  • C#
  • Python
  • Ruby
  • PHP
  • Perl
  • JavaScript(Node.js)

マルチブラウザ対応

現在(2015年3月)時点では以下のブラウザに対応しています。PCのブラウザだけでなく、iPhoneやAndroidのモバイルブラウザにも対応しております。また、Appium(Selenium for Application)というツールを使えば、Webブラウザのテストだけでなく、モバイルアプリのテストも行うことができます。

  • Chrome
  • FireFox
  • InternetExplorer
  • Opera
  • iOS Safari
  • Android標準ブラウザ

Selenium Webdriverで出来ること

Selenium Webdriver は、ユーザー操作で出来ることは殆ど実行することができます。クリックやスクロール・文字入力などはもちろん、ウィンドウサイズの調整やCookieやセッション情報の書き換えも可能です。

また、スクリーンショットを撮ることもできるため、レスポンシブレイアウト等の表示確認やテスト実施時のテストエビデンス(*1)として画面を残しておくことができるため、テストの用途だけでなく、自動化ツールとしても使用することができます。

Selenium Webdriver は、Webサイトの管理画面やユーザーのマイページ、SinglePageApplication(SPA)などのテストに特に向いていると思います。

*1 テストエビデンスとは、テスト実施の記録(証拠)となるもので、テストを実施時のスクリーンショットなどが使われます。

環境構築の手順

JavaScript(Node.js)を使ってChromeブラウザでテストを実施するテストコードを作成していきたいと思います。

まずNode.jsをインストールします。Node.jsは公式サイトのインストーラーを使って手順に従ってインストールしていきます。インストール後コマンドラインでnode -vと実行し、Nodeのバージョンが表示されていればインストール成功です。

1. selenium-webdriver のインストール

コマンドラインを立ち上げ、以下のコマンドを実行してselenium-webdriverをインストールします。

npm -g install selenium-webdriver

※Macでエラーが出る場合は、管理者権限(sudo)で試してみてください。

2. ライブラリのインストール

本記事ではテスティングフレームワークとしてMochaを、アサーションライブラリとしてExpect.jsを使ってテストコードを作成していきます。
コマンドラインを立ち上げ、以下のコマンドを実行してインストールします。

npm -g install mocha
npm -g install expect.js

※Macでエラーが出る場合は、管理者権限(sudo)で試してみてください。

3. Selenium Server のダウンロード

下記のURLのよりSeleniumServerをダウンロードし、任意のフォルダに設置してください。
http://www.seleniumhq.org/download/

4. Seleinum Google Chrome Driver のダウンロード

下記のURLより最新バージョンのDriverを取得し、ダウンロードしてきてください。(2015年3月時点の最新は2.14)
ダウンロードしたZipファイルを解凍すると、実行ファイルが出てきますので、任意の場所に設置します。

http://chromedriver.storage.googleapis.com/index.html

テストコードの作成

テストコードとして次のJavaScriptを記述したファイル「formTest.js」を作成しましょう。

var webdriver = require('selenium-webdriver');
var t = require('selenium-webdriver/testing');
var expect = require('expect.js');
var driver;
var assert = require('assert');
var By = webdriver.By;

t.describe('入力フォーム デモ', function() {
    t.before(function() {
        driver = new webdriver.Builder().
        usingServer('http://localhost:4444/wd/hub').
        withCapabilities(webdriver.Capabilities.chrome()).
        build();
    });

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

    t.it('名前欄の必須入力チェック その1', function() {
        driver.get('http://ics-drive.jp/sandbox/demo/demo.html').then(function() {
            // 何も入力せずにSubmitする
            driver.findElement(By.id('sampleForm')).submit();

            // エラーメッセージを取得して、文言が正しいかチェックする
            driver.wait(driver.findElement(By.id('error_name')).getText(), 1000)
            .then(function(text) {
                expect(text).to.be('名前を入力してください。');
            });
        });
    });

    t.it('名前欄の必須入力チェック その2', function() {
        driver.get('http://ics-drive.jp/sandbox/demo/demo.html').then(function() {
            // 名前を入力してSubmitする
            driver.findElement(By.id('name')).sendKeys('品川太郎');
            driver.findElement(By.id('sampleForm')).submit();

            // エラーメッセージを取得して、文言が空であるか確認する
            driver.wait(driver.findElement(By.id('error_name')).getText(), 1000)
            .then(function(text) {
                expect(text).to.be('');
            });
        });
    });

});

9行目の「t.before」と16行目の「t.after」はそれぞれテスト前・後に実行される処理を記述します。上記のコードでは、テスト実施前にchromeWebDriverを起動し、テスト実施後に終了する処理を記述しています。

実際のテスト処理は、20行目と33行目の「t.it」にそれぞれ記述しています。「driver.findElement」はHTMLのDOMにアクセスできるメソッドで、「By.id」を使ってDOMの中から指定したIDの要素を取得しています。「By.id」の他にも「By.name」「By.css」「By.tagName」などが用意されており、それぞれname属性、cssのクラス、タグなどを指定して要素を取得することができます。

20行目と42行目に記述されている「expect(xx).to.be(”);」が、テスト処理内で行なわれるAssertionの処理になります。Assertionとは、期待しているものと合致しているかを検証するコマンドで、上記のコードでは取得したエラーコードの文言が正しいかを検証している処理になります。

テストコードの実行

  1. テストを開始する前に Selenium Server を起動します。先程ダウンロードしたファイルを配置したディレクトリに移動し、以下のコマンドを実行します。
    java -jar selenium-server-standalone-2.44.0.jar -Dwebdriver.chrome.driver=chromedriver
    
  2. Selenium Server が起動したら、以下のコマンドを入力し、作成したテストコードを実行します。デフォルトのタイムアウト設定の場合、通信環境によってはタイムアウトになってしまう可能性があるため、実行時のオプション設定でタイムアウトの時間を10000msに変更しておきます。
    mocha tests/formTest.js --timeout 10000
    
  3. コマンドを実行するとテスト結果がコンソールに表示されます。緑のチェックが入っているものは「テストOK」、赤字になっているものは「テストNG」となります。「テストNG」のものはテスト結果の下に詳細が表示されます。下記の例では、期待値となるエラー文言と実際のエラー文言の内容が違うためエラーとなっていることがわかります。
    SeleniumTestResult

おわりに

慣れるまではテストコードを作るのに時間がかかり、手動でテストした方が早いのではと思うかもしれません。しかし、規模が大きくなればなるほど、手動でのテスト工数は膨大な時間になり、自動化するメリットが出てくると思います。また、一度テストコードを作成しておけば、機能改修や運用でのバグフィクス時にリグレッションテストを簡単に行うことができるため、プロジェクト全体を通して見ると、自動化するメリットがあるかと思います。

もちろんプロジェクトの規模やテストの内容により自動化する必要のないものもあると思います。みなさまもご自身のプロジェクトのテスト手法を一度見直してみてはいかがでしょうか?

渡邊 真耶

インタラクティブデベロッパー。Web制作会社でサーバサイドやフロントエンドの制作に携わり、現在は株式会社ICSでFlashコンテンツの制作を担当。