不安定なテストを書いてはいけない3つの理由


はじめに

不安定なテストはITエンジニアの敵であると言っても過言ではありません。今後不安定なテストが生み出されなくなるといいなという願いを込め、この記事では不安定なテストがいかに問題があるかについて皆様と一緒に考えることができたらと思います。
普段、不安定なテストに悩まされている方にとっては目新しい内容ではないと思います。

不安定なテストとは?

一般的に使われている言葉かどうかはよくわからないのですが、とりあえずこの記事では「コードを何も変更していないのにテスト結果が変わる場合があるテスト」のことを「不安定なテスト」と呼ぶことにしています。
テスト結果が変わる、とはつまり「普段は成功するが、コードを変更していないのに気まぐれに失敗することがある」みたいな感じです。
なお、ここで言う「テスト」とは手動テストではなく、主にユニットテストのことを想定しています。

以下、早速本題に入っていきます。

3つの理由

理由1 テストの失敗が軽視されるようになる

テストが失敗するということは、通常であれば何かバグがあることを示します。しかし、不安定なテストが存在する場合はどうでしょうか?
本来、テストの失敗とは異常事態であるべきと思います。しかし、不安定なテストが存在するとテストの失敗が「普通のこと」になってしまいます。
不安定なテストが存在しなければ「テスト失敗 = バグの発生」と言えると思います1が、不安定なテストが一つでも存在すればこの等式は崩れます。不安定なテストは、バグがなくても失敗することがあるためです。
するとどうなるか。テストの失敗がバグ発生を示すとは限らないことになるため、テストが失敗してもあまり真剣に捉えられなくなります。「あーはいはい、どうせいつものアレが失敗してるんでしょ」みたいな感じで。
そうしてテスト失敗が軽視されるようになると、テストが失敗した時にその内容の確認を怠ることに繋がり、バグが見逃されるようになる恐れがあります。
また、そのようにテストの失敗が「普通のこと」になるとテストの失敗に対してあまり抵抗がなくなるため、修正の影響でテストが失敗することがあっても、それを修正する気があまり起こらないなんてことにもなりかねません。

理由2 テスト結果を通知する仕組みが機能不全に陥る

偉そうなことを書いていますが、残念ながらうちのチームも不安定なテストをいくつも抱えています。個々のテストの失敗率はそれほど高くなくても、不安定なテストの数が多いと毎日のように何かしらのテストは失敗します。
うちのチームではテストが失敗したらSlackに通知されるようになっているのですが、毎日のように何らかのテストが失敗するということは、毎日のようにSlackに失敗通知が来るということであり、正直ウザいです。
また、私はテスト失敗通知が来たら自分の担当でない場合でも結果を確認するようにしているのですが、毎日のように確認しなければならないのでうんざりすることもあります。
するとどうなるか。失敗を通知するチャンネルを抜けてしまうとか、通知を切るとか、そういった形でテスト結果を確認しなくなってしまう恐れがあります。
幸い、うちのチームではそこまでの事態にはなっていないので想像も含んでいますが、不安定なテストの数が増えてしまうといずれそうなるという可能性は否定できません。

理由3 そもそもテストが機能しない

そもそもなぜテストを実行するのかというと、コードの修正に問題がないかどうかを確認するためです。通常であれば、修正に問題がなければテストが一件も失敗せず、とりあえずは安心できます。(あくまでもとりあえずは)
しかし不安定なテストが一件でも存在すると、本当は修正には問題ないのに不安定なテストがたまたま失敗し、原因調査で時間を無駄にしたり、原因がわからなくて辛い思いをしたりするなんてことになりかねません。
また、「一見するとコードの修正と関係なさそうに見えるが、実は修正の影響で失敗したテスト」なんてものがあった場合に、「いつもの不安定なテストが失敗しただけで、修正には問題ない」と判断してしまってバグを見逃すという恐れもあります。まあ、その場合はその後該当のテストが常に失敗し続けるはずなのでそのうち気づくかもしれませんが、気づくのが遅くなるというだけでも十分に悪いことです。
こうなるとコードの修正に問題ないかどうかをテストの結果から読み取ることが難しくなるため、そもそものテストの目的を果たせてるのかどうかすら怪しくなります。

テストを不安定にさせやすいコード

「処理時間に依存するテスト」や「ファイルやDBなどの外部リソースに依存するテスト」、「マルチスレッドで実行されるテスト」などは不安定なテストになりやすいので、そういったテストを書く場合は十分に注意する必要があります。
この節はちゃんと書こうとすると膨大な量になってしまうのと、それ以前にこの記事の主な目的は「不安定なテストがいかに問題があるか認識していただく」ことなので、ここは敢えてさらっと流します。
ただ、むしろここが肝心だろうと思われる方も多いかもしれないので、別の記事として書けるといいですね。(書くとは言っていない)

不安定なテストを見つけた時の対処

もちろんテスト結果が安定するテストするように修正するのがベストなので、可能な限り修正するべきです。しかし、簡単には修正できない場合もあると思います。
その場合はテストの趣旨を確認して、不要だと判断できれば消すなり実行をスキップさせるなりするといいですね。でも、不要と判断できるケースは少ないでしょうね…
修正も実行スキップも難しいのであれば、せめてそのテストが不安定であるということを記録するのがおすすめです。私は、不安定なテストを見つけたらRedmineでチケットを発行するようにしています。何か記録があれば、テストが失敗した際にそれが既知の不安定なテストなのかどうかを確認できるため、多少はマシになります。
本当はこの節の内容ももう少しちゃんと書くべきなのかもしれないですが…それも書くとしたら別の記事ですね。(書くとは(ry)

終わりに

これまで見てきたように、不安定なテストは問題を多く含みます。できるだけそのようなテストを書かないように心がけたいところですね。(もちろん私も)
具体的にどうすればいいのかということはこの記事ではあまり書いていないのですが、まずは心がけるところから始めるのが重要だと思います。


  1. 単にテストコードの修正漏れということもありますが、それはテストコードのバグってことで…