海未「では今回は、ユニットテストを見てみましょう。簡単なFizzBuzzプログラムを使います」
ことり「FizzBuzz詐欺・・・」
海未「ユニットテストは、プログラムの単体テストです。テストハーネスを使って自動化するのが一般的で、Node.jsにも自動テストの仕組みが色々あります」
穂乃果「ホワイトボックステストだね」
海未「そういえば穂乃果たちは、テストについて調べていましたね。その通り、ホワイトボックステストに該当します」
海未「今回はテストフレームワークとしてmocha、アサーションライブラリとしてchaiを使います」
ことり「おいしそうだね♪」
海未「・・・どちらもnpmからインストールできます」
1 2 3 |
$ npm install mocha -g $ npm install chai --save |
海未「mochaをグローバルインストールしていますが、これはmochaがコードから利用するだけのモジュールでなくmochaコマンドをインストールするためです」
ことり「アプリみたいなパッケージもあるんだ」
海未「はい。npmでインストールできるパッケージは、ExpressのようなWebフレームワークからgulpのようなビルドツールまで様々なものがあります」
海未「では、テスト対象のコードを用意します」
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// fizzbuss.js module.exports = function(n) { if (n % 3 === 0 && n % 5 === 0) { return "ラブアローシュート!"; } else if (n % 3 === 0) { return "ファイトだよっ!"; } else if (n % 5 === 0) { return "ちゅんちゅん"; } else { return n; } } |
海未「3の倍数だと"ファイトだよっ!"、5の倍数だと"ちゅんちゅん"、3と5の公倍数だと・・・・・・"ラブアローシュート!"・・・です」
穂乃果「海未ちゃん、自分で書いておいてそれは・・・」
海未「いざ言葉にすると恥ずかしいではないですか!」
ことり「FizzとかBuzzとかどこいったのかな・・・」
海未「これに対するテストコードはこのようになります」
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// fizzbuzztest.js var should = require("chai").should(); var fizzbuzz = require("./fizzbuzz.js") describe("test", function() { it("pass 1, expect 1", function() { fizzbuzz(1).should.equal(1); }); it("pass 3, expect ファイトだよっ!", function() { fizzbuzz(3).should.equal("ファイトだよっ!"); }); it("pass 5, expect ちゅんちゅん", function() { fizzbuzz(5).should.equal("ちゅんちゅん"); }); it("pass 15, expect ラブアローシュート!", function() { fizzbuzz(15).should.equal("ラブアローシュート!"); }); }) |
海未「describe
の中のit
が1件のテストケースになります」
ことり「fizzbuzz(1) should equal 1、普通に読めるね」
穂乃果「うーむ・・・」
海未「穂乃果の英語力には期待していません。このshould
は、Object
のプロトタイプを拡張する形で実装されています」
ことり「じゃあ、このコードの中なら何にでもshould
プロパティが付いてるんだ」
海未「そうなりますね。should
には今回使ったequal
の他にhave
やbe
などのアサーションメソッドが用意されています」
海未「これをmochaコマンドで実行すると」
1 2 3 4 5 6 7 8 9 10 11 12 |
$ mocha fizzbuzztest.js test √ pass 1, expect 1 √ pass 3, expect ファイトだよっ! √ pass 5, expect ちゅんちゅん √ pass 15, expect ラブアローシュート! 4 passing (41ms) |
海未「このようになります」
ことり「4件とも成功だね」
海未「これが最もシンプルなユニットテストです」
海未「少し応用です。今回は必要ないのですが、テストの前後に処理を入れることができます。データの準備や環境のクリーンアップなどに使います」
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
var should = require("chai").should(); var fizzbuzz = require("./fizzbuzz.js") before(function(done) { console.log("before"); done(); }); beforeEach(function(done) { console.log("beforeEach"); done(); }); after(function(done) { console.log("after"); done(); }); afterEach(function(done) { console.log("afterEach"); done(); }); describe("test", function() { // snip }); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
$ mocha fizzbuzztest.js before test beforeEach √ pass 1, expect 1 afterEach beforeEach √ pass 3, expect ファイトだよっ! afterEach beforeEach √ pass 5, expect ちゅんちゅん afterEach beforeEach √ pass 15, expect ラブアローシュート! afterEach after 4 passing (64ms) |
海未「実行結果を見れば分かる通りですが、before
とafter
は最初と最後に1回、beforeEach
とafterEach
は各テストケースの前後に実行されます」
海未「Node.jsについては、知っておくべきはこんなところでしょうか」
穂乃果「中締め?」
海未「そうですね。これからExpressなどに手を付けるとかなり長丁場になってしまいますし」
穂乃果「まあ、何かネタがあればまた集まればいいよね」
ことり「なんか当初の目的が」
海未「気にしてはいけません」
穂乃果「では再び中締めということで。お相手は高坂穂乃果とっ!」
ことり「南ことりと♪」
海未「園田海未でした♡」
3人「「「まったねーっ!!」」」