Webアプリケーションのテストを書くときに考えていること

テストを書く目的

自分の書いたコードが意図した通りに動いてるか確認するために書くのですが、自分が楽をするためと他の人のために書いてます。

自分が楽するため
  • Webアプリの場合、実装した機能がちゃんと動作するかを確認するために何度もブラウザポチポチしてというのは時間がかかります。なのでその回数をなるべく減らすためにテストとして書けるところはなるべくテストで確認して、ブラウザポチポチする回数を必要最低限にしたいと思っています。
  • ブラウザポチポチするのも立派なテストだと思っています。再現性のない。
他の人のため
  • テストがないと他の人がその機能に関連する機能を変更しようとした時に変更の影響がないのか確認することが出来ず、その機能に対するテストを手動で行わせてしまうことになってしまいます。

テスト書く時間がない問題

  • テストの話をすると書く時間がないと言われたりしますが、既存の開発の流れにテスト書くことをプラスするのではなくブラウザポチポチをテストを書くことで自動化して置き換えることでむしろ開発の時間を短くすることが出来るんじゃないかという実感。

シンプルな設計

  • またテストを書きながら開発することで、実装もテストの書きやすいシンプルな形にする必要があるのでその点もメリットかなと思っています。

機能の実装とテストを書く順番

  • 実装したい機能についての設計をざっくりやります。
  • 必要そうなI/Fを空で実装します。
    • 他と連携させた時にこのI/Fで問題無さそうか確認します。
  • 機能に対するテストケースをざっくり書きます。
    • ここでは実際にテストを書かずにケースだけ書きます。
    • 出力結果がわかりやすいように、class > method みたいな感じで階層化して書いています。
describe "User", ->
  describe "greet", ->
    it "xxxxの場合はyyyyになる", ->
    it "zzzzの場合は例外を投げる", ->

  • テストと機能に対する実装を交互にやっていきます。
    • テストコードを先に書くか、機能の実装を先に書くかはその時次第でやってます...
    • 先に書くか後に書くかよりも機能の実装をテストで確認しながらやることが重要だと思っているので(TDDでできれば素晴らしいと思いますが...)
  • テストが通れば、ブラウザなどで実際に動作するか確認します。

テストする範囲を意識する

  • モックなどを有効に使って、テストを書く対象に対するテストだけを書いていくのが重要だと思っています。
  • そうしないとテストを書くのが難しくなったりテストが増えてくるので...。

サーバーサイドのテスト

  • 基本的には全てのpublicメソッドのテストを書くようにと考えています。モデルだけなくWebのHTTP Responseを返すところも。
  • HTTP Responseを返すところなどはPerlの場合はPlack::Testを使うと簡単に書くことが出来ますし、外部APIを叩いているところはMockを使ってテストを書いています。
    • 外部のAPIの仕様が変わってないかどうかについては別途それ用のテストがあるといいのかなぁとは思ってます。
  • サーバー側でテンプレートエンジンによってHTMLを返す場合は、stashなりrenderメソッドに渡される値までのテストでいいかなと思ってます。
  • モックについてはモック用のライブラリがあればそれを使って、なければTest::Mock::Objectを使ったり、局所的に強引にメソッド上書きしたりでテスト書いてます。
no warnings qw/redefine/;
local *Hoge::Foo::method = sub {
    ....
};

JavaScriptのテスト

  • jQueryでベタに書かれていると結構面倒ですが、テストを書こうという規模の場合、最近だとなんらかのフレームワークを使っていると思いますし、その場合はテストを書くのは難しくないかなと思います。
  • レンダリング結果についてもテストを書くことは出来ますが、最終的にブラウザで確認する必要があるところなどはテスト書かなくてもいいかなと思っています。
    • コストに見合わなかったり、デザイン変更の度にテストを修正するのは辛い場合があるので。
    • なのでなるべくDOMを触る部分は独立させて他の部分のテストを書きやすい構成にすることは大切だと思います。
  • JavaScriptのテストについてはここにあるような構成でやってます。
  • mochaだと非同期のテストも簡単に書けますし、sinon.jsを使うとspyやstubがものすごく簡単に出来ます。
  • JavaScriptのテストは難しいと言われてましたが、ライブラリが整っているので今だとむしろ書きやすいかなと思います。特にsinon.js。
  • JasmineやMochaでテストを書いてみて、BDDな感じでitに仕様を書いてexpectでその確認をする形がとても見やすくていいなと思ったので、他の言語で書くときもそんな感じで書こうと思いました。
  • Backbone(Marionette)でのテストのサンプル

テストとドキュメント

  • mochaとか使って、describeの説明を丁寧に書くとテスト結果がドキュメントみたいになってとてもいい感じになるし、テストケース==ドキュメントというアプローチは無駄がないしメンテしやすいしとてもいいなぁと思っています。
  • autodocみたいなアプローチも面白いですね


TDDについてはこちらのt_wadaさんの説明が素晴らし過ぎるのでオススメです!
https://codeiq.jp/magazine/2013/11/1475/


テストというとなんだか意識高い感じがしますが、自分が怠ける(楽する)ために書くことから始めてみるといいんじゃないかと思います。