SSブログ

ScalaCheckへの疑念 [Scala]

「プロパティベースのテスト」について初めて知ったのは Fun of Programmingという本で、 それを読んだ当時ScalaにもScalaCheckがあることを知って少しさわっていたんだけど 結果的には「なんか微妙」という感想を持ってやめてしまった。[^1]

その後特にScalaCheckをさわってはおらず、Scalaからもかなり離れてしまったので感想も変わっていないんだけど Scalaのユーザーが増えるとともにScalaCheckも使われているようで、よく聞くようになった。

それで思い出したのでScalaCheckへの疑念を言語化することにした。 タイトルはScalaCheckとしたけれどもQuickCheckやその他の同様のフレームワークにも該当すると思う。

普通にテストケースを書いたほうがいいのではないか

ScalaCheckでは例えば「任意の1024以上の整数nについてP(n)が成立する」のような性質から、 nを例えば100通り自動生成してテストケースを実行してくれる。 人間がテストケースを書く場合、おそらく2,3個のケースを書くにとどまるだろう。

ここで「50倍ものケースを自動実行するのだからより大きい確証が得られるだろう」 ということが言えるだろうか。

人間が書くテストケースにおけるnはおそらく1024と、MAX_INTと、ひょっとしたらその間の適当な値である。[^2]

自動生成されるケースは1024以上MAX_INT以下のランダムな100個で、 1024とMAX_INTはそこに含まれるかもしれないし含まれないかもしれない。

この例で1024とMAX_INTはバグを見つけてくれそうなテストケースである。それは仕様の境界値だから。[^3] プログラムは「以上」と「より大きい」を勘違いしているかもしれないし、オーバーフローを考慮していないかもしれない。

これに対して1025からMAX_INT-1までの値はせいぜい1つ選べばよく、残りは無駄なテストである。 無駄なテストケースは100個あっても10000個あっても品質の向上に貢献しない。 ランダムに100回実行したから1回実行したよりも99回分多くの確信が得られると思うのは偽の確信である。 偽の確信はテストにおける害悪だ。

これらに対して「それはジェネレーターの定義次第だ」という反論があるかもしれない。 でもそれを意識してジェネレータを作るならば、 それは人間がテストケースを決めるのを遠回りにしただけではないだろうか。

ランダムな組み合わせはどうか

複数の変数に対する組み合わせテストを自動生成してくれる点が ScalaCheckなどの方法の有利な点だという考えがあるかもしれない。 これは確かに手で書くのは煩雑だ。

でも同じ自動生成するのでも直交表やPairwise法などの、経験的な研究に裏付けられた、 バグ検出に効率的な組み合わせの自動生成方法があり、 ランダムな生成が有利だという根拠はない。

確率的なものは難しい

以前ScalaCheckをさわっていた時の記事で、 確率的な分布を意識していないと有効なテストが生成されないことがあるという注意点を取り上げていた。

テストの中に確率的なものが現れるのは悪いことだと思う。 おそらく多くの開発者にとって確率はプログラムよりずっと理解しにくいからだ。 プログラムコードの結果を予測するよりもテストコードの結果を予測するほうが難しいというのは、 明らかに望ましい状況ではない。

再帰的なデータ構造についてはどうか

再帰的なデータ構造に対するテストデータの生成はScalaCheckのような方法が活躍できる領域かもしれない。 再帰的なデータ構造では変数の数自体が固定的でなく、 そのような問題に対して既存の組み合わせ技法をどう適用すればいいかはあまりはっきりしないからだ。

これについてもしかし、ランダムである必要があるのかという点についてはやはり疑問が残る。 (有界モデル検査のようにある決まった範囲を全網羅するような方法が代わりに考えられる)


以上ScalaCheckや類似の手法についての疑念を書いた。

大体においては 「同値分割や境界値分析やPairwiseなどの既存のテスト技法でテスト設計したほうがいいのでは」 と感じているということだ。

一方で「ScalaCheckは駄目だと思っている」かというとあまりそこは断言できない。

1つにはこれだけ皆使っているので自分の理解が何か間違っているのではないかという不安がある。 (上記に書いたようなことを補填するような洗練されたやり方が考案されているのかもしれない)

もう1つはテスト手法の良しあしは経験的に決まるものだという点で、 例えば「実際にプロパティベースのテストのほうが既存のテスト手法より良くバグを見つけるのだ」 という経験的研究結果があればなるほどそういうものかと思って納得するかもしれない。 (読んでいる人でご存知の人がいたら教えてください)

  • [^1] 左下の「ScalaCheckを試す」のリンク集を参照
  • [^2] n=1023でP(n)が成立しないこともテストするかもしれないが、比較のためここでは取り上げない
  • [^3] MAX_INTは「暗黙の」境界値であるともいえる

nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。