C++向けテストライブラリQuickCheck++について

Haskellで著名なテストライブラリにQuickCheckがあるが、C++ではそれに似た機能を実現するQuickCheck++というものが開発されている。今回はこのQuickCheck++について位置づけや例をまとめたい。

検査でのQuickCheckの位置づけ

QuickCheckは、対象の実行領域内で対象が検査式を満たしていることをランダムに検査するために用いられる。この考え方はモデル検査にも似ている。とりあえずQuickCheckの位置づけを整理するために、モデル検査やSmallCheckといった似た技術を以下に列挙する。これらの違いは、基本的に集合や実行領域に対して、どこをどこまで検査するかという点になる。

形式手法におけるモデル検査(SMVやSPIN)

以前紹介( Cadence SMVによるアルゴリズムの検査 - 千里霧中 )したCadense SMV等によるモデル検査は、対象の実行領域すべてで検査式を満たしていることを確認する。

QuickCheckによる検査

QuickCheckは、対象の実行領域の一部をランダムに選びとり、そこで検査式を満たしていることを確認する。なおランダムなのは、全網羅が不可能あるいは困難な場合でも領域を全体的にテストしたい事に寄る。

SmallCheckによる検査

QuickCheckと比較されることの多いライブラリにSmallCheckというものがある。こちらは、対象の実行領域の中でも、特定の実行領域内のみに限定して検査式を満たしていることを確認する。

パラメータ化テスト

ユニットテストなどで一般的なパラメータ化テストは、対象の実行領域の中で、特定の一つの状態を選択して検査式を満たしていることを確認する(なお前述の3つは集合や実行領域を対象としているが、パラメータ化テストはそうでない用例が多いという違いがある。今回はあくまで参考として列挙している)。

QuickCheck++の使い方

本題のQuickCheck++の使い方だけれど、基本的に本家(http://software.legiasoft.com/quickcheck/)のドキュメントの説明が充実している。

入手

入手はドキュメントの通り以下でできる。

git clone http://software.legiasoft.com/git/quickcheck.git

なおQuickCheck++はソースコードをそのまま使用するので、特にビルドなどは必要ない。上記コマンドで得られるファイルのうち、「quickcheck」ディレクトリに格納されているヘッダファイルをインクルードして使用する。

コードの記述

QuickCheckのコードの例は以下の通り。今回はテスト対象のTargetに対して、入力となるvectorのオブジェクトをランダムに生成してテストする。

#include <quickcheck/quickcheck.hh>
#include <vector>

using namespace quickcheck;

class PropertyleapCheck : public Property<std::vector<int> >
{
  bool holdsFor(const std::vector<int>& values)
  {
    //targetがテスト対象オブジェクト
    Target target;
    //テスト対象を生成したvaluesをインプットに動作させる
    for (std::vector<int>::const_iterator it = values.begin(); it != values.end(); ++it)
    {
      target.inputControlValue(*it);
    }
    
    //以下が検査式。式を満たしているならばtrueを返す
    if (target.overshoot_ < 20 && target.undershoot_ < 20) {
      return true;
    } else {
      return false;
    }   
  }
};

なおテストランナーは以下の様な記述になる。ランダムに生成する入力を補正したい場合は、check()の引数やAPIで指定する。例えばテスト回数はデフォルトでは100回となっているが、10倍にしたい場合は「prop.check(1000)」と記述する。

int main(void)
{
  PropertyleapCheck prop;
  prop.check();
}

QuickCheck++の用途

QuickCheck++は本家QuickCheckに倣って、集合や実行領域の検査を目的としている。ただ実際はかなりシンプルなコードであり機能も限定的なため、実質的にはユニットテストでのランダムデータジェネレータのような扱いになる。またQucikCheckのヘッダファイルはGNU GPLが適用されているので、そのまま使うとテスト対象にライセンスの制約が適用される点に留意が必要。
そういった背景があるので、QuickCheck++を検討する場合は、コードは独自に実装して、あくまでアイデアのみを活用するやり方が無難かもしれない。