MochaがPromisesのテストをサポートしました
JavaScriptテストフレームワークのMocha 1.18.0がリリースされ、promiseのテストがサポートされました。
この記事では、次の事について書かれています。
- Promisesのテストの書き方がどう変わるの?
- なぜ、フレームワーク側がpromiseのサポートのする必要があるの?
- 他のPromisesテストのアプローチ
Promisesのテストの書き方がどう変わるの?
例えば、以下のようなpromiseオブジェクトを返す関数をテストしたいと思います。
function getSuccessPromise() {
return Promise.resolve(true);
}
このpromiseオブジェクトは、resolveするので、.then
の第一引数で指定したonFulfilled
コールバックに true
という値を渡すようになってます。
今までのテストの書き方
このgetSuccessPromise
を 1.18.0より以前は以下のように書くことでテストをしていました。
it("should manually handling test...", function (done) {
getSuccessPromise().then(function (value) {
assert(value);
done();
}).catch(done); // <= このcatchが今回の変更での焦点
});
getSuccessPromise()
の返り値であるpromiseオブジェクトがresolveされると value
に true
が入って assert(true)
なのでテストが通るという感じですね。
これの何が問題(面倒)なのかというと、意味がなさそうに見える catch(done)
をわざわざ書いてるのから分かるかもしれませんが、テストが失敗した時に結果をdoneに渡す必要があります。
何故かというと、assertの結果がfailの場合は例外が投げられますが、promisesの.then
の中で例外が投げられても自動的に例外がキャッチされてしまいます。
もし、.catch(done);
を書かなかった場合、テストが失敗することもないですし、done
も呼ばれないため終わらないテストが出来上がってしまいます。(タイムアウトになるテスト)
このことを忘れると簡単に無意味なテストが出来上がったりしてしまうため結構はまりやすいです。
例えば、次のようなテストはタイムアウトが来るまで終わらなくなります。
it("is 終わらないテスト", function (done) {
Promise.resolve(false).then(function (value) {
assert(value);
done();
});
});
promisesのテストサポート
これがどのように書けるようになったかというと、公式のドキュメントにも載ってるのでそちらも参考にして欲しいのですが、以下のように書けるようになりました。
it("should support by mocha", function () {
return getSuccessPromise().then(function (value) {
assert(value);
});
});
上記のようにdone
がテストから消えてることがわかります。
代わりに、promiseオブジェクトをテスト内でreturnして渡しています。
ちゃんとassertがfailの場合はテストもfailとなり、テストコードに無駄がなくなっています。
いわゆるthenableオブジェクト、then
メソッドを持ったオブジェクトをreturnした場合、それはpromiseのテストだと判断してくれます。
以下にサンプルコードを置いてあります。(主に失敗した時の問題がわかるように失敗するテストが混じってます)
その他
このテスト内で promiseオブジェクトをreturn してテストできるものとしてはBuster.JS等があります。
(他にpromisesをサポートしてるフレームワークとかあるかな?)
mochaの該当pull request見ても分かるように結構歴史ある話ですが、最近になってECMAScriptとしてPromisesが仕様に入ってきたのもあって需要が出てきてサポートされた感じに見えます。
- Adding promise support to runnables (and thus tests). by domenic · Pull Request #329 · visionmedia/mocha<blockquote cite=“https://github.com/visionmedia/mocha/pull/329#issuecomment-37054832”
title=“Adding promise support to runnables (and thus tests). by domenic · Pull Request #329 · visionmedia/mocha”>
it is a community project so it’s kinda up to you guys
Adding promise support to runnables (and thus tests). by domenic · Pull Request #329 · visionmedia/mocha
その他のpromisesサポートの方法としては、domenic/mocha-as-promised等のassertを拡張したライブラリ使うことなどでも、シンプルに書くことができるかもしれません。
as-promisedで検索すると色々見つかると思います。
Promises Bookのテストを書いてて、同じ事を思ってたのでmocha自体がサポートしてくれてちょうど良かったです。
Promisesの強力なエラーハンドリングが、反ってテスト時には邪魔になってしまう事があるという面白い感じの話だと思います。
お知らせ欄
JavaScript Primerの書籍版がAmazonで購入できます。
JavaScriptに関する最新情報は週一でJSer.infoを更新しています。
GitHub Sponsorsでの支援を募集しています。