JavaScript
JsTestDriver

JsTestDriver使い方メモ

More than 3 years have passed since last update.

JsTestDriver の使い方をメモする。

JsTestDriver とは、 Google が開発してるオープンソースの JavaScript 用テスティングフレームワークのこと。


環境


OS

Windows7 64bit


Java

1.7.0_25


JsTestDriver

1.3.5


JsTestDriver のインストール

ここ から JsTestDriver-x.x.x.jar をダウンロードして任意のフォルダに配置する。

仮に jar を配置したフォルダのパスを %JSTESTDRIVER_HOME% とする。


テストを実行する

JsTestDriver でテストするときの手順はおおまかには以下の通り。


  1. JsTestDriver サーバを起動する

  2. テストしたいブラウザを JsTestDriver サーバに接続する

  3. テストを実行する


JsTestDriver サーバを起動する

コマンドプロンプトを開き、以下のコマンドを実行する。


サーバの起動

>java -jar %JSTESTDRIVER_HOME%\JsTestDriver-x.x.x.jar --port 4224


サーバが 4224 ポートで起動する(4224 ポートは JsTestDriver を使うときの慣例らしい)。


テストしたいブラウザを JsTestDriver サーバに接続する

とりあえず Chrome で接続する。

Chrome を起動し、 http://localhost:4224 にアクセスする。

Chromeでアクセスした様子

テストする時のページのDTD を「移行型」と「厳密型」のどちらにするかを選択する。

選択すると、以下のページに移動する。ブラウザの準備はこれで OK。

ブラウザで接続


テストを実行する


フォルダ構成


フォルダ構成

D:\tmp\JsTestDriver

│ jsTestDriver.conf
├─src
│ TestTarget.js
└─test
TestTargetTest.js


各ファイルの内容


src/TestTarget.js

function targetMethod(x, y) {

return x + y;
}


test/TestTargetTest.js

TestCase('TestTarget Test', {

'test targetMethod': function() {
// setup
var expected = 51;

// exercise
var actual = targetMethod(11, 40);

// verify
assertEquals(expected, actual);
}
});



jsTestDriver.conf

server: http://localhost:4224

load:
- src/*.js
- test/*.js



実行方法

コマンドプロンプトを開き、 jsTestDriver.conf のあるフォルダに移動して次のコマンドを実行する。

jsTestDriver.conf があるフォルダまでのパスに日本語が含まれるとエラーになる。


テストの実行

>java -jar %JSTESTDRIVER_HOME%\JsTestDriver-x.x.x.jar --tests all



テストの実行結果

setting runnermode QUIET

.
Total 1 tests (Passed: 1; Fails: 0; Errors: 0) (0.00 ms)
Chrome 29.0.1547.76 Windows: Run 1 tests (Passed: 1; Fails: 0; Errors 0) (0.00 ms)


注意点


テスト関数は、名前が test で始まっている必要がある。


テスト関数の名前のルール

TestCase('TestTarget Test', {

// 実行される
'test function': function() {
jstestdriver.console.log('test function');
},

// 実行されない
'not test function': function() {
jstestdriver.console.log('not test function');
}
});



実行結果

Total 1 tests (Passed: 1; Fails: 0; Errors: 0) (1.00 ms)

Chrome 29.0.1547.76 Windows: Run 1 tests (Passed: 1; Fails: 0; Errors 0) (1.00 ms)

TestTarget Test.test function passed (1.00 ms)
[LOG] test function



テスト関数名には日本語が使えるが、実行時に文字化けする


日本語は基本文字化けする

TestCase('TestTarget Test', {

'test 日本語': function() {
jstestdriver.console.log('test 日本語');
}
});


実行結果

Total 1 tests (Passed: 1; Fails: 0; Errors: 0) (0.00 ms)

Chrome 29.0.1547.76 Windows: Run 1 tests (Passed: 1; Fails: 0; Errors 0) (0.00 ms)

TestTarget Test.test ??{?? passed (0.00 ms)
[LOG] test ??{??


実行はできるけど、文字化けしてしまう。

テスト名は日本語で書きたいなぁ。。。


その他使い方


コンソール出力

console はブラウザによっては対応していないものがあるので、 JsTestDriver を使うときは JsTestDriver が提供してるコンソール出力用 API を使うのが良い。

具体的には、 jstestdriver.console というオブジェクトを使う。

loginfodebug といった関数が用意されてる。


コンソール出力

TestCase('TestTarget Test', {

'test console': function() {
var console = jstestdriver.console;

console.log('log message');
console.debug('debug message');
console.info('info message');
console.warn('warn message');
console.error('error message');
}
});



実行結果

[LOG] log message

[DEBUG] debug message
[INFO] info message
[WARN] warn message
[ERROR] error message

C の printf 的な使い方もできる。


フォーマット

TestCase('TestTarget Test', {

'test console': function() {
var string = 'string message';
var obj = {
string: 'Name',
num : 10,
bool : true,
und : undefined,
nul : null,
func : function() {
alert('hoge');
}
};

var console = jstestdriver.console;

console.log('string = %s', string);
console.log('obj = %o', obj);
}
});



実行結果

[LOG] string = string message

[LOG] obj = {"string":"Name","num":10,"bool":true,"nul":null}

%s で文字列形式、 %o でオブジェクトを JSON に変換した形式で出力できる(undefined と関数は出力されない)。


事前処理・事後処理を実装する

JUnit の setUptearDown メソッドに該当するもの。

ずばりその名前で関数を定義すれば、各テストの前後で実行される。


事前・事後処理

TestCase('TestTarget Test', {

setUp: function() {
log('setUp');
},

tearDown: function() {
log('tearDown');
},

'test 1': function() {
log('test 1');
},

'test 2': function() {
log('test 2');
}
});

function log(msg) {
jstestdriver.console.log(msg);
}



実行結果

TestTarget Test.test 1 passed (0.00 ms)

[LOG] setUp
[LOG] test 1
[LOG] tearDown

TestTarget Test.test 2 passed (0.00 ms)
[LOG] setUp
[LOG] test 2
[LOG] tearDown


各テストメソッドごとに、 setUp() 関数と tearDown() 関数が呼ばれる。


各テスト関数で共通して使用する値を用意する

各テストで共通して使用したい値がある場合は、 setUp() 関数内で this にプロパティを追加すればいい。


各テストで共通して使用する値の参照

var cons = jstestdriver.console

TestCase('TestTarget Test', {
setUp: function() {
this.value = 'common value';
},

'test 1': function() {
cons.log('test 1 : this.value = %s', this.value);
},

'test 2': function() {
cons.log('test 2 : this.value = %s', this.value);
}
});



実行結果

TestTarget Test.test 1 passed (0.00 ms)

[LOG] test 1 : this.value = common value

TestTarget Test.test 2 passed (0.00 ms)
[LOG] test 2 : this.value = common value



1つの js ファイルに複数の TestCase を書く

JUnit4 の Enclosed みたいなイメージ。


複数のTestCase

var cons = jstestdriver.console;

TestCase('TestCase 1', {
'test 1': function() {
cons.log('test 1');
}
});

TestCase('TestCase 2', {
'test 2': function() {
cons.log('test 2');
}
});



実行結果

Total 2 tests (Passed: 2; Fails: 0; Errors: 0) (1.00 ms)

Chrome 29.0.1547.76 Windows: Run 2 tests (Passed: 2; Fails: 0; Errors 0) (1.00 ms)

TestCase 1.test 1 passed (1.00 ms)
[LOG] test 1

TestCase 2.test 2 passed (0.00 ms)
[LOG] test 2


問題なく動く。事前処理が同じものでまとめるとコードが見やすくなるかな。


テスト用の DOM を用意する

テストコード中に特殊なコメントを記述することで、テストでのみ使える DOM を用意することができる。


DOM オブジェクトを作成する


DOMオブジェクトの作成

TestCase('TestCase 1', {

'test': function() {
/*:DOC dom = <input value="test-value" />*/

