Island Life

< Pythonでモナド | Chief >

2008/01/11

テスト

ひがやすを blogより:

実は、テストを書くのは結構工数かかるんですよ。スクリプト言語は、 コンパイラがミスを教えてくれることはないので、Javaと比べると、 より多くのテストを書く必要があります。でも、そんな話ほとんど聞いたことないですよね。

気持ち的には平均して実装:テストは1:1くらいだと思っている。 平均だから、場合によってはテストの方が工数がかかることももちろんある。 あとドキュメントが気持ち的に0.5くらい。 だから、実装がひととおり済んだというのは 道程にして40%にすぎない。もっともやっと動いたところでまだ4合目というのでは 士気が保てないので、ドキュメントもテストも平行してやるようにしてるけど。

なぜ実装の方が楽なことがあるかというと、実装ってよく考えないでも とりあえず動くものは出来ちゃうことがあるんだよね。でもテストは ちゃんと隅から隅まで考えないと作れない。

特に、何年も潜んでいてある特殊な条件が重なった場合にようやく露見するような バグは、滅多に通らないパスの、それもそのパスを通るかどうかの境界条件まわり に居ることが多いと思う。そんな面倒なところをちゃんと詰めて考えないでも、 ほとんどの場合に動くものは作れる。もう少し真面目にコードパスのカバレッジを 100%にしようと思うなら、多少試行錯誤すれば滅多に通らないパスを 通るようなテストデータを用意することもできる。

でも、そのパスに入るか入らないかのクリティカルな判断がされるところを テストしようとしたら、どういう条件でパスのスイッチが起きるのかを定量的に 把握してないとならない。

型の整合性がちゃんとチェックされる言語、MLやHaskellなどで時々 「コンパイルが通ればほとんどバグはない」みたいに言われることがあるけど、 これらの言語の型システムも上で言ったような境界条件回りの整合性を検出できる ほどには強力ではないはずだ(ちゃんとやろうと思ったら依存型が要るのでは)。 「コンパイルが通れば〜」と言えるのは、 こういう言語で書いている人は実装段階から「ちゃんと考える」ことを ある程度システムに強要されるためではないか、という気がする。

(ところでテストファーストというのは基本的には良いことだと思うのだけれど、 上記のとおりちゃんとしたテストというのは実装で使った具体的なアルゴリズムや パラメータにべたべたに依存するので、特に性能評価などでいくつものアルゴリズムや パラメータを試した場合などは採用したものを基にして改めて境界条件を つっつくテストを書く必要があると思う。みたいなことはちゃんとしたTDDのドキュメントには 書いてあったりするのかしらん。)

Tag: Programming