自動比較とは
比較というと、地味だという印象を受ける人がいるかもしれませんね。
テスト自動化でまず話題になるのは、第3章で述べられているテストスクリプトです。Selenium[1]を使ってWebアプリケーションのテストをしている人にとっては、比較はテストスクリプトの一部になっており、あまり意識しないかもしれません。JUnit[2]のassert
で簡単に自動比較ができるからです。
しかし、原著が刊行された1999年当時、比較を自動化するというのは、テスト実行の自動化と同等かそれ以上に考えなければならない部分でした。そして、刊行から15年以上経った現在でも、これらのようなツールの恩恵を受けられない場合があります。そのような場合も踏まえながら、本稿では比較の自動化とそれにまつわるお話をしていきたいと思います。
テストの実行と比較
テストの検証というのは「ソフトウェアの出力が正しいかどうかを確認するプロセスである」と、本書では述べられています。確認というのは、テスト実行の後に、実行結果と期待結果を比較することです。言い換えると、自動テストには、
- テストケースをテスト対象に対して実行する
- 実行結果と期待結果を比較する
という2つの自動化があるということです。本書では前者を第3章、後者を第4章で解説しています(図1)。
別の観点から比較の話をしてみましょう。テストケースの実行後、実行結果と期待結果を比較しますと、比較が失敗(NG)することがあります。
「しめた、バグを見つけた!」と判断するのは少し待ってください。このとき、以下のようなことが想定されます。
- テスト対象のバグにより、実行結果が期待結果と違った(バグを見つけた!)
- テストケースにバグがある(テスト設計にバグがある)
- テストスクリプトにバグがある(テストスクリプトの論理的な誤りやシンタックスの誤り)
- 比較対象である期待結果が間違っていた(比較するものが間違っていた)
- 比較の誤差、判定の誤りなどの、比較そのものが間違っていた(比較の仕組み、アルゴリズム、精度の問題、判定方法、判定基準の問題)
- 実行結果が用意できていないのに比較をした(比較するタイミングが外れている)
このように、比較が失敗したとき、それがテスト対象プログラムのバグである確率は6分の1なのです。あとはテスト側の問題で、そのうち半分(4、5、6)は比較に関わるものです。
こう考えると、テストを実行するスクリプトを考えるのも大事ですが、「比較の自動化をどう実現するか」を考えることも重要であることがお分かりになる思います。これがなかなか奥深く、本書でも自動比較が一番長い章になっています。
それでは比較の自動化について考えてみましょう。
動的比較と実行後比較
比較には「動的比較」と「実行後比較」の2種類があります。
動的比較は、テスト実行直後に比較する方法です。一方、実行後比較は、実行結果をファイルなどに保存しておき、後でじっくり期待結果と比較するという方法です。原著が刊行された当時はコンピュータが貧弱で、比較によるリソースの消費がばかになりませんでした。そのため、比較によるリソースの消費が、テストの実行自身に影響することが懸念される場合には、実行後比較を用いていました。
現在では、コンピュータリソースがずっと潤沢になりました。Selenium(IDEおよびWebDriver)をはじめとするOSSのテスト自動化ツールは、動的比較を用いるものがほとんどです。
GUIでの比較を自動化するキャプチャーリプレイ
20年以上前、コンピュータのユーザーインタフェースはキャラクタ端末(つまりCUI)が主流でした。CUIでは文字列を読み書きできればよいので、コンピュータにユーザ操作をシミュレートさせることが容易でした。また、実行結果はキャラクタなので、比較も単純な処理で行うことができました。
ところが、Windows 95が登場して以降、GUIを使うソフトウェアが爆発的に増えました。GUIでは、ユーザ操作(テストデータやボタンイベントの入力など)のシミュレーションが難しく、実行結果を取り出して比較する処理も複雑になります。
そこで考え出されたのが、「キャプチャーリプレイ」です。キャプチャーリプレイでは、マウス操作やキーボード入力を丸ごと記録(キャプチャー)しておき、テスト時にはそれを再生(リプレイ)することで、GUI上でのユーザ操作をシミュレートします。リプレイによって得た実行結果はビットマップデータとして取り出し、あらかじめ記録しておいたビットマップデータ(期待結果)と比較したり、画像認識で比較し、動的比較を行います。
キャプチャーリプレイは画期的なテスト自動化機能として、まず商用ツールベンダーがサポートしました。その後、OSSでもキャプチャーリプレイ機能を持つものが現れました。
キャプチャーリプレイが抱えていた課題
しかし、キャプチャーリプレイにはいろいろな問題がありました。今回のテーマである比較の観点から述べれば、「保守性」と「比較精度」に問題があります。次バージョンで行うテストで再利用しようとしても、GUIに変更があったらそれはできません。キャプチャーと期待結果を取り直すことになりますが、それにかかるコスト(保守コスト)はばかになりません。
保守コストは、自動化によるテストの効率化を阻むものの1つです。キャプチャーリプレイはこの保守性おいて不利です。また、ウインドウの拡大/縮小や縦横比の変更、画面の解像度の変更が行われた場合にも、期待結果を新規に用意する必要が出てきます。画像認識においても、誤認識を起こさないように精度を高めていくと、システムへの負荷や処理時間が過大になる恐れがあります。
解決のカギは実行結果と期待結果の抽象度
解決のカギは「実行結果と期待結果を適切に抽象化すること」にあります。
たとえば、「あるフィールドに1234.54
という数字が実行結果として表示されていることを確かめたい」というテストの要求があったとします。その要求の目的は何でしょう。1234.54
という文字列が期待した場所に正しく表示されていることを、ビット(ピクセル)単位で図形的に確認することでしょうか。それとも、「1234.54」という値が出力されていることを確認することのでしょうか。
比較すべきことは、テストの目的によって大きく変わります。出力の値を確かめることが目的なのに、表示されたビットマップまで比較していては、効率や精度が下がりますし、コストも時間もかかります。自動化の目的は、効率を高めつつコストを下げることです。そのためには、テストの目的に適った抽象度の情報を入出力できなければならないのです。