ユニット 10 / 11

誤った信頼のリスク、テストの品質、および突然変異のテスト: テストのテスト

利益:

  • 疑似信頼の 3 つの側面 (非主張、自己主張、些細な主張) を認識し、解毒剤を適用する能力
  • ツールや手作業によるカバー率よりも正確な品質の尺度として、突然変異テストと突然変異スコアを使用する能力
  • AI をテストに対するレッドチームとして位置づけ、賞賛の罠に陥ることなくテストの抜け穴を探す能力

このモジュールの中心には、繰り返し警告が表示されます。緑色に光るテスト パネルは品質の証拠ではありません。テストによって自信が得られた場合、その自信が本物か偽物かを知る必要があります。人工知能 (AI) の時代では、AI は流動的で滑らかに見えるが中身のないテストを作成することに長けているため、この質問はこれまで以上に重要になっています。実際にはテストで何も検証されていないにもかかわらず、テストが緑色であるためソフトウェアが正しいと信じる誤った信頼は、QA チームに起こり得る最も危険な行為です。エラーがないことを隠すのではなく、エラーが見えなくなるからです。この単元では、モジュール全体の検証哲学を、テストのテストという 1 つの分野にまとめます。

テストの品質を測定するためのゴールドスタンダード: 突然変異テスト

テストが実際に保護しているかどうかを理解する最も強力な方法は、ミューテーション テスト (ミューテーション テスト - ソース コードに意図的に小さな歪み/ミューテーションを生成し、テストでこれらの歪みが検出されるかどうかを測定する手法) です。ロジックは単純です。意図的にコードを破壊した場合 (+ を - に、> を >= に、true を false に)、優れたテスト スイートはその破損を検出して赤に変わるはずです。そうでない場合、その混乱は生き残った突然変異体であるため、テストでは実際にはその動作が保存されていません。

突然変異スコア = 殺された突然変異 / 総突然変異。 90% のライン カバレッジを持つパッケージの突然変異スコアは 40% になる可能性があります。これは、回線は機能しているが、動作が検証されていないことを示します。突然変異スコアは、カバレッジ率よりもはるかに正確な品質の尺度です。

ヒント: 自動変更ツール (Java の場合は PIT/Pitest、JavaScript/TypeScript の場合は Stryker、.NET の場合は Stryker.NET、Python の場合は mutmut) があります。これらは、数百もの突然変異を自動的に生成し、テストします。ツールがない場合は、手動の「コードをブレーク テスト」する方法でも、重要な機能には非常に役立ちます。

疑似信頼の 3 つの側面とその解毒剤

疑似信頼フォーム

症状

解毒剤

アサートなしでテストする

コードは機能しますが、何も検証されていません

すべてのテストで真のアサート。突然変異を伴うテスト

自己確認テスト

期待される = コードの出力

期待値を独自に計算する

自明なアサート

「nullではない」、「200が返されました」

ビジネスルール/実績の検証

広範囲にわたる誤謬

90% のライン、保護力が低い

突然変異スコアを見てください

脆弱なテスト耐性

「また詰まった、パス」

根本原因 + 決定論的テスト

AIを「レッドチーム」として活用する

AI は、疑似信頼を生み出すことも、それを追い詰める強力な味方になることもできます。 AI を独自のテストに対してレッド チームとして使用します。「これらのテストには合格するが間違っているコードを作成してください」、または「これらのテストを騙す破壊版を見つけてください」と依頼してください。 AI がテストの抜け穴を見つけた場合、その抜け穴は実際のリスクとなります。

注意: AI に「私のテストの品質は良いですか?」と尋ねないでください。 「はい、素晴らしいです」という答えを確信として受け取ります。 AIは優しい傾向にあります。代わりに、AI に「これらのテストに合格するバグを生成する」という具体的なタスクを課します。エラーが生成される場合、テストではそのエラーが認識されません。

同等の変異とスコアの限界

ミューテーション テストは強力ですが、落とし穴もあります。ミューテーションによっては、コードの動作がまったく変わらない場合もあります。これらは等価突然変異 (等価突然変異 - 破損したコード、元のコードとまったく同じ結果を生み出す突然変異) と呼ばれます。たとえば、一度も使用されない変数の初期値を変更しても、出力には影響しません。これを検出できるテストはありませんし、検出すべきではありません。したがって、100% の変異スコアは実際には達成できないことが多く、目標ではありません。同等の突然変異を手作業で取り除くのは多大な労力を要します。したがって、突然変異スコアを絶対的な試験スコアとして解釈するのではなく、「テストが本当に保護しているかどうか」を示す正直な指標として解釈してください。

実際のアプローチは次のとおりです。コード ベース全体で突然変異テストを継続的に実行するのではなく、最も高いリスクと最も複雑なビジネス ルールを含むモジュールに対してテストを実行します。これらのモジュールに残っている変異を 1 つずつ調べます。実際のギャップがある場合は、テストを追加します。同等の突然変異の場合は、両端揃えでマークを付けて合格します。 AI は、生き残った変異が同等であるかどうかを評価する初期スクリーニングを実行できます。ただし、最終的な決定は、コードの動作を理解しているあなたが行います。

注意: ミューテーション テストは計算コストが高くなります (すべての関連テストはミューテーションごとに再実行されます)。したがって、一般的で合理的な戦略は、重要なモジュールの詳細なチェックを、マージごとではなく、毎週またはリリース前の詳細なチェックとしてスケジュールすることです。

弱いプロンプト / 強いプロンプト

