ククログ

株式会社クリアコード > ククログ > Cutter 1.0.6リリース

Cutter 1.0.6リリース

先日、C言語用単体テストフレームワークであるCutterの新バージョン1.0.6がリリースされました。(アナウンス

ハイライト

NEWSにも書いてあるように、今回のリリースでも多くの新機能がありますが、ここではその中でも特におすすめの構造体定義なしで複雑なテストデータを使えるAPIを紹介します。

この新機能によりもっと簡単にデータ駆動テストが書けるようになります。実際、milter managerのテストが簡単に書けるようになりました。

データ駆動テスト

データ駆動テストとは同じテストケースに対して複数のテストパターンを適用するテスト手法です。これにより多くのテストパターンを簡単に書くことができるという利点があります。

例えば、入力された文字列の小文字をすべて大文字に変換するto_upper()関数のテストをするとします。テストデータは以下の3つを考えます1

  • すべて小文字の文字列
  • 小文字と大文字が混ざった文字列
  • すべて大文字の文字列

これはこのように書けます。

cut_assert_equal_string("HELLO", to_upper("hello"));
cut_assert_equal_string("HELLO", to_upper("HelLo"));
cut_assert_equal_string("HELLO", to_upper("HELLO"));

データ駆動テストでは、テストケースはこのようになります。

cut_assert_equal_string(expected, to_upper(input));

このうち、expectedとinputを外部から与えることになります。Cutterではこのように書きます。

void
data_to_upper (void)
{
#define ADD_DATUM(label, expected, input)             \
  gcut_add_datum(label,                               \
                 "expected", G_TYPE_STRING, expected, \
                 "input", G_TYPE_STRING, input,       \
                 NULL)

    ADD_DATUM("all lower", "HELLO", "hello");
    ADD_DATUM("mixed", "HELLO", "HelLo");
    ADD_DATUM("all upper", "HELLO", "HELLO");

#undef ADD_DATUM
}

void
test_to_upper (gconstpointer data)
{
    const gchar *expected, *input;

    expected = gcut_data_get_string(data, "expected");
    input = gcut_data_get_string(data, "input");
    cut_assert_equal_string(expected, to_upper(input));
}

QtのQtTestLibではこのようになります。 Chapter 2: Data Driven Testingより:

void TestQString::toUpper_data(QtTestTable &t)
{
    t.defineElement("QString", "string");
    t.defineElement("QString", "result");

    *t.newData("all lower") << "hello" << "HELLO";
    *t.newData("mixed")     << "Hello" << "HELLO";
    *t.newData("all upper") << "HELLO" << "HELLO";
}

void TestQString::toUpper()
{
    FETCH(QString, string);
    FETCH(QString, result);

    COMPARE(string.toUpper(), result);
}

ほとんど同じくらいの手間で書けているのではないでしょうか。

テストプログラムは重複があってもいいからわかりやすい方がよい、とよく言われます。しかし、そのために、重複がたくさんある中から、興味がある重複していない部分が見つけづらくなるのは問題かもしれません。データ駆動テストでは、どのようにテストしたいのかがわかりやすいテストケースになる傾向がある気がしています。

データ駆動テストのサポート状況

多くのテスティングフレームワークはデータ駆動テストをサポートしています。PerlのTest::Base、RubyのRSpec2、C++のQtのQtTestLibやGoogle Testでもサポートされています。他にもまだまだたくさんあります。

テストデータの入力方法も様々で、テストプログラム中でテストデータを生成するものから、データベースからテストデータを取り出すもの、CSV、Excelなどから取り出すものもあります。

まとめ

動的に複雑なことができるスクリプト言語、アノテーションなどでメタデータを指定できる最近の言語、トリッキーなC++などでは便利にデータ駆動テストを実行できるテスティングフレームワークは多くあります。しかし、C言語用のフレームワークではそんなになかったのではないかと思います。3

Cutterに興味がある方は使ってみたり、メーリングリストなどで提案、質問などしてみてください。

  1. 他にも空文字列やアルファベット以外が入った文字列などが考えられます。

  2. 動的にspecを定義してね、という方針のようなのでサポートしているというか、Rubyを使っているからできちゃうという感じ

  3. 少なくともまだ見つけられていない。C言語用のテスティングフレームワークのAPIや機能に関してまとまっている場所はあるのだろうか。