JavaScriptプログラム開発では、テスト環境が限られることが多い。また、Webブラウザごとに動作を確認しなくてはならないこともある。それなら、ライブラリ自身にテストツールが用意されていれば、テストの手間がいくらかでも軽減できるのではないか。

そこで連載の最後となる今回は、Script.aculo.usが持つテスト関連機能を取り上げる。バージョン1.8.1、Windows環境の場合で説明する。

テスト関連機能の概要

Script.aculo.usのテスト関連機能は、unittest.jsというファイルにソースコードが記述されている。注意すべきは、このファイルはscriptaculous.jsの自動ロードに対応していないことだ。つまり、このファイルを用いるときは、必ず<script>で読み込まなくてはならない。

このとき、以下のa.のようにファイル名を直接指定してもよいし、b.のようにloadパラメータで記述してもよい。ただし、b.の場合はloadパラメータを持つ<script>を先に記述しておいたほうが良いWebブラウザがあるので注意したい。

a. ファイル名を直接指定する場合

<script type="text/javascript" src="ディレクトリ/scriptaculous.js"></script>
<script type="text/javascript" src="ディレクトリ/unittest.js"></script>

b. loadパラメータで指定する場合

<script type="text/javascript" src="ディレクトリ/scriptaculous.js?load=unittest"></script>
<script type="text/javascript" src="ディレクトリ/scriptaculous.js"></script>

機能は大きく、xUnitとイベントのシミュレータに分かれる。

xUnitとは、JUnitなどのようなプログラム単体で動作をテストできるツールのことで、Script.aculo.usではTest.Unitというオブジェクトで用意されている。

シミュレータは、マウスのクリックやキーボード入力をテストプログラムで自動的に行うものだ。ただしこれは一部のWebブラウザでしか機能しないので、実行環境上で利用できるかを事前に確認しておいたほうが良いだろう。

テストするJavaScriptプログラム

では、テストを実行する対象となるJavaScriptプログラムを【リスト1】に示す。これは色名が書かれたボタンをクリックすると、点線の領域がその色に変わるというものだ。実行結果を図1、ソースコードの抜粋を【リスト1】に示す。

図1 ボタンのクリックで領域の背景色を変更

【リスト1】 図1を実行するソースコード(抜粋)

[HTML]
<div id="demo">
  <button id="red">赤</button>
  <button id="green">緑</button>
  <button id="blue">青</button>
  <button>リセット</button>
  <br />キーやボタンによって色がつく要素
</div>

[JavaScript]
// 領域の背景色などを変更
function setBgColor( bgColor )  {
  $( 'demo' ).setStyle( ( bgColor ) ?
    { 'backgroundColor' : bgColor, 'color' : 'white', 'fontWeight' : 'bold' } :
    { 'backgroundColor' : '', 'color' : '', 'fontWeight' : '' }
  );
}
// ボタンクリック時の処理を行うイベントハンドラ
function buttonClick( ev )  {
  setBgColor( ev.target.id );   // 領域の背景をid属性の値と同じ色にする
}
Event.observe( window, 'load', function()  {
  // ボタンクリック時のイベントハンドラを登録
  $$( 'button' ).invoke( 'observe', 'click', buttonClick );
} );

[CSS]
div#demo  {
  width   : 150px;
  height  : 100px;
  padding : 3px;
  margin  : 0.5em 0;
  border  : 1px dashed #000;
}

テストケースの作成

次に、上記がうまく動作するかを調べるテストケースをオブジェクトとして作成する。setupにはテストごとに行う初期設定、teardownにはテストの後処理を記述する。testに続く名前のプロパティの値(関数)が実際のテストケースとなる。

【リスト2】に示すtestRedは「赤」ボタンがクリックされたときに背景色が'red'と設定されるかをテストする。他のボタンについても同様にテストケースを記述できる。なお、Opera 9の場合は'#ff0000'などの値で結果を検証しないとテストが成功しない。

ここでは、ボタンのクリックをEvent.simulateMouseによって行っているが、現状ではFirefoxのみにしか対応していない。よってそれ以外のWebブラウザの場合はイベントハンドラを直接実行するようにしている。

イベントハンドラの引数を { target : { id : ... } } としているのは、処理中で ev.target.id を参照できるようにするためだ。処理で扱われるのと同じ構造のプロパティにしておかなくてはならないことに注意したい。

テストケース中のwith( this ) { ... } は、Test.Unit.Testcaseインスタンスのメソッド(assertEqualなど)を、this.を記述しなくても実行できるようにするものだ。必須とまではいえないが、実際にはテスト結果を検証するassert...メソッドを多用することになるので、記述しておくと便利だ。

【リスト2】 リスト1のテストケース(JavaScript)

var testcases = {
  setup : function()  {  with( this )  {
    // 領域を初期化
    $( 'demo' ).setStyle( { 'backgroundColor' : '', 'color' : '', 'fontWeight' : '' } );
  } },
  teardown : function()  {  with( this )  {
    /* ..... テストの後処理(省略) ..... */
  } },
  testRed : function() {  with( this )  {
    // 領域を赤色にするテスト
    var color = 'red';
    // ボタンをクリック(そうでなければイベントハンドラを実行)
    try  {
      new Event.simulateMouse( color, 'click' );
    }  catch( e )  {
      buttonClick( { target : { id : color } } );
    }
    // 領域の背景色が'red'なら動作は正常
    assertEqual( color, $( 'demo' ).getStyle( 'backgroundColor' ) );
  } },
  testGreen : function() {  with( this )  {
    /* ..... 領域を緑色にするテスト(省略) ..... */
  } },
  testBlue : function() {  with( this )  {
    /* ..... 領域を青色にするテスト(省略) ..... */
  } }
};

テストケースの実行

Test.Unit.Runnerインスタンスの引数に作成したテストケースを設定すると、それらが実行される。このとき、テスト結果を出力する要素もしくはそのIDも引数に記述しておくと、そこに出力される。

【リスト3】に、<div id="testlog">内にテスト結果を出力する場合の例を示す。リスト2のテストケースでは図2のように表示される。出力の形式は決まっているので、図3のようにCSSでテスト結果を目立たせると、より視認性を高めることもできる。

【リスト3】 テストケースの実行

[HTML] <div id="testlog"></div>  ← テスト結果の出力先
[JavaScript] new Test.Unit.Runner( testcases, 'testlog' );

図2 テスト結果

図3 テスト結果(CSS設定後)

開発に用いているライブラリにテストツールが同梱されていれば、別のツールを用意しなくても済み、ツール同士の親和性を気にする必要もない。Script.aculo.usを用いた開発を行うときは、今回紹介したテスト機能も有効に活用していただきたい。