そうですね。またよい質問をいただきました。「テストの資産価値」という話をこれからしたいと思います。
小さいテストがすべて真っ赤っかに……
私も「不安」ですし、新人の人だったら不安がいっぱいでしょうから、たくさんの小さいテストができることはあると思います。
その場合、小さい単位のテストを基盤にして、それらの学習結果やそれらの不安をもとにしたテストコードと、それらの上で実際に書かれたコードが存在することになります。
それに対して仕様変更があった場合、小さい視点のテストが全滅してしまう、もしくは真っ赤っか(テスト失敗だらけ)になってしまうということはよくあります。
そのときに、そのテストを一つ一つ直していくことに意味があるのか、割に合うのかという話が出てくると思います。実プロジェクトではよく遭遇する事態だと思います。
整理すると、まず最初にサイクルとして大きいテスト(受け入れテストや、スコープの広い機能テストなど)\を作りました。そして、小さいテストから積み上げて開発をしていきました。あるとき大きいレベルで仕様変更があったときに、その大きい機能を満たすために積み上げていった小さいテストが、全部真っ赤っかになってしまった、というような場面です。
テストの資産価値
私は、「テストの資産価値」という考え方を持っています。
リファクタリングで小さい粒度のテストが赤くなったときには、もうそのテストは役目をある程度果たしていると考えています[1]。
ですから、テストをその時点で捨ててしまうこともあります。ただし、小さいテストを捨てるという判断をするときには、当然それらのテストを包含している大きいテストがあることが前提です。
たとえば、小さいテストがいっぱいあり、それらの小さいテストの学習結果や、それらの小さいテストによる不安の克服をベースにしてできあがった大きい粒度のテストがいくつかあったとします。
私は、実際にテストとしてメンテナンスしていく価値を持っているのは、この大きいテストケースのほうだと考えています。この大きいテストケースをグリーンにするために、小さいテストケースのレッド、グリーン、レッド、グリーンの繰り返しがあったと考えるのです。
階段、積み木、はしごというメタファ
私はよくテスト駆動開発の例え話として、階段や積み木、はしごの話をします。
提供したい機能を「高いところにある」とイメージしてみます。高いところまで行きたいときに、最初に受け入れテストとして、ここまでいきたいですというテストを書くんですね。
テストは書いたものの、書いた時点ではテストはもちろん通らない(成功しない)です。目標とする地点まで至るために、土台として小さいテストを積み上げていって、最終的に大きいテストが通るようになります。
そのようなとき、小さい単位で積み上げていったテストの1個1個の総和と、大きい視点のテスト1個は、資産価値が同じだと私はとらえています。要するに、小さいテストを全部足した価値と、それらを包含する大きいテスト1個の価値は同じだと考えているのです。
テストのメンテナンスコスト
価値は同じでも、メンテナンスコストは全然違いますよね。小さいテストのほうが数は断然多いですし、細かい内容になってます。大きいテストのほうはもっとずっと粗い視点ですよね。
大きい視点での仕様がちょっと変わったために、積み上げていった関連する小さなテストが全部真っ赤っかになってしまったとき、大きい視点のテストの変更は当然行います(さらに言えば、テストファーストをしているのなら、「先に」変更されるはずですね)。
赤くなっていた大きい視点のテストを、仕様変更作業を行うことによってグリーンにしました。このとき、メンテナンスをまだしていないレッド状態の小さいテストが非常にいっぱいあるという状態になります。
そのようなときに、テストの資産価値を考えます。大きいテストと小さいテスト群はだいたい同じ価値ですので、「大きいテストがメンテナンスされたことで、小さいテスト群は、もう用済みになったのではないか」というようなことを考えるのです。小さいテストのメンテナンスコストが気になるのであれば、大きい機能を満たすために積んでいった踏み台としての小さいテストは、仕様変更のあとで赤くなってしまった時点で外してしまってもよいのではないかと考えています。
「もったいない」と言われたときは……
先ほど「もったいない」という言葉が出てきました。
誰でも、自分が一生懸命作ったものを消すことには抵抗があります。だから、説明をきちんとしなければ、きちんと説明できなければなりません。
まず大前提として繰り返しますが、小さいテストを捨てていいのは、それら小さいテストを包含している大きいテストがあるときだけです。
同じ意味合いを持ったもっと粗いテストがある場合、コストを考えると小さいテストのメンテナンスは段々に重荷になってしまいますし、精神的にも負担です。
私はそういうときに、テストの資産価値という視点で説明を行って、「新機能をテスト駆動で開発するところで活躍してくれたテストだけど、そういう小さいテストたちは今やもう役目を終えたので、メンテナンス対象から外してしまいましょう。消してしまいましょう」という話をしています。
テストをレッドのまま放置してはいけない
テストをレッドのまま放置してはいけません。メンテナンスしてグリーンにするか、消すかの二択です。
なぜかというと、テストをレッドなまま、動かないまま放っておいてしまうと、プロジェクトが段々と不健康な状態になってしまうんです。「この単体テストはレッドバーなんだけど、それはそれでいいから」という感じでプロジェクトを進めてしまうと、レッドバーを見ても危機感を感じなくなってしまうのです。
プロジェクトは基本的に、小さい単位のユニットテストは常にオールグリーンの状態、すなわち進捗管理に使う受け入れテスト以外のテストはオールグリーンの状態で進めていかなければならないと考えています。
レッドバーが出たら、何かがおかしいと感じるような状態をキープしましょう。レッドバーは炭坑のカナリヤの役割を果たすと考えてみてください。
プロジェクトのセンサーとしてのテストの質を維持するために、資産価値が低くて用済みになってしまった赤くなったテストたちは、プロジェクトの健康のために捨ててしまいましょう。