主夫ときどきプログラマ

データベース、Webエンジニアリング、コミュニティ、etc

YUITest を使ってJavascriptの単体テストを自動化するまで (前編)

Javascriptのテストフレームワークにはいくつも種類があるが、そのなかでYUIのTestライブラリの使い方を紹介する。YUITestでテストを書くことで、それの実行から自動化までを用意に実現することができる。その一連の方法を紹介する。

テストを書く

まず大事なのはテストを書くこと。今回はサンプルとしてとてもシンプルな関数を用意する。シンプルすぎる。


target.js

/**
 * 引数を足しあわせて結果を返す
 *
 * @param {Number} operand1
 * @param {Number} operand2
 * @return {Number} sum of args
 */
var sum = function(op1, op2) {
     return op1 + op2;
}


この関数をテストしていこう。テストファーストという言葉もあるが、それは空の彼方へ置いておけばいい。いまのところは。
テストはこんなかんじになるだろう。


test.js

YUI({ loadInclude: {TestRunner: true}}).use('test', function (Y) {

     var testCase = new Y.Test.Case({

          name : 'sum() のテスト',

          setUp : function() {
          },

          tearDown : function() {
          },

          'test normal' : function() {
               Y.Assert.areSame(10, sum(2, 8), '合計は10');
          },

          testNull : function() {
               Y.Assert.isNull(sum(null, 1), '不正な引数の場合はNullが返る');
          }
     });

     // load TestCase
     Y.Test.Runner.add(testCase);
});

いきなりよくわからないキーワードが出てきてしまった。YUI? なんだそれは。まだそれはわからなくていい。大事なのは

  • testXXX という名前のメソッドを用意すれば、それがテストとして実行されること
  • ’空白を含む 名前' というメソッドもテストとして実行されること
  • Y.Assert.XXXX というAssertionsがあること
  • setUp, tearDown はよくあるはなし

だろう。

テストを実行する

さぁ、さっそくテストを実行しよう。実行するためのHTMLを用意してブラウザで読みこめばテストが実行される。

testRunner.html

<html>
    <head>
         <meta http-equiv="content-type" content="text/html; charset=utf-8">
    </head>
    <body>
        <div id='log' class='yui3-skin-sam'></div>
        <script src="http://yui.yahooapis.com/3.16.0/build/yui/yui-min.js"></script>
        <script type='text/javascript'>

            // コンソール表示の設定を先にロードする
            YUI({ loadInclude: {TestRunner: true}}).use('test', 'test-console', function (Y) {
                // out puts Console
                (new Y.Test.Console({
                    newestOnTop : false,
                    filters : { pass : true, fail : true, info : true, status : true }
                })).render('#log');

                Y.Test.Runner.setName('単体テスト');
            });
        </script>

        <!-- テスト対象をロード -->
        <script src="target.js"></script>

        <!-- テストをロード -->
        <script src="test.js"></script>

        <script type='text/javascript'>
            YUI({ loadInclude: {TestRunner: true}}).use('test', 'test-console', function (Y) {
                // テスト実行
                Y.Test.Runner.run();
            });
        </script>
    </body>
</html>

YUIのライブラリをサイトから直接ロードして実行する。テスト結果を表示するコンソールは<div id=‘log’></div>に出力されるので必ず用意しよう。コンソール、テスト対象、テスト、の順にロードして最後にテストを実行だ。これをブラウザでロードしよう。


Very Good!!

見事に結果が表示されている。たった3行のコードにだってエラーがあるんだから、君が書いているコードにだってかならずエラーが潜んでいる。テストをどんどん書いてバグをどんどん潰していくんだ!まず手始めに testNull のエラーを取り除いてみよう。


より詳しい使い方は下記を参照しよう。
YUITest
http://yuilibrary.com/yui/docs/test/
コンソール
http://yuilibrary.com/yui/docs/test-console/
Assertion
http://yuilibrary.com/yui/docs/api/ Assertを検索

コマンドラインからのテスト実行

ブラウザからテストを実行することはできたが、これは少々面倒な作業だ。なにより自動化することがとても困難だ。テストを迅速に実行しそれを自動化するにはコマンドラインからテストを実行する必要があるのだ。

PhantomJS + grover


PhantomJSはコマンドから利用できるブラウザで、これを使うことでテストを実行することができる。合わせて grover というYUITest専用のPhantomJSラッパーツールを組み合わせることで簡単にコマンドラインからテストを実行出来るようなる。
それぞれは簡単にインストールすることができる

$ brew install phantomjs
$ npm install -g grover


OSがMacじゃない君は自力でインストール方法を調べてくれ。もしくはここで立ち去っても構わない。Macだけど実行できない君はHomebrew をインストールして出直して来い。
さぁPhantomJSとgroverのインストールが終わったらテストを実行しよう

$ grover testRunner.html



Fantastic!!

これでいつでも迅速にテストを実行出来るようになった。


カバレッジの測定

次はカバレッジを測定しよう。カバレッジを測定するにはテスト対象のtarget.jsを変換する必要がある。変換にはYUITestで提供されているjarを使う。https://github.com/yui/yuitest ここから java/build/yuitest-coverage.jar をダウンロードして早速変換だ。

$ java -jar yuitest-coverage.jar -o target-coveraged.js target.js


testRunner.html のテスト対象を target-coveraged.js に変えて実行すればカバレッジを測定できる。テストにエラーがあるとカバレッジを測定できないから先のエラーは直しておこう。

$ grover ―coverage testRunner.html


Terrific!!

いちいちファイルを変換するのは面倒だから一連の処理を1つのタスクとしてまとめてしまおう。


task.sh

#!/bin/sh
java -jar yuitest-coverage.jar -o target-coveraged.js target.js
grover --coverage testRunner.html


さぁこれで準備は整った。あとはこれを自動化していこう。



後編へ続く YUITest を使ってJavascriptの単体テストを自動化するまで (後編) - masayuki14 note