JsTestDriverとは
JsTestDriverはオープンソースで開発されているJavaScript用のユニットテストフレームワークである。JavaScriptの場合、通常は実行エンジンがWebブラウザに依存するため、ブラウザごとに個別にテストしなければならないという難点がある。JsTestDriverを使うことでその悩みは解消できるだろう。
JsTestDriverはWebサーバとして動作するフレームワークである。テストコードはJavaScriptで記述して指定されたディレクトリに配置する。WebブラウザからJsTestDriverの特定のパスにアクセスすると、そのブラウザがテストを実行する環境として登録される。Webブラウザは複数同時に接続しておくことができる。
実際にテストを実施すると、接続されているすべてのWebブラウザのJavaScriptエンジンそれぞれでテストコードを実行し、結果を表示する。したがってエンジンごとに挙動の異なるような場合でも簡単にテストすることができる。
JsTestDriver本体はJavaで作成されており、単体のJARファイルとして提供されている。したがってサーバの起動やテストの実行はコマンドラインからjavaコマンドを用いて行う。またEclipse用プラグインも提供されており、これを用いることで使い慣れたIDEでの開発にJsTestDriverによるユニットテストを取り込むことが可能となる。
JsTestDriverによるユニットテストの実施
ではさっそく、JsTestDriverを使ってみよう。公式サイトではSubversionリポジトリにおいてサンプルプロジェクトが公開されているので、まずはこれを試してみることにする。サンプルプロジェクトのリポジトリは「http://js-test-driver.googlecode.com/svn/samples」なので、まずはこれをチェックアウトする。
プロンプト1
> svn checkout http://js-test-driver.googlecode.com/svn/samples samples
samplesにはhello-worldというディレクトリが含まれており、その中にあるJsTestDriver.jarがJsTestDriverの本体である。そしてsrcディレクトリにテスト対象となるコードが、src-testディレクトリにテストコードが格納されている。
まずテストを実行する前に、JsTestDriverをサーバとして起動する必要がある。hello-worldディレクトリに移動し、次のようにjavaコマンドを使って起動する。--portオプションで指定しているのはサーバを立ち上げるポートである。
プロンプト2
> cd samples/hello-world
> java -jar JsTestDriver.jar --port 4224
この状態で、テストしたいWebブラウザを起動して「http://localhost:4224/capture」にアクセスすることで、そのブラウザがテスト環境として接続される。たとえばFirefoxの場合には図1のように表示される。あるいは、自分でWebブラウザを立ち上げる代わりに、次のようにサーバの起動時に--browserオプションでWebブラウザの実行ファイルへのパスを指定してもよい。
プロンプト3
> java -jar JsTestDriver.jar --port 4224 --browser "C:\Program Files\Mozilla Firefox\firefox.exe"
「http://localhost:4224/」にアクセスすることで、現在サーバに接続されているWebブラウザの一覧を見ることができる。図2はFirefoxとGoogle Chromeを接続している場合の表示だ。
テストの実施は、1つ以上のWebブラウザが接続されている状態でコマンドプロンプトから次のコマンドを実行すればよい。FirefoxとGoogle Chromeにおいて、それぞれテストを通過していることが分かる。
プロンプト4
> java -jar JsTestDriver.jar --tests all
..
Total 2 tests (Passed: 2; Fails: 0; Errors: 0) (1.00 ms)
Chrome 3.0.195.6: Run 1 tests (Passed: 1; Fails: 0; Errors 0) (1.00 ms)
GreeterTest.testGreet passed (1.00 ms)
[LOG] JsTestDriver Hello World!
Firefox 1.9.0.13: Run 1 tests (Passed: 1; Fails: 0; Errors 0) (1.00 ms)
GreeterTest.testGreet passed (1.00 ms)
[LOG] JsTestDriver Hello World!
今回テストしたJavaScriptのコードを見てみよう。srcディレクトリにはGreeter.jsというファイルが格納されており、内容は次のようになっている。このmyapp.Greeter.prototype.greet()関数がテストの対象となっている。この関数は引数に文字列を受け取り、「Hello XXXX!」の形にして返すという単純なものだ。
リスト1
myapp = {};
myapp.Greeter = function() { };
myapp.Greeter.prototype.greet = function(name) {
return "Hello " + name + "!";
};
テストコードはsrc-testディレクトリに格納されているGreeterTest.jsで、中身は次のようになっている。
リスト2
GreeterTest = TestCase("GreeterTest");
GreeterTest.prototype.testGreet = function() {
var greeter = new myapp.Greeter();
assertEquals("Hello World!", greeter.greet("World"));
jstestdriver.console.log("JsTestDriver", greeter.greet("World"));
console.log(greeter.greet("Browser", "World"));
};
TestCaseはJsTestDriverに用意されたテストを定義するためのクラスである。このTestCaseを利用して、独自のテストケースとなる「GreeterTest」を用意している。GreeterTestのprototypeに関数を定義することによって、その関数がテスト用の関数となりJsTestDriverから呼び出されることになる。ここではGreeterTest.prototype.testGreet()というテスト用関数が定義されている。
実際に状態チェックを行っているのはassertEquals()関数だ。これは2つのオブジェクトの値が等しいかどうかをチェックするアサーション用の関数である。この例では「greeter.greet("World")」の呼び出し結果が「Hello World!」になっているかどうかをチェックしている。JaTestDriverにはその他にもtrue/falseやnullチェックなどを行う関数が用意されている。最後の2行はログ出力のためのコードである。
ここで、ためしにassertEquals(...)の部分を「assertEquals("Hello World!", greeter.greet("Warld"));」と書き換えてみよう。先程と同様にテストを実行すると次のような結果が出力される。書き換えたassertEquals(...)の部分でテストに失敗していることがわかる。
プロンプト5
> java -jar JsTestDriver.jar --tests all
FF
Total 2 tests (Passed: 0; Fails: 2; Errors: 0) (55.00 ms)
Chrome 3.0.195.6: Run 1 tests (Passed: 0; Fails: 1; Errors 0) (55.00 ms)
GreeterTest.testGreet failed (55.00 ms): expected "Hello World!" but was "Hello Warld!"
at [object Object].testGreet (http://localhost:4224/test/src-test/GreeterTest.js:5:39)
Firefox 1.9.0.13: Run 1 tests (Passed: 0; Fails: 1; Errors 0) (1.00 ms)
GreeterTest.testGreet failed (1.00 ms): expected "Hello World!" but was "Hello Warld!"
()@http://localhost:4224/test/src-test/GreeterTest.js:5