テストファーストの弊害

作成:2006年1月13日

吉田誠一のホームページ   >   ソフトウェア工学   >   技術コラム   >   開発プロセス

テストファーストは、XP(エクストリームプログラミング)の中でも特に広く浸透したプラクティスの1つである。

テストファーストは、モノを作るよりも前に、まずテストから着手する、という手法だ。モノが無ければテストできないという常識を、根本からひっくり返す斬新なアイディアは、多くのソフトウェア開発者に衝撃を与えた。

テストファーストは、短期開発におけるXPの有効性が認められ、JUnitなどのテストツールが普及した今では、広く受け入れられるようになった。

だが、このようなまったく新しい手法は、初めはなかなか受け入れられ難いが、いったん受け入れられると、今度は逆に、魔法の技術であるかのように盲信されやすい。テストファーストについても、最近では「JUnitでテストコードを書いていれば、ソフトウェアの品質は問題ない」という風潮が広まりつつあるような危惧も感じる。

テストファーストの効果は、多くの人が認めるところだ。だが、ここでは敢えて、テストファーストがもたらす弊害について考えてみる。

目次

  1. 計画性のないテストによって、テストの品質が下がる
  2. 単体テストが行われず、バグが見逃される
  3. 効果的でないテストで工数を浪費する
  4. 読みづらいドキュメントが、修正を妨げる

計画性のないテストによって、テストの品質が下がる


   

 

     

     

     

なお、この弊害に対する解決策として、 JUnit Primer では、次のようなイディオムが提示されている。

  • Write tests for the areas of code with the highest probability of breakage.
  • Write tests that have the highest possible return on your testing investment.

単体テストが行われず、バグが見逃される

従来のソフトウェア開発では、コーディングの後で、ある程度の工数をかけて、単体テストが行われる。

テストファーストは、コーディングの工程の中に、単体テストが組み込まれたものだ。コーディングが完了した時点では、テストケースはすべてパスしている。そのため、コーディング完了と単体テスト完了がイコールだと見なされる。

だが、 「バグを見つけるためのテストをしよう」 で述べたように、テストには、確認のためのテストと、バグを見つけるためのテストの、2つのアプローチがある。

テストファーストの考えは、作るべきモノの仕様を先にテストケースとして書き表すことで、仕様から外れないように導く、というものだ。ここで、テストケースに書かれるテストとは、確認のためのテストである。つまり、ある条件である処理を行った時に、どのような結果になるか、期待される結果が明記できるようなテストだ。

一方、バグを見つけるためのテストは、テストを実行した際に期待される結果を、予め明記できない。そのため、テストファーストでは、このアプローチのテストケースを作ることはほとんど無い。つまり、テストファーストでは、実施できるテストは限られており、それだけでは、ソフトウェアの品質を保つためには不十分である。

効果的でないテストで工数を浪費する

テストファーストでは、テストケースをコードとして書く必要がある。コーディング量が増える分だけ、どうしても工数は増えてしまう、という懸念は、以前から指摘されている。だが、テストファーストが引き起こす工数の増大は、それだけではない。

技術者の中には、完全なテスト項目を作り上げ、完全なテストを実施し、完全なテストの記録を残したい、という考えの人も少なくない。それでも、従来のソフトウェア開発では、それまでにかかった工数や、締め切り、ソフトウェアの品質、チームの状況などにより、現実的なテストに落ち着くことが多い。

テストファーストでは、テストケースの作成が、一番初めの作業になる。ソースコードが存在しないため、どれくらいの規模のテストを実施すべきか判断する材料が少ない。また、スケジュールにも余裕がある。この状況では、完全なテストを行いたい技術者は、必要以上にテストケースの作成に時間をかけてしまう、テスト中毒に陥りやすい。

しかも、これまで述べてきたように、こうして作られたテストケースは、あまり問題の無さそうな、作りやすいものばかりになる危険性が高い。工数が増えても効果は薄く、工数を浪費しただけに終わりがちである。

また、テストファーストで実施するテストは、事実上、単体テストに過ぎない。結合テスト・システムテストは、従来どおり行わなくてはならない。

単体テストの工数が増大しても、結合テスト・システムテストに十分な工数をかけるのであれば、問題はない。だが、テスト全体の工数として、従来の開発手法と同じ時間しか見積もっていなければ、テストファーストによって単体テストの工数が増えた分、結合テスト・システムテストを軽視することになる。

テストファーストでは、テストケースの作成に必要以上に時間をかけやすい。これは、テストファーストを導入すれば、自然に、単体テストにかける比重が大きくなることを意味する。

従来、単体テストの不備で問題が多く発生していたのであれば、テストファーストは最適な解決策であろう。だが、それ以外の要因で問題が起きていたのであれば、テストファーストの導入によって、的外れなところに力を注ぐことになり、より事態が悪化することにもなりかねない。

読みづらいドキュメントが、修正を妨げる


 1  

 

 

 

 

 

 

 

なお、この弊害に対する解決策として、 JUnit best practices では、次のようなプラクティスが提示されている。

  • Name tests properly
  • Document tests in javadoc

また、JUnit スーパーTips(JavaWorld 2005 October)では、クラスやメソッド、アサーションの名前に日本語を使って、内容を分かりやすくする、という方法が提案されている。

テストファーストの流行は、ソフトウェアの品質に対する意識が高まっていることの表れであろう。だが、どのような手法も、ツールも、あくまでテストを行うための「道具」の1つにすぎない。ソフトウェアの品質は、結局、これらの道具を人間がいかに使いこなすか、にかかっているのだ。

Copyright(C) Seiichi Yoshida ( comet@aerith.net ). All rights reserved.