ビジネスNEW

【連載】第5回:ソフトウェアテストそもそも話~三角形問題の歴史(後編): テストプロフェッショナルたちの解答

【連載】第5回:ソフトウェアテストそもそも話~三角形問題の歴史(後編): テストプロフェッショナルたちの解答

「HQW!」の読者の皆さん、こんにちは。辰巳敬三です。

この連載コラムでは、ソフトウェアのテスト技術や品質技術の歴史を紹介しています。

第5回の前編では、「誰が「マイヤーズの三角形問題」を作ったのか」と題して三角形問題の考案の歴史を解説しました。
後編では、三角形問題に対するテストプロフェッショナルたちの解答を紹介します。

Glenford J. Myers(以下、Myers)が著書『The Art of Software Testing(ソフトウェア・テストの技法)』[1] の冒頭で、三角形判別プログラムのテストケース作成の課題を提示したことは前編で紹介しました。

書籍では続けて、テストケースを評価するための質問リストが示されます。内容は「xxxのテストケースがあるか」という形式の13項目と、「それぞれのテストケースの予想出力を示しているか」という1項目の計14項目です。そして読者に対し、「このリストを使って質問に答えながら、あなたのテストケースを評価してみよ。"YES"と答えるごとに1点を加算せよ」と自己診断を促しています。

テストケースに関する質問13項目の中には、3つの整数値の入力順序を変えて確認するものが3項目あるので、これらを別々に数えると、Myersのチェックリストの全項目を満たすには最低15個のテストケースが必要になります。
では、三角形問題の正解は15個のテストケースなのでしょうか?「そもそも」正解はあるのでしょうか?

三角形問題の解答

前編で書いたように、三角形問題は、特定の業務知識を必要とせず、誰にでもイメージしやすいため、教育や研修の例題としてよく用いられています。

2004年に米国で開催されたソフトウェアテストワークショップLAWST[2]の中のソフトウェアテスト教育ワークショップで、米国のコンサルタントのRoss Collardは、発表資料『Exercise: Analyzing the Triangle Problem』[3] で、次のように三角形問題のテストケース数について書いています(筆者要約)。

  • Paul Jorgensenは約185件のテストケースを示している
  • 私(Ross Collard)は4件で十分だと主張できる
  • Kent Beckは彼の三角形問題の実装に対しては6件のテストケースで十分だと述べ、Bob Binderが示した65件のテストケースと比べている

そして、

4人の専門家に依頼すると、4件から185件にわたる4つの異なる答えが返ってくる。そして、4通のコンサルティング請求書が届く。
これは、まるで悪い冗談のようですね。

と続きます(笑)。
この4人のテストケースがどのようなものか見てみましょう。

Paul Jorgensen

Paul Jorgensen(以下、Jorgensen)は、著書『Software Testing: A Craftsman's Approach』[4]の第5章 Boundary value testing(境界値テスト)で三角形問題に対するテストケースの例を示しています。

書籍では、基本的な境界値分析手法が次のように説明されています(筆者要約)。

変数がn個ある場合、着目する一つの変数以外の変数を中間値(nominal value)に固定し、着目した変数の値を、min、min+、nom、max-、max(下限値、下限値+1、中間値、上限値-1、上限値)に変化させる。これを各変数について繰り返すと、4n+1件のテストケースが生成される。

さらに、故障の発生原因を単一と想定する(単一故障仮説)か、複数の組み合わせと想定するか、また、変数の値を正常値のみとするか、異常値も含めるかによって、次の4つに分けてテストケースの生成方法が示されています。

テストケース生成方法

原因の想定

変数の値

通常境界値テスト
(Normal boundary value testing)

単一

正常値のみ

堅牢境界値テスト
(Robust boundary value testing)

単一

異常値も含める

最悪ケース境界値テスト
(Worst-case boundary value testing)

複合

正常値のみ

堅牢最悪ケース境界値テスト
(Robust worst-case boundary value testing)

複合

異常値も含める

三角形問題の場合、生成されるテストケースの数は、

  • 最悪ケース:3辺の min, min+, nom, max-, max を全て組み合わせた125件(=5の3乗)
  • 堅牢最悪ケース:3辺の min-, min, min+, nom, max-, max, max+ を全て組み合わせた343件(=7の3乗)

