テストファースト文化 :-)

テストファーストは、まずテストコードを書いてエラーを出し、そのエラーを解決することで正しい実装を確認していく、というやり方だ。大抵はテストファーストというとコーディングとユニットテストのテクニックと思われる場合もあるだろうが、これは要求仕様にも適用できる。

たとえば、まず結合テスト仕様書を作成し、実装は何も無い、という状態でテストをする。当然何も作っていないからエラーになる。次に、該当の仕様書のケースにのみ通るようなある意味無茶苦茶な実装をし、無理やりテストをOKとするのだ。次に、新しい結合テスト仕様書を作成し、最初のテストに通りかつ次のテストに通るような実装に変更するのだ。すでにある単体テストコードが必ず正常に通る状態を維持して新しいテストコードも通るように実装を変更していくのだ。こうやっていけばいつかはすべてのテストに通る実装が出来上がるはずだ。

ただ、システムが複雑になってくるとどうしてもそれだけではできない場合もある。データの組み合わせが星の数ほどある場合などはロジック自体も検証が必要になる。それに、ある程度、どのような方針で作るか、どのような要件があるかを抑えておいたほうが効率的になる場合もあるだろう。で、通常はまず分析設計をしてから実装をすることになるのだ。

ただ、大抵のプロジェクトではこの分析設計を重視するあまり、実際に開発時間が足りなくなるケースが多い。たとえば、

  • 機能コードのコード体系を決めなければいけない。コード体系ごとに振る舞いを変更するため、まず検討したい。
  • 障害時の動作を明確に決めたおかなければいけない。どうするかを検討し仕様書を作成しましょう。
  • XXX処理の要件があいまいです。ある程度は実装できますが、それ以上はムリです。ですから結合するまでにはもう少し時間がかかります。早く明確にしてください。

こんな感じで、決まらない、あいまい、わからないことがあるとがあると実装や単体テストは一部できても結合テストまでは持っていけないことが多い。で、なかなか決まらず時間が過ぎた後、ある程度明確化し実際につなぐと新たな問題が発覚し、対応する時間が無い、という場合が多いのだ。

そういう意味ではどうせ、結合すれば問題も明らかになるし、あいまいでどうしたらよいかわからなかったところも見えてきたりする。確実に失敗する、とわかっていて結合テストをするのはストレスかもしれないが、今開発の現場に求められているのはそういう姿勢では無いだろうか。

昔は、コンパイルに半日もかかる、マシン占有は1日のうち2時間のみ、なんていう時代もあったからそういう時代には、慎重に固めてマシンを使う時間を短くする工夫が必要だった。しかし、今は複数の環境すら使い分けてテストをすることが容易な時代だ。結合テストでもまず、失敗させることを恐れず実行し、そのテストに対応していけばおそらく、確実に設計をしてから進めていくやり方よりはずっと早くコストを削減して開発を続けることができるはずだ。

これは、イテレーティブであろうとウォーターフォールであろうと同じだ。ただ、イテレーティブでは致命的に遅れる前に結合せざると得ないため、問題は軽微で終わる可能性が高いだけだ。ウォーターフォールで行う場合は、要件が決まらなくてもテストに踏み切らなければいけない。これをウォーターフォールというのかはわからないが、現場では実はそういうやり方をしていたはずだ。*1ただ、テストに踏み切る時期が遅かっただけなのだ。まず、開発期間の1/10ぐらいの期間に結合テストに着手していればウォーターフォールでも成功しやすいプロジェクトになる気がする。「要件が決まらなければ作れない!」といわず、要件が決まらなくても無理やりテスト仕様を書けばできるはず。これで問題点が明確化するのだ。これは計画があいまいなイテレーティブのようなものになるのかもしれない。

*1:完璧で理想的なウォーターフォールを実現できた経験を持つ人はどのくらいいるのだろう。