Born Too Late

Yuya's old tech blog.

JavaScript の spec を RSpec で書く

2011-03-06 17:33:18

Ruby 以外のプログラムを書いていると, 「RSpec で spec が書けない」というだけの理由で, 億劫になってしまうことがあります.
RSpec で JavaScript の spec が書ければ... そう思って, やってみました.

まずは実際のコードを説明なしに紹介し, 環境構築手順や, 解説については後述します.

テスト対象 (System Under Test)

今回はこの JavaScript のコードを対象に, spec を書いてみます.

とりあえずは「RSpec で JavaScript の spec が書けるのか」という検証が目的なので, シンプルなもので十分でしょう.
t-wada さんのRSpec の入門とその一歩先へをそのまま JavaScript にしてみたようなものです.

detect メソッドに渡す文字列の中に, コンストラクタに渡された単語が含まれるか, を検証するだけの簡単なオブジェクトです.

$ js
Rhino 1.7 release 2 2010 09 15
js> load("message_filter.js")
js> var filter = new MessageFilter("foo");
js> filter.detect("foo bar baz");
true
js> filter.detect("Hello, World!");
false

spec

上記のコードをテストするための spec です.

MessageFilter というクラスは Ruby 上で定義されているわけではないので, ここでは Symbol 型を利用しています.

これを実行すると, 以下のようになります.

$ rspec -fs message_filter_spec.rb 

MessageFilter with argument "foo"
  should detect from "foo bar baz"
  should detect from "Hello World!"

Finished in 0.40217 seconds
2 examples, 0 failures

一応の動作は確認できましたね.

環境の構築

今回は以下のような環境を使用しています.
OS は Ubuntu 10.10 です.

$ ruby -v
ruby 1.8.7 (2011-02-18 patchlevel 334) [i686-linux]
$ rspec -v
2.5.1
$ gem list # 一部省略

*** LOCAL GEMS ***

harmony (0.5.6)
johnson (2.0.0.pre3)
rspec (2.5.0)
rspec-core (2.5.1)
stackdeck (0.2.0)

普段は Ruby 1.9.2 を使用しているのですが, 今回使用する harmony という gem の依存ライブラリである johnson が, 1.9.x ではインストールできないようなので, 1.8.7 を使用しています.
RVM を利用して複数の Ruby 環境を切り替えられる環境であれば, さほど問題は無いでしょう.

以下のようにインストールします. (Ruby, RVM のインストールは省略)

$ gem install stackdeck
$ gem install johnson -v "2.0.0.pre3"
$ gem install harmony
$ gem install rspec

harmony のインストール時には, 依存ライブラリである stackdeck と johnson も一緒にインストールされるべきですが, 現在は問題があってうまくできないようです.
とりあえず手動でインストールしておけば問題ありません.

どういう仕組みで動いているのか

Johnson が Ruby 上での JavaScript (SpiderMonkey) の実行環境を提供し, Harmony はそれをラップした DSL, とのことです.

Harmony::Page オブジェクトが .js ファイルを読み込んだコンテキストを保持し. x メソッド (execute_js メソッドのエイリアス) でプログラムを実行することができます.
x メソッドで実行した JavaScript プログラム中, 最後に評価された値が返り値として Ruby に渡されます.
(ただし, オブジェクトは返らないらしい)

問題点

上記の理由から, 実際に運用・保守していくのは難しいでしょう.

最近は HTML5 によるスマートフォンアプリ作りに挑戦しようとしているのですが, TDD/BDD のフレームワークに何を使うべきか, で迷っています.
今のところは次作の簡単なフレームワークで検証していますが, さすがにずっと運用するわけにはいかないので, デファクトスタンダードなものが知りたいところです.
いいのを知っている方は是非 @yuya_takeyama まで教えてください.

JavaScript におけるテスト技法については, 2011/03/08 (Tue) に Test.js というイベントでおもしろい話が聞けそうです.
是非参加したいところですが, ATND への参加登録が遅くなったので絶望的な状態です...
この記事を LT する発表者としての参加, なんてのはダメですよねぇ...
Ust で我慢します.