となります。書籍では最悪ケースの125件のテストケースの表が掲載されています。
Collardは「約185件」と書いていましたが、Jorgensenが示したテストケースは125件、あるいは343件ということになります。

※筆者の蔵書を撮影

Ross Collard

Ross Collard(以下、Collard)は、前述のワークショップ発表資料[3]で、IBMなどの組織で実施された三角形問題のテストケース作成実験において、経験豊富な専門家でさえ適切な数のテストケースを挙げられなかったという結果を「嘆かわしい」と解釈することに疑問を呈しています。彼は、テストケースの「適切さ」は文脈に応じて評価されるべきであり、自身は次の4件のテストケースで十分だと主張できる、と述べています。

テストケース

入力値

期待結果

1

3, 3, 3

正三角形

2

3, 3, 2

二等辺三角形

3

3, 4, 5

不等辺三角形

4

3, 3, ?

不正値

Kent Beck

Kent Beck(以下、Beck)は、著書『Test-Driven Development By Example(テスト駆動開発)』[5]で、テストの量について次のように述べています。

どのくらいのテストを書けばよいかについて考えるとき、私は平均故障間隔(MTBF: Mean Time Between Failures)を思い浮かべる。(中略)そのテストはプログラムのMTBFに寄与するだろうか。(中略)テストを書く意味があるかどうかは、どの程度のMTBFを考えているかによる。

Beckはこの考えを示すとともに、Smalltalkを用いた三角形問題の解答(判定プログラムとテスト)を掲載し、下表に整理した6件のテストケースを示しています。

メソッド

入力値

期待結果

意味

testEquilateral

2, 2, 2

1

正三角形

testIsoceles

1, 2, 2

2

二等辺三角形

testScalene

2, 3, 4

3

不等辺三角形

testIrrational

1, 2, 3

失敗

三角形にならない

testNegative

-1, 2, 2

失敗

不正な入力(負の値)

testStrings

'a', 'b', 'c'

失敗

型エラー

※筆者の蔵書を撮影

Robert Binder

Robert Binder(以下、Binder ※前述のBobはRobertのニックネーム)は、Myersへのオマージュと言えると思いますが、著書『Testing Object-Oriented Systems: Models, Patterns, and Tools』[6]の第1章を「A Small Challenge」と題し、三角形問題から始めています。Myersが提示した課題を紹介した上で、Javaで書かれた三角形のクラスの定義(class Triangle)を示し、このクラスを適切にテストするためのテストケース作成の課題を提示しています。

Binderは解答として、まず「Myersのテストのほとんどは、依然としてclass Triangleの責務 (Responsibility) に対して適切だ」と述べ、Myersのテストケースに具体値を与えたものに、最大値の入力を確認するテストを加えた33件を基本テストケース(Basic Test Case)として提示しました。さらに、オブジェクト指向ソフトウェアに対しては「それだけでは全く不十分だ」として、オブジェクト指向特有の側面を考慮したテストとして、カプセル化(Encapsulation)と永続性(Persistence)に起因するバグに関するもの29件、継承(Inheritance)と多態性(Polymorphism)に関するもの3件を追加し、合計65件のテストケースを示しています。

※筆者の蔵書を撮影

以上、4人の三角形問題の解答を紹介しましたが、皆さんは誰の解答に最も共感しますか。
Collardは、前述の論文で次のようにまとめています(筆者訳)。

正しい答えは何でしょうか?

その答えは、「すべての状況に通用する唯一の答えは存在しない」ということです。最も適切な答えは、その文脈に依存するからです。(中略)

「正しいテストケースの集合とは何か?」という問いに対しては、その状況において認識されているリスクと、それを回避するためにどれだけの労力を割く意思があるかという観点からしか答えることはできません。(中略)言い換えれば、正しいテスト量は、リスクと経済性とのトレードオフによって決まります。もしリスクが十分に低い、あるいはテストのコストが非常に高い場合、4件の最小限のテストケースでも適切です。(中略)三角形の問題を解く前に、まず文脈を理解しておく必要があるのです。