弱者: 「私の検査は十分ですか?」
Strong: 「この関数とテスト スイートのレッド チームとして行動します。(1) コード内で強制終了できる 8 つの突然変異 (演算子の置換、境界シフト、条件の反転、戻り値の置換) を生成します。(2) 各突然変異について、既存のテストのどれがそれをキャッチし、どのテストがキャッチしないかを示します。(3) 生き残った各突然変異について、それを強制終了する新しいテストを作成します。(4) これらのテストすべてに合格するコード例を作成できるかどうかも示します。ビジネス ルールに違反しています。コード + テスト: [貼り付け]」

強力なプロンプト。 AI を賞賛する機械ではなく、試験を突破する試験官として位置づけています。

コピー可能な 4 つのテンプレート

1) 手動による突然変異制御:

このコードに対して 8 つの重大な変異 (軽度の意図的な中断) を生成します: 算術演算子の置換、比較限界 (> 対 >=)、論理反転、戻り値/定数の置換、条件のスキップ。それぞれの変異について、利用可能なテストのどれがそれを検出するかどうかを予測します。コード+テスト: [貼り付け]

2) 生き残った突然変異を殺す:

次の突然変異テスト レポートには、生き残った (捕捉されなかった) 突然変異が含まれています: [リスト/レポート]。それぞれについて、その突然変異を強制終了する最小限のテストを作成します (そのように壊れるとコードが赤になります)。テストで確認された動作についてコメントします。

3) レッドチーム — 血液検査:

次のテストのすべてに合格するが、次のビジネス ルールに違反するコードを作成できますか: [ビジネス ルール]。もしそうなら、これらのテストのどの抜け穴がこれを可能にしますか?その抜け穴を塞ぐテストを追加します。テスト: [貼り付け]

4) テスト品質検査:

このテスト スイートの品質を確認してください。各テストにチェックを入れます:- 真のアサートはありますか? それともそれはプロパティですか?- 期待値はコードから派生した独立したものですか?- ビジネス ルールまたは何か些細なことを検証しますか?最後に、推定される「真のアサート スコア」と最も弱い 3 つのテストを示します。テスト: [貼り付け]

ミニケース3個

ケース 1 — カバレッジ 92%、突然変異スコア 38%。あるチームは高いカバレッジに依存していました。 Stryker を使用して突然変異テストを実行した場合、スコアは 38% でした。生成された突然変異のほとんどが生き残りました。これは、テストがラインを実行して動作を検証していないことの証拠でした。チームは品質のテストに 3 週間を投資しました。突然変異スコアは 81% に増加し、次のリリースでは強化されたテストによって 2 つの実際の計算エラーが検出されました。

ケース 2 — AI がテストを騙した。 「レッドチーム」テンプレートを使用して、専門家が AI に既存のテストには合格したが、割引ルールに違反したコードを尋ねました。 AI は常に割引ゼロを返すコードを作成しました。実際の割引値を検証するテストはなかったため、すべてのテストは緑色のままでした。ギャップが見られ、実際の主張が追加されました。

ケース 3 — 賞賛の罠。若手テスターが AI に「私のテストは良好ですか?」と尋ねました。 「非常に充実しています」という返事を聞いて安心しました。彼の先輩も、「テスト品質監査」テンプレートを使用して同じテストを監査させました。 20 のテストのうち 12 は装飾 (アサートやジャンクなし) であることが判明しました。正しい質問は正しい答えをもたらしました。

よくある間違い

  • 範囲を品質と勘違いしている。高い行カバレッジに依存し、突然変異スコアをまったく見ていません。
  • AIの賞賛を信じて。 「テストは良かったですか?」と尋ねます。そして肯定的な答えを保証とみなします。
  • コードから期待値を導き出す。欠陥のあるコードを確認する自己検証テスト。
  • つまらない主張に満足してください。 「null ではない」、「200 が返されました」など、実際のルールを検証しないチェック。
  • 生き残った突然変異を無視します。変異レポートに含まれていないものは無視します。
  • 重要なコードを手動で変更しようとすることさえありません。ツールが利用できない場合は、「コードを分割してテストする」ステップをスキップします。

要約すれば

疑似信頼とは、テストが緑色であるため、ソフトウェアが正しいと信じることです。一方、テストでは何も確認できない場合があります。これを測定するためのゴールドスタンダードは突然変異テストです。つまり、意図的にコードを破壊し、テストでそれが検出されるかどうかを測定します。突然変異スコアは、カバレッジ率よりもはるかに正確な品質の尺度です。 AI は疑似信頼を生成すると同時に、それを追跡する強力なレッド チームにもなり、「これらのテストに合格するバグを生成してください」と要求します。テストをテストします: 真のアサート、独立した期待値、ビジネス ルールの検証、および強制終了されたミューテーション。

アプリケーションタスク

ビジネス ルールとそのテストを含む関数を独自のプロジェクトからインポートします。可能であれば、突然変異ツール (Stryker/Pitest/mutmut) を実行し、突然変異スコアを測定します。ツールがない場合は、「手動変異制御」テンプレートを使用して少なくとも 8 つの変異を生成し、手動で試します。生き残ったミューテーションごとに、「kill surviving mutation」テンプレートを使用して新しいテストを作成します。最後に、「レッド チーム」パターンを使用して、AI がテストを欺くコードを生成できるかどうかを確認します。開始および終了の突然変異スコア (または検出/合計突然変異率) を報告します。

チェックリスト

  • [ ] テストの品質をカバレッジではなく、突然変異スコアによって評価しました。
  • [ ] 重要なコードに対して突然変異テストを (ツールまたは手動で) 実行しました。
  • [ ] 生き残った変異ごとに新しいテストを作成しました。
  • [ ] 私は AI をレッドチームとして使用し、テストの抜け穴を探しました。
  • [ ] 私は AI の「テストは良好です」という賞賛を安心感として受け取っていませんでした。
  • [ ] 各テストが実際のアサート、独立した期待値、ビジネス ルールを検証していることを確認しました。