テスト
セットアップ
Mithril.js アプリケーションのテストは比較的容易です。最も簡単な方法として、ospec、mithril-query、JSDOM を使用する方法があります。これらのライブラリは、以下のコマンドで簡単にインストールできます。
npm install --save-dev ospec mithril-query jsdom
インストール後のセットアップも比較的簡単で、いくつかの手順が必要です。
package.json
ファイルの npm スクリプトに"test": "ospec --require ./test-setup.js"
を追加します。--require
オプションで、後述するセットアップファイルを指定します。以下は例です。プロジェクトによっては、他のフィールドも含まれる場合があります。
{
"name": "my-project",
"scripts": {
"test": "ospec --require ./test-setup.js"
}
}
- セットアップファイル
test-setup.js
を作成し、以下のコードを記述します。
var o = require('ospec');
var jsdom = require('jsdom');
var dom = new jsdom.JSDOM('', {
// `requestAnimationFrame` を利用可能にする
pretendToBeVisual: true,
});
// Mithril.js が動作するために必要なグローバル変数を設定します。最初の 2 つはテストで役立つことがよくあります。
global.window = dom.window;
global.document = dom.window.document;
global.requestAnimationFrame = dom.window.requestAnimationFrame;
// Mithril.js を require して、正しくロードされることを確認します。
require('mithril');
// テスト終了時に JSDOM を終了させる
o.after(function () {
dom.window.close();
});
- テスト対象のコンポーネント(例:
src/my-component.js
)を以下のように作成します。
function MyComponent() {
return {
view: function (vnode) {
return m('div', vnode.attrs.text);
},
};
}
module.exports = MyComponent;
- 最後に、テストファイル(例:
src/tests/my-component.js
)を以下のように作成します。
var mq = require('mithril-query');
var o = require('ospec');
var MyComponent = require('../my-component.js');
o.spec('MyComponent', function () {
o('正常に動作すること', function () {
var out = mq(MyComponent, { text: 'What a wonderful day to be alive!' });
out.should.contain('day');
});
});
上記の設定が完了したら、インストールに使用したターミナルで以下のコマンドを実行します。
npm test
すべて正しくセットアップされていれば、次のような出力が表示されるはずです。
––––––
All 1 assertions passed in 0ms
ベストプラクティス
テストは多くの場合、比較的簡単です。各テストは通常、状態のセットアップ、コードの実行、結果の検証という 3 つのステップで構成されます。効果的なテストを行うために、テスト時に留意すべき点がいくつかあります。
できるだけ早い段階でテストを書くことを推奨します。必ずしも最初にテストを書く必要はありませんが、コードを書くのと並行してテストを書くことをお勧めします。そうすることで、想定通りに動作しない場合でも、すぐに原因を特定できます。後回しにして、後で大規模な修正が必要になる状況を避けることができます。
API と動作をテストし、実装の詳細をテストしないようにします。特定のアクションによってイベントが発火されることをテストするのは良いでしょう。しかし、DOM 構造全体をテストすることは避けるべきです。単純なスタイルの変更で、多数のテストを修正する必要が生じる可能性があります。また、オブジェクトに新しいメソッドを追加しただけで、すべてのテストを書き直すような事態も避けたいものです。
同じ処理の繰り返しを避けることを意識しすぎないでください。同じファイル内で何度も同じ処理を繰り返す場合や、テストを自動生成する場合にのみ抽象化を検討してください。通常のコードでは、同じロジックを2~3回繰り返す場合は関数として抽象化しますが、テストコードでは冗長性がある方が、問題発生時の状況把握が容易になります。テストは仕様であり、通常のコードとは異なるということを覚えておいてください。
ユニットテスト
ユニットテストは、アプリケーションの一部(通常は単一のモジュールですが、場合によっては単一の関数)を分離し、それを単一の「ユニット」としてテストします。特定の入力と初期状態が与えられた場合に、期待される出力と副作用が生成されることを検証します。難しく聞こえるかもしれませんが、実際にはそうではありません。JavaScript の +
演算子を数値に適用した場合のユニットテストの例を以下に示します。
o.spec('addition', function () {
o('整数での動作を確認', function () {
o(1 + 2).equals(3);
});
o('浮動小数点数での動作を確認', function () {
// IEEE-754浮動小数点数の仕様によるものです。
o(0.1 + 0.2).equals(0.30000000000000004);
});
});
このように単純なものをユニットテストできるのと同じように、Mithril.js コンポーネントもユニットテストが可能です。以下のコンポーネントがあるとします。
// MyComponent.js
var m = require('mithril');
function MyComponent() {
return {
view: function (vnode) {
return m('div', [
vnode.attrs.type === 'goodbye' ? 'Goodbye, world!' : 'Hello, world!',
]);
},
};
}
module.exports = MyComponent;
これに対して、以下のようなユニットテストを簡単に作成できます。
var mq = require('mithril-query');
var MyComponent = require('./MyComponent');
o.spec('MyComponent', function () {
o("`type` が `hello` の場合、'Hello, world!' と表示されること", function () {
var out = mq(MyComponent, { type: 'hello' });
out.should.contain('Hello, world!');
});
o("`type` が `goodbye` の場合、'Goodbye, world!' と表示されること", function () {
var out = mq(MyComponent, { type: 'goodbye' });
out.should.contain('Goodbye, world!');
});
o("`type` が指定されていない場合、'Hello, world!' と表示されること", function () {
var out = mq(MyComponent);
out.should.contain('Hello, world!');
});
});
前述のように、テストは仕様です。テストからコンポーネントがどのように動作するべきかを確認でき、コンポーネントはその仕様を効果的に実行します。