🌟

テストの信頼性がQAを上回るにはどうしたらいいんだろうか

2022/05/14に公開

(執筆時点で明確な結論はまだ出てません。ただ、あえていうなら 「ソフトウェアテストがQAを上回るのは無理」 が現時点での回答です)

テストをちゃんと書けばQAなしでリリースできる!?

そんなふうに考えていた時期が僕にもありました。しかし、現実にはおそらく無理です。

なぜテストをしっかりと書いてもQAなしでリリースできないのでしょうか?それは 「テストを信頼できないから」です。 「テストが通ったから、仕様通りにプログラムは完璧に動いています!」と言い切れますか?言い切れませんよね?それがテスト結果を信頼できていない何よりの証拠です。

逆に、信頼されているのがQAです。QAが通ればプログラムが意図したとおり問題なく動いていると誰しもが思うでしょう。これがテストとQAの違いです。

さて、ではQA並みにテスト結果を信頼するにはどうしたらいいのでしょうか?

テストの信頼度を測りたい

テストの信頼度を数値化できれば目的が達成できそうです。もし定量的に測れたら「この数値をご覧ください。このテストにはQA並の信頼度があります。今回のリリースでテストはすべて通っているので、バグはありません」これでリリースできます。つまりリファクタリングし放題、ライブラリのバージョン上げ放題。まさに理想郷です。テストの信頼度を測る指標が俄然ほしくなってきましたよね?

しかし、残念ながらテストの信頼度を測る指標は今のところありません。

カバレッジをいくら上げてもテストの信頼度は変わらない

ここまで読んで「テストカバレッジが100%ならテストは信頼できるんじゃないか?」と思った方もいると思います。しかし、非常に残念ですが テストカバレッジではテストの信頼度を測れません。

例えば「ソートアルゴリズム」のテストを考えます。

const sort = (arr) => {/* implementation */};
it('orders elements from smallest to highest', () => {
  const result = sort([0, 1, 3, 2, 4]);
  
  expect(
    result.every((val, idx) => idx === 0 || result[idx-1] < val )
  ).toBe(true);
});

このテストは「ソート後の値が昇順になっているか」をテストしています。そして、テストカバレッジはおそらく100%になります。しかし、ソート関数が一般的に満たすべき性質はもう一つあります。それは「ソート前後で要素の個数、種類が変化しないこと」です。

単に昇順に並べるスターリンソートというジョークアルゴリズムがあります。これは配列を前から見ていって昇順になっていない要素を削除して無理やり昇順にするというアルゴリズムです。

const stalinSort = arr =>
  arr.slice(0).reduce((acc, a) => {
    if (acc.length === 0 || acc[acc.length - 1] <= a) return [...acc, a];
    return acc;
  }, []);

スターリンソートは先ほどのテストを通過し、さらにテストカバレッジ100%です。 ソート関数として重要な性質が足りてないにも関わらず、です。これはつまり カバレッジが100%だからといって仕様を網羅できているとは限らないことを意味しています。

テストの信頼度を測る方法はないのか?

ここ数週間ずっとテストの信頼度を測れないか考えていますが、「今のところ無理そう」という結論になっています。理由はいくつかあります。

  • 「満たしてほしい仕様」はステークホルダーによって異なってくる
    • スターリンソートでも十分に要件を満たしているかもしれない
  • 一般にバグはプログラマの想定漏れによって起きる
    • 想定外のものは見えないから気づきようがない。つまり 人力で「このテストは信頼度が高い」と判断することもできない。
  • 仕様は常に変化する
    • 仮にある時点で完璧に信頼できるテストが書けたとしても、仕様の変更や追加によって信頼度は低下する。

じゃあテストは意味がないのか?

ここまで聞いて、「じゃあQAに全部おんぶにだっこでいいじゃん。テストなんてどうせ信頼もされないし意味ないじゃん」というニヒリズムに陥る方がいると思いますが、僕はそれには反対です。 テストはQAを代替できずとも意味があるからです。

例えば、テストがあれば以下のようなメリットがあります。

  • レビューのコストが下がる
  • バグの早期発見につながる
  • テストを書いた範囲については動作保証できる

要するに完全完璧にはなりませんが、効果はちゃんとあるのです。

まとめ

  • テストの信頼度を上げないと、テストは QA の代替にはなり得ない
  • だが、テストの信頼度を定量的、定性的に測る方法は今のところ存在しない
  • ただ、だからといってテストを書くことは無意味ではない
  • もし信頼度を測れる方法があったら教えてください

Discussion