プログラマでありたい

おっさんになっても、プログラマでありつづけたい

Web画面の自動テストの導入に失敗する理由とその対策


 皆さん、自動テストしていますか?体感的には、ユニットテストは当たり前のように開発工程に組み込まれるようになってきているのではと思います。一方で、どこの部分を対象にしているかというと、モデルであったりコントローラであったりと機能単体のテストです。品質をつくり上げるには、まず単体での精度を上げることです。ですので、ユニットテストで品質を保証するのは正しい。圧倒的に正しいです。
 一方で、最近ではサポート対象のブラウザやバージョンが増えたり、JavaScriptの第二の全盛期であったり、IEが未だ消えてなくならなかったりと、個々のブラウザでテストすることの重要性が増しています。じゃぁWeb画面も自動的にテストすればええやん、Seleniumもあるしとなると思います。ただ導入しようとすると、7〜8割方失敗するのですよ。これが。


 理由としては、これに尽きます

Seleniumのテストと、本体のソースの乖離がすぐ出て、テストが腐る。

テストが腐る理由



 何故このような事態になるのでしょうか?Webの画面の変化が激しいとか、環境構築面で面倒くさいとか色々ありますが、結論としてはSelenium IDEが優秀過ぎるから。Seleniumでテストしろと言われたら、恐らくWebで使い方みてSelenium IDEでピコピコとテストケースを作ると思います。まずこれが間違いの始まり。これは、現在の画面の現在のデータに対してテストを作っているだけです。ご存知のようにフロント側の画面はすぐ変わりますし、データなんかもっと変わります。画面やデータが変わるごとにSeleniumのテストケースを作りなおすのですか?このやり方ではテストが腐るのは当たり前です。またSelenium IDEで作ったら、何となくソースコード管理されないことが多いように思われます。

テストコードの扱い方



 テストの本質に立ち返ると、テストは機能が要件に満たしていることを最小限の動作で確認することです。画面のテストも同じです。本番同等のデータを用意して全部を確認するのは、理想的に見えるかもしれませんが現実的ではありません。(もっと言うと理想でもありません。)
 では、役に立つ画面の自動テストを作るのはどうしたら良いのでしょうか?結論から言うと、他のユニットテストと同じように扱うことです。至極当然のことのようですが、これに尽きます。
 例えばモデル層のユニットテスト。これだけを別のプロジェクトとして違うリポジトリで管理しますか?あるいはソース管理しないということがありますか?恐らくないでしょう。Seleniumのテストコードも同じようにプロジェクトの一つとして管理しましょう。また、モデル層のユニットテストする為に、事前に全データをローディングしますか?しませんね。必要なデータだけをその場で生成して、テストしますよね。画面の自動テストも同じです。また、ユニットテストを実行する為に、わざわざ別のツールを立ちあげる必要があるのは面倒臭いですよね。画面の自動テストでも同じです。

テストコードの扱い方



 まとめると、次の3点になります。

  • Seleniumのテストコードを本体のソースと一緒のリポジトリで管理する
  • Selenium用のデータをいれたDBを用意しない。テストの都度、コードで最小限のデータ生成する

 ⇒Fixtureより、Factoryパターン

  • Seleniumのテストの実施を、他のユニットテスト同様のコマンドで実行出来るようにする。

 ⇒画面のテストだけ、ブラウザ立ちあげてSelenium IDEから実行するといったやり方はしない


 つまり画面の自動テストも、ユニットテストとして扱えということですね。
個々のプラクティスだと、Selenium WebDriver使えよとかJekinsと統合しろよというのはありますが、まずは上の3つのことを意識することかと思います。
 そして、テストコードのメンテナンスをプロセスとして必ず組み入れてください。そこまでいけば大丈夫です。


2013/3/5 実践編を書きました。
JenkinsとSelenium WebDriverでUI層のテストも自動化&永続化する


See Also:
Selenium2.0 WebDriverで複数ブラウザのUIテスト もう一度、Selenium再入門
JenkinsとSelenium WebDriverでUI層のテストも自動化&永続化する
ユニットテストのデータ生成は、FixtureよりFactoryモデル