yaakaito.org

小さいCoffeeScriptのテストにはVowsが便利

CoffeeScript, Node.js, Testing, Vows

こんにちは!うきょーです! 小さめのツールをCoffeeScriptで書く機会があったのですが、 テストに使ったVows(日本語訳)というのが結構良かったです。 一言で言えば、BDDライクで非同期テストに強く、Coffeeと相性のよい、topicという独特の概念をもったフレームワークです。(長い)

Vowsのセットアップと実行

npm経由でインストールします。

1
2
npm install vows
npm install -g vows

設定ファイルとかは特に必要なく、直接テストファイルを実行します。

1
vows test.js

CoffeeScriptをそのまま実行することができます。ここが重要

1
vows test.coffee --spec

--specオプションを付けるといい感じの出力になります。

Vowsのテストケース

簡単な例として文字列を反転するreverseというモジュールを考えたときのテストはこんな感じ。 特にCoffeeScriptで書くことにメリットを感じるので、サンプルは全部CoffeeScriptです。

1
2
3
4
5
6
7
8
9
10
11
12
vows    = require 'vows'
assert  = require 'assert'
reverse = require 'reverse'

vows
  .describe('reverse')
  .addBatch
    'example' :
      topic : ->
        reverse('abc')
      'should return cba' : (str) ->
        assert.equal str, 'cba'

describeを定義して、addBatchでテストのまとまりを追加します。 ポイントはさっきからちょっと出てきているtopicで、これの実行結果がその下のテストケースへ渡ってきます。 この中は非同期でもokみたいで(今回は試していないけど)、topicの実行が終わったタイミングでテストが走る、という仕組みみたいです。便利ですね。 topicを使っていくとどうしてもモジュールを小さくせざるをえないので、きれいなコードを書くのにはよいと思います。

topicとかテストケースはネストすることもできて、例えばabcの他にdefgもテストしたい!とかって場合は、

1
2
3
4
5
6
7
8
9
10
11
.addBatch
  'example2' :
    topic : reverse
    'when abc' :
      topic : (f) -> f('abc')
      'should return cba' : (str) ->
        assert.equal str, 'cba'
    'when abc' :
      topic : (f) -> f('defg')
      'should return gfed' : (str) ->
        assert.equal str, 'gfed'

こういう感じで書くこともできます、一つ上のtopicは次のtopicに渡っていくので、テストするスコープを制限することができます。 ただ、ネストしすぎるとちょっと読みにくいですね。

まとめ

個人的には、今回みたいにNodeを使って小さいコマンドラインツールとかを全部Coffeeで書くときに使うのがよいかなーという印象でした。 クライアントサイドのテストとかになってくると、長い目で見たときにBusterJSやその他Swarm系使った方がよさそうな印象。 大きめのプロジェクトになってくると、テストケースが要はでかいオブジェクトの定義なので、どうもしんどくなっていく気がする。

テストの為の中間ファイルとして.jsを吐く必要がないので、リポジトリがCoffeeScriptだけできれいに保てるのもポイント。 vowsでカバーできるサイズなら全部CoffeeScriptで書いてしまっても、それなりにモチベーションが保てる。(CoffeeScriptそんなに好きじゃない)