Seiichi Yonezawa — How creativity is helped by failure

開発日記 #63

Node.js(JavaScript)関連のテスト界隈は本当に驚くことばかりです。今回は簡単にこれまでの内容をまとめてみようと思います。

まず背景に、GitLabを使いだしてからRailsのSystem testをサポートすることを知ってから、今までおろそかにしていた統合テストに対する興味が湧いてきました。統合テストは単体テストを発展させた内容で、例えば個々のクラスに対して行うテストではなく、ブログの場合は新規投稿ページに遷移、フォーム入力・送信、リダイレクトしてブログの投稿ページへリダイレクト、投稿ページに入力した内容が表示されているかというステップを経てようやくひとつのテストが成功します。

統合テストは実際に出力されたHTMLだけではなく、JavaScriptが絡んでくるので、操作にかかわるJavaScriptが構文エラーしていた場合、単体テストでは検知できませんが統合テストでは検知できると思います。これも正しく処理を把握できていなければ、テストを書いてるだけというケースもあり得るのですが、コアとなる機能には必要かと思います。毎回目視で確認するわけにもいきませんもんね。

Railsで書いた場合は大抵単体テストだけでも問題なかったりするのですが、JavaScriptのライブラリを書いている場合は単体テストだけだと不安です。というのも、ブラウザにはDOMという概念があるので、JavaScriptのクラスだけで完結していても、ひょっとしたらDOMの内容によっては失敗するかもしれない。さて、私はここでJavaScriptのテストフレームワークを選択する必要があったのですが、QUnitはコマンドラインで実行する方法を見つけられなかったので、Mochaを選択しました。

Mochaは柔軟に設計されているので、ブラウザやNode.jsといった環境を選びません。しかし、CIで実行したり、コマンドラインで確認するにはやはりNode.jsをうまく取り入れる必要があります。そこで問題になってくるのが先ほど出てきたDOMです。DOMそのものはw3で定義されているのですが、やはりGoogle ChromeやMozilla Firefox等で違いが出てくるかもしれません。特に最新のブラウザのAPIとかを使おうと思ったらその障壁にぶつかります。まあ、現状私の予定ではまだそこまで大規模なライブラリは書いていませんが、今後そういった可能性も出てくるでしょう。

話が逸れてしまっていたので戻しますと、DOMという概念をうまくテストで実行させるにはヘッドレスブラウザでhtmlに書いたテストを実行させる、あるいはテストにDOMのモックを取り入れることでしょうか。私はこれまでCapybaraのSeleniumから始まり、Poltergeistを経てPhantom.jsに辿りつき、そこからNightmareというテストフレームワークを知りました。Nightmareはかなり柔軟に思えるのですが、いざテストを実行してみようと思うと、毎回nightmare.goto()等のAPIを記述していくとなると、これは単体テストのような感覚では実行できません。

もともとライブラリを書いてみたものの、私が必要としていたのは単体テストで、抽象度の高い統合テストも後々必要になるとは思いますが、一通りNightmareでテストを書き始めてみてこれを単体テストに使うのはかなり遠回りしているなと感じました。統合テストではそのほかにもTestCafeというフレームワークがあるみたいで、Nightmare単体ではfile://でURLを直接指定するよりかはよいかもしれません。

というわけで、最終的には一連のテストを調べたのが現時点ではやりたいこととは異なっていましたが、テストひとつ実行するにもなかなか目的のものを到達するのは大変だなと思いました。かといってテストを書かないでいるのは一人で開発していてももったいない感じもします。Nightmareなどのテストはある種Webサーバが開通しているかどうかも調べられるので、ステージング環境のテスト等に使ってみようかなとも思っています。