まさに、ISTQBのシラバス[7]に書かれている「テストの原則」の一つ「テストは状況次第」ということですね。

Kent Beckにも見落としがあった!

皆さんは、三角形問題に対して幾つのテストケースを作成できたでしょうか。
Myersの当時の調査によると、高度な経験を持つ専門プログラマーでも、平均点は14点満点中たった7.8点だったそうです。

皆さんも、前編で紹介したように、Hammingの言う三角形問題の「隠れた前提」を見落とし、「よくできる学生でも(3,4,7)の組が不等辺三角形と呼ぶべきでないことを見い出して驚く(Gruenberger)」というのと同じ状況にならなかったでしょうか。
もしそうだったとしても、がっかりすることはありません。

実は、Beckでさえ同じ見落としをしていたのです。
Beckが「6件のテストケースで十分だ」と述べていることを前に紹介しましたが、この6件は、2001年12月にUSENETニュースグループ comp.lang.ruby に投稿された内容が基になっています。当初5件のテストケースが提示されたのですが、抜けがあるとの指摘を受け、1件追加して6件となったのです。

最初に示されたテストケースは次の5件です。

テストケース

入力値

期待結果

1

1,2,3

不等辺三角形

2

2,2,2

正三角形

3

1,2,2

二等辺三角形

4

不正値

失敗

5

'a', 'b', 'c'

失敗

どうでしょう。おかしなところに気付きましたか?
修正版では次の修正と追加が行われ、前述の6件のテストケースになっています。

  • テストケース-1の入力値を 2,3,4 に修正。1,2,3では三角形にならないですからね。
  • 入力値 1,2,3 をテストケース-6として追加。三角形にならない場合のテストですね。

テストプロフェッショナルたちのテストの考え方を学ぶ

ところで、ここで伝えたかったのは「Beckでさえ見落とした」ということではありません。むしろ、このcomp.lang.rubyでの一連の議論のメールを読むと、三角形問題を題材にして、TDD(テスト駆動開発)におけるユニットテストの考え方と、それに対する反論の両方が理解でき、とても興味深い(学ぶところが多い)内容であるということです。

この議論では、Kent Beckの他にも、XPの創始者の一人であるRon Jeffries、そして「Uncle Bob」ことRobert C. Martinといった、Agile Manifestoの署名者たち、さらには前述のRobert Binderも発言しています。

