自動テストはすぐに辻褄が合わなくなってしまい、メンテナンスするのが大変だ。従って企業もテストを自動化したがらない、とDale Emery氏は言う。氏は、最近公開したペーパーにテスト自動化に関わる共通の問題を回避するための実践的な方法を記している。これは、典型的な自動化コードから始めて、より強力でメンテナンスしやすいコードに育てていく方法だ。
氏のペーパーの根底にある発想は、テスト自動化はソフトウエア開発だ、ということだ。この発想はシンプルでとても現実化しやすい。Dale Emery氏はこの発想をElisabeth Hendrickson氏から教え込まれた。
ほとんどのソフトウエアにとってメンテナンスは、初期開発以上にコストがかかるものだ。しかも、そのコストはコードの生存期間全般にわたる。テスト自動化の分野では、レコード/プレイバックスクリプトがこの傾向に拍車をかける。これらのスクリプトは作成しやすいが、メンテナンスしにくくなる傾向がある。
Dale氏は、自動化スクリプトをメンテナンスしやすくするには2つの要因に対処する必要がある、と強く主張している。それはすなわち、付随的細部とコードの重複だ。
付随的細部とはテスト実行に不可欠だがテストの本質的な部分ではない、あらゆる'もの'のことだ。例えば、変数割り当て、ループ、低レベルルーチンの呼び出し、ボタンクリックの自動化、さらにはスクリプト言語自体のシンタックスがこれに含まれる。これらは不可欠であり、'どのように'テストコードが動作するのかを現している。しかし、同時にコードが本当は'何'をしようとしているのかを理解しづらくしている。
コードの重複とは、字義通りコードが何回も現われることだ。これがメンテナンス可能性の敵なのはよく知られている。システムを変更したら、重複コードをすべて修正しなければならないかもしれない。これはレコード/プレイバック方式の自動化テストの主要な問題点のひとつだ。テストスクリプトはあっという間に重複コードだらけになってしまう。
自身の考えを具体化するため、Dale氏はサンプルコードを提供している。このコードはアカウント作成処理をテストするテストコードだ。このテストコードは現実的で正確だが、多くの付随的細部と重複を含んでいる。段階的にリファクタリングすることで、氏はコードから付随的細部を隠し、重複を除去している。結果、コードのメンテナンス性は明らかに向上した。さらに各テストが何を検証しようとしているのかがより明確になった。テストツールやその他の文脈を理解していなくても、下記のコードが失敗した場合、どのようなシステム要求が満たされなかったのか理解することができるだろう。
Rejects Password ${aPasswordWithNoLetters}
1997年、Los Altos Workshop on Software Testing (LAWST)というソフトウエアテストのプロフェッショナルの集まりで、テスト自動化の当時の状況に関して同じような問題が発見されている。Cem Kaner氏がこの集まりでの議論の結果を文書化し、Quality Week '97で発表した。自動テストスイートのメンテナンス性改善と題されたこのペーパーで、氏は下記のように述べている。
最も一般的なテストケース作成方法は、テスト自動化ツールのキャプチャ機能を使うことです。しかし、これはとてもばかばかしい...。プログラムのUIをほんの少しだけ変更しただけで、テストスクリプトが使えなくなってしまうのです。このテスト方法のメンテナンスにかかるコストは受け入れられません。
下記の3つはよりメンテナンスしやすいテストコードを書くためのLAWSTの提言だ。
テスト自動化の開発はソフトウエア開発であることを認識すること。
他の人はともかく、テスターは次のことを理解しなければならない。すなわち、素早くて汚い設計や実装を行うより、ソフトウエア開発の原則的手法に従うことが重要であるということ。原則に従わなければ、これまでテストしてきた多くのアプリケーションと同様、悲惨な失敗をおかしてしまうだろう。
データ駆動設計を使うこと。
多くのテストケースのロジックは同じになる。しかし、それらのロジックひとつひとつには様々な入力を与えて対応する期待値を出力するかどうか、テストする必要がある。この場合、与える入力や期待値をテストロジックから分離することで重複を排除できる。こうしておけば、例えば、ユーザーインターフェイスを変更したときでも、基底にあるテストコードの単一の箇所を修正すれば、多くのテストケースを修正することができる。
フレームワークベースの設計を使うこと。
この場合のフレームワークは、共有ライブラリを提供する。そして、このライブラリのファンクションが、テストスクリプトとテスト対象のアプリケーションを分離する。テストスクリプトの作者はこれらのファンクションを、テストツールのプログラミング言語のコマンドであるかのように扱う。こうすることでスクリプトの作成者はソフトウエアのユーザーインターフェイスに依存せずにスクリプトを作成できる。
実装の汚らしい詳細を抽象化すること。これは良いプログラミングの実践のひとつに過ぎない。また、この考えを押し進めるとサブルーチンの発想までさかのぼってしまう。しかし、インターフェイスに基づくオブジェクト指向学派の思潮はこの実践の利益について長年にわたって説教を続けてきた。
よく設計されたフレームワークの上にデータ駆動的手法のテストコードを書くことで、メンテナンスにかかるコストを大きく減らすことができる。真の問題はどうやってそれを実現するかだ。Dale氏のペーパーには答えが書いてある。つまり、上に挙げたような特性が見えるようになるまで、既存のコードを何度もリファクタリングすること。テスト自動化をソフトウエア開発として考えれば、このやり方は理にかなっている。
テスト自動化に関するあなたの経験はどうだろうか。メンテナンス可能性に問題を抱えたことはないだろうか。その問題を克服するために試した手法はどんなものだろうか。結果はどうなったか。コメントすることで、であなたの経験をコミュニティで共有するといいだろう。