愛と勇気と缶ビール

ふしぎとぼくらはなにをしたらよいか

JavaScriptのテストについて本気出して考えてみた(1)

一週間のうちまる一日くらいは、「あーあのJavaScriptコードのテストってどうするのがいいかしら?」と考えている。

嘘です。多分45分くらい。

考えている時間の長さはどうでもいいんだけど、JavaScriptのテストは場合によっては中々ややこしい問題に成り得る。DOMなどの外部リソースにタッチすることのない「純JavaScript(オレオレ用語です)」であればブラウザ上であろうとRhino上であろうとNode JS上であろうと(理論上は)テストを動かせるのだが…。

JavaScriptであろうとなかろうと、外部のリソースに依存している(外部のリソースを操作する)コードはそうでないコードよりテストが面倒になる。ファイルR/WやDBの操作などIO系は勿論そうだし、どこかのサーバに何かしらのプロトコルで話しかけるようなコードもしかり。


JSのテストがややこしくなるのは、JavaScriptのコード、特にアプリケーションレイヤのコードはほとんどの場合

  1. DOM操作
  2. xhrによる外部httpリソースの操作
  3. あるいはそれら両方(いわゆるAjax)

のいずれかを含んでいるからである。こいつらを一体どのように扱うか、というのがJavaScriptのテストの自動化の焦点なんである。

DOM/xhrとの闘い

つい昨今まで、DOM/xhrがあるが故にJavaScriptのテストはブラウザ上でしか行えないものだった。現代では、DOM/xhrの操作を行うようなコードのテストに関しては主に2種類のアプローチがある。

  1. 真っ正直にブラウザでテストをかます。
  2. DOM/xhrを頑張ってエミュレートする。
実ブラウザ自動化の戦略

1. は当たり前っちゃ当たり前なんだが、自動化がしづらい。Test Suite的なページを一つ一つ開いていくなんてやってらんない。自動化されてないテストというのは面倒なので、足が遠のく。足が遠のくと通らないテストが増える。通らないテストが増えるとますます足が遠のく。負のスパイラルである。

というものの本物のブラウザ、本物の環境でのテストにはやっぱり信頼性があるので、実行環境でまちまちな動作をすることで有名な言語であるJavaScript的にはサポートするつもりのある全てのブラウザで回帰テストを行うのが理想的である。あくまで、理想的には。(この辺は後述)

とはいえやっぱりブラウザポチポチはやってらんないので、モノホンのブラウザを使いつつ自動化したい!と思うのが人の情である。このような試みには

  1. JsTestDriver (http://code.google.com/p/js-test-driver/)
  2. JSTAPd (http://search.cpan.org/~yappo/JSTAPd-0.01/lib/JSTAPd/Tutorial/JA.pod)
  3. TestSwarm (https://github.com/jeresig/testswarm/wiki)

などがある。前者2つはちょっと触ってみたことがあるが、どっちもCUI/GUIからテストの自動実行が可能であり、ブラウザにpushあるいはcometなどの擬似pushを行うことでブラウザ外部からのテスト実行/自動化を実現している。TestSwarmは「今の環境に導入するのはあまりにも大袈裟すぎるな」と思って試してないのだが、図を見る限りおそらく類似したアーキテクチャではないかと思う。

上に挙げた三つのツールはそれぞれ特徴があり一緒くたに語れるものではないが、「やっぱ実際のブラウザでテストしたいよね、そんでもってやっぱ自動化できないとやだよね」という発想に基づいている。手前味噌ではあるが、僕が昔かいたTest::QUnitとかいうPerlからmozrepl経由で自動的にQUnitのテストを実行するモジュール(ただしFirefoxのみ)も同じ発想である。

なんでここでSeleniumが出てこないんだよ!と思う人はけっこういるかもしれないが、僕はSeleniumがあんまし好きになれないから、というだけの理由である。いや嫌いではないんだけど、好きでもない、なんでだろ。プログラマブルでないからかしら。わかりません。



(長くなりそうなのでつづく)