先日のJEITAのイベントで、メタモルフィックテスティング(Metamorphic Testing、MT)というものを知り、「誰かMetamorphic Testingの勉強会やりませんか?」とブログに書いたところ、ソフトウェアテスト・ヒストリアンの辰巳さんが資料をたくさん紹介してくださいました。ちなみに、一緒に勉強してくれる人は誰もいませんでした。
その後、自分でいくつかMetamorphic Testingに関する資料を集めましたので必要なら声をかけてください。また、ICSE 2017併設Workshopで
— Keizo Tatsumi (@KeizoTatsumi) 2017年12月20日
MET: 2nd International Workshop on Metamorphic Testinghttps://t.co/Lrb54PufzU
が開催されています。基調講演slidesがダウンロードできます。
ICSE MET'2017のサイトにも、MTについてのスライドがたくさん掲載されていたので、学んだところを紹介してみたいと思います。
日本語の論文も無償で見られるものがいくつかあるのですが、どちらかといえばMTについての知識は前提として、それを機械学習にも応用してみたという内容なので、基本を学ぶには敷居が高そうです(論文だから当たり前か・・・)。
メタモルフィックテスティングの概要
まず、Chris Murphy氏の『Applications of Metamorphic Testing』(ppt)が一番わかりやすいです。スライド終盤のサマリには、以下のようにあります。
一つずつ、見ていきましょう。
なぜテストケースを増やす必要があるのか。
「新しいテストケースを生成する」理由は何でしょう。
境界値分析や組み合わせテストといったテスト技法は、テスト空間を論理的に絞り込み、効率的にテストケースを減らすための技術でした。なぜあえて、テストケースを増やすのか。
このスライドでは「だって、テストケースは多ければ多いほどいいだろう?」とあります。手動テスト中心のテスターが聞くと吐血しそうな意見ですね。
たとえばこちらのICSTの論文『Metamorphic Model-based Testing of Autonomous Systems』(pdf)では、ドローンの飛行や障害物回避のシミュレーションプログラムにMTを応用した例が載っています。ドローンの出発地点と到着地点、その経路にある障害物には無数のパターンがあるので、ある特徴的なテストケースをいくつか通すだけでなく、そこから大量のテストケースを派生させて、プログラムの妥当性を検証することが有効なのですね。
テストオラクルってなんだっけ?
テストオラクル(Test Oracle)などという用語を使うのは、I/JSTQBで学んだ界隈の人だけだと思っていましたが、MTの文脈では当然のように使われている言葉です。
ISTQB用語集に追加された日本語検索機能をさっそく使ってみましょう! 使い方は、湯本さんのnoteから!
テストオラクル(test oracle)
テスト対象のソフトウェアの実行結果と比較する期待結果のソース。オラクルは、実在する(ベンチマーク用の)システム、他のソフトウェア、ユーザマニュアル、個人の専門知識の場合があるが、コードであってはならない。
テストオラクルがないというのはつまり、「どういう出力なら正しいのか」がよくわからない状況ということですね。
メタモルフィックプロパティとは?
「メタモルフィックプロパティ」(Metamorphic Properties)とは一言でいうと、対象とするソフトウェアが備えている「性質」のことです*1。MTでは、この性質から多くのテストケースを導出することを目的としています。
それってプログラムの仕様そのもの、あるいはそれを変換した高位レベルテストケースのことでは、とも思いませんか? 一般的なテスト技法でテストケースの絞り込みを行わなければ、テストケースはいくらでも追加できそうなものです。
たとえば、「12歳以上は料金1,000円」という仕様からは、入力である年齢を12歳、13歳、14歳、・・・とし、出力が「1,000円」となることを確認するテストケースがどんどん作れます。
ですが、メタモルフィックプロパティはもっと別のものです。
わたしは、「プログラムの仕様として定義するまでもない、自明な性質」と解釈しています。
メタモルフィックプロパティの具体例
数値リストから最小値を求めるプログラム
抽象的な話になってきたので、先の資料から具体例を引用します。
整数のリストの中から最小値を得る関数 findMinを、以下のように書くとします(バグがあります)。
「2、1、4、3」というリストを入力にすると、期待値(つまり最小値)は「1」になる、というテストケースは、以下のように表現することができます。
さて、このプログラムが持つべきメタモルフィックプロパティには、どういうものが考えられるでしょうか。
それはたとえば、「リスト内の数字を並び替えても、出力値(最小値)は同じになる」という性質です。このような性質は、おそらく外部仕様として明示されない、「自明な」性質ということができるでしょう。
この性質に従ってテストケースを生成すると、
というテストケースが通らないことがわかり、バグを検出することができます。
形式的な表現をしてみると
少し形式的に表現してみましょう。
プログラムfに対する元のテストケースを {x, f(x)} と表現します。
元のテストケースの入力値を関数tに通すと、新しい入力値はt(x)、プログラムfからの出力値はf(t(x))となります。
一方、元のテストケースの出力値を関数gに通すと、新しい出力値はg(f(x)) となります。
プログラムfのメタモルフィックプロパティとは、すべての入力値xに対して、f(t(x))=g(f(x))を満たすような関数ペア(t, g)のこと。文字列だと全然わからないですね・・・。
先のfindMinの例では、関数tは「リスト要素の並び替え」に相当します。出力値の方は変わらないことを期待しているので、関数gは恒等関数になるでしょう。入力に「リスト要素の並び替え」という操作を行っても、出力値は変わらないというのが、findMinのメタモルフィックプロパティです。
一般的にはどんなプロパティがある?
一般的に、どんなメタモルフィックプロパティがあるのでしょうか。P.22からその例が書かれています。
元のテストケースが「要素a~fの総計がsになる」というものだったとして、
といったものがメタモルフィックプロパティとなります。これはだいぶ単純というか・・・数学以外には適用できそうにない、退屈な性質ですよね・・・。
もう少し違うタイプとして、以下のようなものが紹介されています。
数値計算分野以外での応用
メタモルフィックプロパティが上で紹介したようなものばかりだと、MTは数値計算関連のプログラムにしか応用できないのではと思いますが、Zhi Quan Zhouさんの講演『Metamorphic Testing: Beyond Testing Numerical Computations』(pdf)によると、数値計算関連分野での適用は全体の4%でしかないそうです*2。
この講演で紹介された適用例は、プログラム難読化ツール*3。
難読化ツールのメタモルフィックプロパティには、たとえば以下のようなものがあります。
こういったプロパティを利用して、一般的なテストでは必ずしも検出できないバグが、MTであれば検出できるという例を示しています。
また、オンライン検索での例も紹介されています。一口にオンライン検索といっても、GoogleのようなWebサイトの検索、ホテルや飛行機の空き状況、商品、用語、地図など無数にありますが、これらに共通して言えそうなメタモルフィックプロパティがあります。
まず一般的な(general)メタモルフィックプロパティとして、以下が考えられます。
この2つ目のプロパティから導出できる具体的な(concrete)プロパティは、たとえば店舗検索において、
というものが考えられます。このメタモルフィックプロパティを利用してテストケースを生成し、妥当性を確認することができます。
まとめ
引用した資料に明確に書かれているわけではないのですが、生成されるテストケースが常に「期待値付き」であることが非常に重要だと思います。いくら大量にテストケースを生成したとしても、それが期待値なしであればあまり役に立ちませんし、自動化もできません。
テスト技法といえば、テストケースを合理的に選択することと思いがちでしたが、「とにかくたくさんのテストパターンが欲しい」「でもテストオラクルがない・・・」という状況において、有効だが数が少ないテストケースから、期待値付きのテストケースを大量に派生させる技術として、メタモルフィックテスティングが有望な技術だということがわかりました。