RailsのJavaScript Testプラグインでカスタムアサーションを利用する

加藤です。

JavaScript Testプラグイン は、script.aculo.usのテスティングフレームワーク unittest.js を利用したユニットテストの作成と実行を助けてくれるRailsのプラグインです。ロジックを含むJavaScriptモデルをテストすると良い感じなので、Railsのユニットテストと同様にモデルのテストを中心に活用すると良いでしょう。Ajax on Railsで紹介されている例のように、ビューのテストで利用しようとすると少し面倒くさいです。

JavaScript Testプラグインの導入や利用の方法は、Ajax on Railsや Ajax on Rails Cheat Sheet を参考にしていただくとして、今回はJavaScript用にテストヘルパーを作成してカスタムアサーションを利用するTipsです。

まず、テストヘルパーを作成します。僕はJavaScript Testプラグインのassetsディレクトリ内に設置しました。テストヘルパーではカスタムアサーション用のメソッドを記述して、最後にObject.extendでTest.Unit.Testcaseへコピーします。

RAILS_ROOT/vendor/plugins/javascript_test/assets/test_helper.js

Test.Unit.TestHelper = Class.create();
Test.Unit.TestHelper.prototype = {
  assertErrorsOn: function(property, object) {
    var message = arguments[2] || 'assertErrorsOn';
    try {
      (object.errors.on(property)) ? this.pass() :
        this.fail(message + ":  property [" + property + "] was not invalid.");
    } catch (e) { this.error(e); }
  },
  ...
}
Object.extend(Test.Unit.Testcase.prototype, Test.Unit.TestHelper.prototype);
<span class="nx">Test</span><span class="p">.</span><span class="nx">Unit</span><span class="p">.</span><span class="nx">TestHelper</span> <span class="o">=</span> <span class="nx">Class</span><span class="p">.</span><span class="nx">create</span><span class="p">();</span>
<span class="nx">Test</span><span class="p">.</span><span class="nx">Unit</span><span class="p">.</span><span class="nx">TestHelper</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="p">{</span>
  <span class="nx">assertErrorsOn</span><span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">property</span><span class="p">,</span> <span class="nx">object</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">message</span> <span class="o">=</span> <span class="nx">arguments</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">||</span> <span class="s1">&#39;assertErrorsOn&#39;</span><span class="p">;</span>
    <span class="k">try</span> <span class="p">{</span>
      <span class="p">(</span><span class="nx">object</span><span class="p">.</span><span class="nx">errors</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="nx">property</span><span class="p">))</span> <span class="o">?</span> <span class="k">this</span><span class="p">.</span><span class="nx">pass</span><span class="p">()</span> <span class="o">:</span>
        <span class="k">this</span><span class="p">.</span><span class="nx">fail</span><span class="p">(</span><span class="nx">message</span> <span class="o">+</span> <span class="s2">&quot;:  property [&quot;</span> <span class="o">+</span> <span class="nx">property</span> <span class="o">+</span> <span class="s2">&quot;] was not invalid.&quot;</span><span class="p">);</span>
    <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span> <span class="p">}</span>
  <span class="p">},</span>
  <span class="p">...</span>
<span class="p">}</span>
<span class="nb">Object</span><span class="p">.</span><span class="nx">extend</span><span class="p">(</span><span class="nx">Test</span><span class="p">.</span><span class="nx">Unit</span><span class="p">.</span><span class="nx">Testcase</span><span class="p">.</span><span class="nx">prototype</span><span class="p">,</span> <span class="nx">Test</span><span class="p">.</span><span class="nx">Unit</span><span class="p">.</span><span class="nx">TestHelper</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span>

作成したテストヘルパーを利用するには、テスト用のHTMLファイルでunittest.jsの後に読み込むようにします。

RAILS_ROOT/test/javascript/user_test.html

...
<script src="assets/prototype.js" type="text/javascript"></script>
<script src="assets/unittest.js" type="text/javascript"></script>
<script src="assets/test_helper.js" type="text/javascript"></script>
...
...
<span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;assets/prototype.js&quot;</span> <span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span><span class="nt">&gt;&lt;/script&gt;</span>
<span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;assets/unittest.js&quot;</span> <span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span><span class="nt">&gt;&lt;/script&gt;</span>
<span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;assets/test_helper.js&quot;</span> <span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span><span class="nt">&gt;&lt;/script&gt;</span>
...

カスタムアサーションがユニットテスト内で以下のように利用できるようになります。

new Test.Unit.Runner({
  ...
  testValidation: function() { with (this) {
    var user = new User({name: "", email: ""});
    assert(!user.valid());
    assertErrorsOn("name", user);
  },
  ...

JavaScriptのモデルもActiveRecordのモデルとインターフェイスを合わせておくと判りやすくて良いですね。

あと、前回紹介した Ajax on Rails Cheat Sheet に間違いがあったので修正しました。あたらしいものをアップしておきますので、良かったら以下からダウンロードしてください。

  • script.aculo.us unittest.js
    修正前: assert[Not]InstanceOf(object, expected[,message])
    修正後: assert[Not]InstanceOf(expected, object[,message])
    ※ Ajax on Railsの269ページも間違ってますね。

Bookmark and Share