Angular JSを使おう2 Testaularの使い方

こんにちは、こんばんわ
NHN Japan ウェブサービス本部開発1室UITチーム 吉田徹生(@teyosh)と申します。

前回の続きでAngularJSについて紹介していきたいと思います。
AngularJSって何?という方は前回の記事[Angular JSを使おう]を御覧ください。

ここ数年でJavaScriptのコードは膨大に増えてきていると感じています。
出来うる限りバグを少なくしよう、保守をしやすくしようと様々なライブラリーやデザインパターンが導入されてきています。
それに伴い、JavaScript界隈にもテストを重視する様になってきて、クオリティも上がってきていると思います。

さて、JavasScriptのテストといえばQunit、Jasmine、Mocha、seleniumなどを挙げられると思います。

今回はそれらとは少し違うAngular JSのために作られたTestacularを紹介したいと思います。

まずは、Testacularについて

Vojta Jina created Testacular (GitHub: vojtajina / testacular, License: MIT, npm: testacular) to write better tests for AngularJS, Google’s client-side library that’s rapidly gaining support from the wider web development community.[DailyJS]
意訳:ボイタ・ジーナがAngularJSのためによりよいテストがかけるようにTestacularを作った。

特徴

  • Node.jsを利用
  • 各種ブラウザでテスト
  • MochaやJasmineをテストライブラリーとして使える
  • Socket.IOを利用してターミナルとブラウザ間でリアルタイムでテスト結果を出力
  • ディレクトリ管理をして、ファイルが更新されたら自動でテスト実行

など、テストをしやすくなっています

利用方法

まずはNode.jsをインストールしてください。
Testacularはnpmと呼ばれるパッケージマネージャに登録されていますので、

npm -g install testacular

と実行してください。
これでインストールは完璧です。

まず最初にテストを実行するための設定ファイルを書き出します。

% testacular init

Which testing framework do you want to use ?
Press tab to list possible options. Enter to move to the next question.
> Jasmine

Do you want to capture a browser automatically ?
Press tab to list possible options. Enter empty string to move to the next question.
> Chrome
>

Which files do you want to test ?
You can use glob patterns, eg. "js/.js" or "test//Spec.js".
Enter empty string to move to the next question.
> src/.js
> test/.js
>

Any files you want to exclude ?
You can use glob patterns, eg. "*/.swp".
Enter empty string to move to the next question.
>

Do you want Testacular to watch all the files and run the tests on change ?
Press tab to list possible options.
> yes

Config file generated at "/Users/nhnmacuser/Test/testacular/testacular.conf.js".

上から順に
・どれか、テストフレームワークを使いますか?
・自動で確認するブラウザを決めてください。
・テストファイルを指定してください。
・読み込まないファイルを指定してください。
・ファイルを監視して変更があったらテストを実行しますか?
となっています。
そして出来上がったのが以下のファイルになります。

// Testacular configuration
// Generated on Thu Nov 22 2012 17:40:09 GMT+0900 (JST)

// base path, that will be used to resolve files and exclude
basePath = '../../../../..';

// list of files / patterns to load in the browser
files = [
JASMINE,
JASMINE_ADAPTER,
'src/.js',
'test/.js'
];

// list of files to exclude
exclude = [

];

// test results reporter to use
// possible values: 'dots', 'progress', 'junit'
reporters = ['progress'];

// web server port
port = 8080;

// cli runner port
runnerPort = 9100;

// enable / disable colors in the output (reporters and logs)
colors = true;

// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel = LOG_INFO;

// enable / disable watching file and executing tests whenever any file changes
autoWatch = true;

// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera
// - Safari (only Mac)
// - PhantomJS
// - IE (only Windows)
browsers = ['Chrome'];

// If browser does not capture in given timeout [ms], kill it
captureTimeout = 5000;

// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun = false;

basePathはデフォルトではrootになっていますので、

basePath='';

として、カレントを指定するのがおすすめです。

実際に使ってみましょう

準備は出来ましたので、実際に動かしていきます。
以下のようなコードがあるとします。

function hello(str){
  var string = "Hello";
  return string;
}

求められる結果はHelloの後ろに引数を継いで返したいとします。
そうなると以下のテストコードになります。

describe("Hello", function() {
  it("returns hello Testacular", function() {
    expect(hello("Testacular")).toEqual("Hello Testacular");
  });
});

では、実行してみましょう。

% testacular start
info: Testacular server started at http://localhost:8080/
info (launcher): Starting browser Chrome
warn (launcher): Chrome have not captured in 5000 ms, killing.
info (launcher): Trying to start Chrome again.
info (Chrome 23.0): Connected on socket id -nVqYdnFQ9NGbFb1UmhY
Chrome 23.0 Hello returns hello Testacular FAILED
    Expected 'Hello' to equal 'Hello Testacular'.
    Error: Expected 'Hello' to equal 'Hello Testacular'.
        at null.<anonymous> (/Users/nhnmacuser/Test/testacular2/test/helloTest.js:3:33)
Chrome 23.0: Executed 1 of 1 (1 FAILED) (0.301 secs / 0.003 secs)

もちろん、失敗します。
シェルはそのままにsrc/hello.jsを書き換えてみます。

function hello(str){
  var string = "Hello "+str;
  return string;
}

これで保存をすると、自動でテストが走り

info (watcher): Changed file "/Users/nhnmacuser/Test/testacular2/src/hello.js".
Chrome 23.0: Executed 1 of 1 SUCCESS (0.097 secs / 0.002 secs)

このようにSUCCESSとなります。

まとめ

MVCなどのライブラリーが増えていき、webアプリも巨大になっていく方向に進んでいます。
そのため、これまで以上にテストが重要になってくると考えています。
CI、自動、クロスブラウザと言ったテストをする上で最低限のことを備えているTestacularはこれからのWebアプリのクオリティを一段階も二段階も上げてくれると感じています。