var value = this.dom.getAttribute('value')
jstestdriver.console.log('dom.value = %s', value);
}
});



実行結果

[LOG] dom.value = test-value



DOMオブジェクトを定義するときの書式

/*:DOC <変数名> = <HTMLタグ>*/


テスト実行時にコメント行を通過すると、以後 this.<変数名><HTMLタグ> に指定したタグの DOM オブジェクトを取得できるようになる。


コメント行の前では DOM オブジェクトは取得できない

コメント行が処理される前だと、 DOM オブジェクトは生成されないので注意。


コメント行の前ではDOMオブジェクトはまだできていない

TestCase('TestCase 1', {

'test': function() {
jstestdriver.console.log('dom = %s', this.dom);

/*:DOC dom = <input />*/
}
});



実行結果

[LOG] dom = undefined



各テスト関数で生成した DOM オブジェクトはその関数内でのみ有効

各テスト関数内で生成された DOM は、その関数内でのみ使用可能で、他のテスト関数からは参照できない。


他のテスト関数で生成されたDOMオブジェクトは参照できない

var cons = jstestdriver.console;

TestCase('TestCase 1', {
'test': function() {
cons.info('test1');
/*:DOC dom = <input />*/
cons.log('dom = %s', this.dom);
},

'test2': function() {
cons.info('test2');
cons.log('dom = %s', this.dom);
}
});



実行結果

TestCase 1.test passed (0.00 ms)

[INFO] test1
[LOG] dom = [object HTMLInputElement]

TestCase 1.test2 passed (0.00 ms)
[INFO] test2
[LOG] dom = undefined



各テスト関数から参照できる DOM オブジェクトを用意する

各テスト関数から共通で参照したい DOM オブジェクトがある場合は、 setUp() 関数にコメントを書けばいい。


setUp関数でDOMオブジェクトを宣言する

var cons = jstestdriver.console;

TestCase('TestCase', {
setUp: function() {
/*:DOC dom = <input value="common-value" />*/
},

'test1': function() {
cons.info('test 1');
cons.log(this.dom.getAttribute('value'));
},

'test2': function() {
cons.info('test 2');
cons.log(this.dom.getAttribute('value'));
}
});



実行結果

TestCase.test1 passed (0.00 ms)

[INFO] test 1
[LOG] common-value

TestCase.test2 passed (0.00 ms)
[INFO] test 2
[LOG] common-value



複数の DOM を作成可能

1つのコメントの中で、複数のタグを記述できる。


複数のDOMを作成

TestCase('TestCase', {

'test': function() {
/*:DOC dom = <input value="test-value-1" /><input value="test-value-2" />*/

var children = this.dom.childNodes;

for (var i=0; i<children.length; i++) {
jstestdriver.console.log('childNodes[%d].value = %s', i, children[i].getAttribute('value'));
}
}
});



実行結果

[LOG] childNodes[0].value = test-value-1

[LOG] childNodes[1].value = test-value-2


ブラウザにDOMを追加する


ブラウザにDOMを追加する

TestCase('TestCase', {

'test': function() {
/*:DOC += <input id="test-dom" value="test-value" />*/

var value = document.getElementById('test-dom').getAttribute('value')
jstestdriver.console.log('value = %s', value);
}
});



実行結果

[LOG] value = test-value



ブラウザにDOMを追加する場合のコメントの書式

/*:DOC += <HTMLタグ>*/


他のテスト関数から参照できないなどの動作は DOM オブジェクトを作成する場合と同じ。


参考