この一連のやり取りは、Google Groups( https://groups.google.com/ )で閲覧できます。興味のある方は、comp.lang.rubyグループで「beck triangle binder」と検索して読んでみてください。

なお、Beckは最初から5つのテストケースを示したわけではありません。TDDのプロセスに沿って、まず1つテストを書き、それが通る最小限の実装を行い、続いてテストを追加しては、それを通すために実装を拡張する――という流れで、テストコードと実装を順を追って説明しています[8]。
一連の議論を読んで、私なりに理解したことや注目したことは以下の通りです。

Beckの実装では何故6個のテストでよいのか

  • SmalltalkのSetの機能を使って実装しているので入力値の順序を入れ換えるpermutationのテストケースは不要となります(注)。Myersの13個のチェック項目の中には、permutationの確認が3項目ありました。
    (注)入力された3辺の値をSetに格納する実装になっています。Setは集合に対して重複しない項目のみを含むので、Setオブジェクトは、3辺の値が[2,3,4]の場合は(2,3,4)、[1,2,2]の場合は(1,2)、[2,2,2]の場合は(2)となります。このSetオブジェクトの項目数が三角形の種類を表すことになり、1は正三角形、2は二等辺三角形、3は不等辺三角形と定義できます。また、Setは3辺の値の入力順序に依存しないので、順序を入れ換える意味がなくなります。
  • Smalltalkでは整数が整数として扱われる(限界値はない)ため入力値の限界値のテストケースは不要となります(MAXINTをテストする意味がない)。Myersの13個のチェック項目の中には限界値の確認はありませんが、JorgensenやBinderのテストケースには限界値を確認するものがありました。
  • Beckの6件のテストケースには、Myersのチェック項目の「一辺がゼロ」「二辺の和が他の一辺より小さい」「全ての辺がゼロ」「入力する個数の誤り」は含まれていませんが、これは『テスト駆動開発』で書いているように「テストがなくても実装の知識により自信が持てれば、そのテストは作成しない」ということだと思います。

Binderの発言から

  • 典型的な三角形判別アルゴリズムでは辺の長さの和を取る処理があるので、少なくとも一つの辺を(2**32)-1にしたテストをして計算オーバーフローの処理を確認する必要がある。
  • 二辺の確認だけで三角形を判別してしまうというバグがよくあり、これがMyersがpermutationのテストを主張した理由である。
  • テスト対象の実装の知識はテストを作成する助けにはなるが、危険を伴う。
  • テスト作成のゴールはテストスイートを最小化することではなくバグ検出機会の最大化であるべき。

その他の議論で注目したもの

  • コードを書く前にテストを書くというXPのルールに反しているのではないか?

    → 違う。XPにおけるテストはコードの作成と同時に書かれる。(Robert C. Martin)

  • あなたのテストは特定の実装に特有のものなので、他の実装では適切なテストにはならない。

    → その通り。unit testはwhite box testであり、設計の変更に影響を受ける。一方、acceptance testはblack box testであり設計の影響は受けない。どちらのテストも必要だ。(Robert C. Martin)

  • テスト対象の実装の知識は助けになるが、危険を伴う。(Binder)
    → その通り。XPではこのジレンマに対して二つのテストスイートを用意することで解決している。一つは開発者が書くwhite box unit test、もう一つは顧客/QA部門が書くblack box acceptance test。(Robert C. Martin)

おわりに

テストプロフェッショナルたちの解答や議論はいかがだったでしょうか。

Jorgensenのように文字通りのブラックボックステストを行う場合と、Beckのように実装(内部処理)を理解した上でテストを行う場合とでは、これほどまでにテストケースの数に差が生じるというのは、大変興味深い例だと思います。

皆さんは、Collardの「全ての状況に当てはまる唯一の解答があるわけではなく、状況に応じて最も適切な解答が存在する」という解説に納得できましたか。
私は、まさにそこにテストの難しさと面白さがあると感じています。

また、Beck、Martin、Jeffries、Binderらの議論は、現場の開発担当者とテスト/QA担当者の間でも起こりうるやり取りのように思われます。
長年検査部門にいた私としては、テストを現実的な(実施可能な)件数に絞り込むには、開発担当者とのやり取りを通じて「確信を持って」減らしていく、あるいはズームアウトするようなグレーボックステストのアプローチが現実的な解ではないかと考えています。

<参考文献>

[1] G. J. Myers, “The Art of Software Testing,” John Wiley & Sons, 1979(松尾正信(訳),長尾真(監訳), ソフトウェア・テストの技法, 近代科学社, 1980)
[2] LAWST - The Los Altos Workshop on Software Testing
 https://lawst.com/
[3] R. Collard, "Exercise: Analyzing the Triangle Problem," Third Annual Workshop on the Teaching of Software Testing (WTST 3), 2004
[4] P. C. Jorgensen, "Software Testing: A Craftsman's Approach 2nd Ed.," CRC Press, 2002
[5] K. Beck, "Test-Driven Development By Example," Addison Wesley, 2002(和田卓人(訳),テスト駆動開発, オーム社, 2017)
[6] R. V. Binder, "Testing Object-Oriented Systems: Models, Patterns, and Tools," Addison Wesley, 1999
[7] ISTQB, JSTQB(訳), ISTQBテスト技術者資格制度 Foundation Level シラバス 日本語版 Version 2023 V4.0.J02,JSTQB,2024
 https://jstqb.jp/syllabus.html#syllabus_foundation
[8] Re: John Roth dolt ( Re: A challenge to proponents of Unit Testing. ), comp.lang.ruby, 10 Dec 2001
 https://groups.google.com/g/comp.lang.ruby/c/LuS-qHhG6tM/m/xTmSkRL_ZbIJ

SNSシェア

この記事は面白かったですか?

今後の改善の参考にさせていただきます!

Search Articles By The Cast出演者/執筆者から記事を探す

Search Articless By The Categoryカテゴリから記事を探す

Ranking

ランキング

もっと見る