C言語・C++言語用単体テスト・ユニットテストフレームワーク - Cutter

はじめに

はじめに — C言語・C++言語用単体テストフレームワークCutterの概要

名前

Cutter

作者

プログラム

  • Kouhei Sutou <kou@clear-code.com>

  • Hiroyuki Ikezoe <ikezoe@clear-code.com>

  • Yuto Hayamizu <y.hayamizu@gmail.com>


きのたんアイコン

  • Mayu & Co.

ライセンス

  • ソースコード: LGPLバージョン3またはそれ以降のバージョン (詳細: license/lgpl-3.txt ) です。

  • ドキュメントときのたんアイコン: LGPLとGFDLとクリエイティ ブ・コモンズ・ライセンスのトリプルライセンス。

  • 例外:

    • glib-compatible/glibintl.h, glib-compatible/gregex.*, glib-compatible/gscripttable.h, glib-compatible/gsequence.*, glib-compatible/gstring.*, glib-compatible/gunicode.h, glib-compatible/guniprop.c: LGPLバージョン2.0またはそれ 以降のバージョン(詳細: glib-compatible/COPYING

    • glib-compatible/pcre/: PCREライセンス (詳細: glib-compatible/pcre/COPYING

    • html/blog.*, html/download.*, html/heading-mark.* html/install.*, html/readme.*, html/reference.*, html/tango-logo.png, html/tutorial.*, html/mini-*.svg: パブリックドメイン。 Tango Desktop Project の成果物を 利用しています。(一部改変しているものもある)

    • html/ja.png, html/us.png, html/famfamfam-logo.png: パブリックドメイン。 famfamfam.com が配布し ている国旗です。

Cutter?

CutterはC言語・C++言語のためのxUnit系の単体テストフレームワー クです。

Cutterの特徴は以下の通りです。

  • テストが簡単に書ける

  • 出力結果がデバッグに使いやすい

  • テストを共有ライブラリとしてビルドする

詳細は 特徴 を見てください。

依存ライブラリ

  • GLib >= 2.16

インストール

インストール を見てください。

リポジトリ

GitHubのclear-code/cutter にあります。

% git clone https://github.com/clear-code/cutter.git

使い方

% cutter [オプション ...] テストディレクトリ

テストディレクトリにはtest_*.soがあるディレクトリを指定しま す。cutterはテストディレクトリ以下にあるtest_*.soを再帰的に 検索します。

詳細は cutter を見てください。

テストの仕方

テストの実行は以下のような流れになります.

  1. テストを作成する

  2. コンパイルし、test_*.soを作成する

  3. cutterを起動し、test_*.soを読み込ませ、テストをする

詳しくは チュートリアル とsample/stack/を参考 にしてください。

テスト結果

テスト結果は例えば以下のようになります。

..........F.................................................

1) Failure: test_test_case_count
<1 == cut_test_case_get_n_tests(test_object, NULL)>
expected: <1>
 but was: <0>
test/test-cut-test-case.c:143: test_test_case_count()

Finished in 0.020857 seconds

60 test(s), 253 assertion(s), 1 failure(s), 0 error(s), 0 pending(s), 0 notification(s)

進行状況

一番上にある「.」と「F」の部分がテストの進行状況を示していま す。

..........F.................................................

各「.」、「F」が1つのテストケース(テスト関数)を表していま す。「.」が成功したテストケース、「F」が失敗したテストケース を表しています。他にも「E」、「P」、「N」があり、それぞれエ ラー、保留、通知を表しています。まとめると以下のようになりま す。

.

成功したテスト

F

表明が失敗したテスト

E

異常終了したテスト

P

保留マークがついているテスト

N

通知が行われたテスト

上記のテストを表す印はテストが実行される毎に出力されます。テ スト実行中は、この出力で実行状況を確認できます。


テスト結果のまとめ

テストが終了すると、テスト結果のまとめを出力します。まとめは、 まず、成功しなかったテストの詳細をそれぞれ表示します。例では 1つ失敗があったのでそれを表示しています。

1) Failure: test_test_case_count
<1 == cut_test_case_get_n_tests(test_object, NULL)>
expected: <1>
 but was: <0>
test/test-cut-test-case.c:143: test_test_case_count()

この例ではtest_test_case_countテストケースが失敗し、 cut_test_case_get_n_tests(test_object, NULL)が1になって欲し かったのに実際は0になっていることを表しています。また、この 失敗した表明はtest/test-cut-test-case.cの143行目、 test_test_case_count()関数内で起こったことがわかります。

テスト結果の詳細一覧の後はテストにかかった時間が表示されます。

Finished in 0.020857 seconds

最後にテスト結果の要約が表示されます。

60 test(s), 253 assertion(s), 1 failure(s), 0 error(s), 0 pending(s), 0 notification(s)

それぞれは以下のような意味です。

n test(s)

n個のテストケース(テスト関数)を実行した

n assertion(s)

n個の表明にパスした

n failure(s)

n個の表明に失敗した

n error(s)

n個の異常事態が発生した(cut_error()を使用した)

n pending(s)

n個のテストケースを保留にした(cut_pending()を使用した)

n notification(s)

n個の通知が発生した(cut_notification()を使用した)

この例では60個のテストケースを実行し、253個の表明にパスし、1 個の表明に失敗したということになります。異常事態や保留にした テストケースなどはありませんでした。


XML出力

--xml-reportオプションを指定することでテスト結果をXML形式で出 力することができます。出力されるXMLは以下のような構造になって います。

<report>
  <!-- テスト結果毎にresultタグを出力する。
       通常は1つのテストにつき1つだが、
       cut_message()を使うと1つのテストにつき複数のテスト結果が含まれる。 -->
  <result>
    <test-case>
      <name>テストケース名</name>
      <description>テストケースの説明(もしあれば)</description>
      <start-time>テストケースの開始時間(ISO 8601形式)[例:2013-11-12T03:32:56.691676Z]</start-time>
      <elapsed>テストケースの実行時間(単位は秒)[例:0.030883]</elapsed>
    </test-case>
    <test>
      <name>テスト名</name>
      <description>テストの説明(もしあれば)</description>
      <start-time>テストの開始時間(ISO 8601形式)[例:2013-11-12T03:32:56.691823Z]</start-time>
      <elapsed>テストの実行時間(単位は秒)[例:0.030883]</elapsed>
      <option><!-- 属性情報(もしあれば) -->
        <name>属性名[例:bug]</name>
        <value>属性値[例:1234]</value>
      </option>
      <option>
        ...
      </option>
      ...
    </test>
    <status>テスト結果(次のうちのどれか:success, notification, omission, pending, failure, error, crash)</status>
    <detail>テスト結果の詳細(もしあれば)</detail>
    <backtrace><!-- バックトレース(もしあれば) -->
      <entry>
        <file>ファイル名</file>
        <line>行</line>
        <info>付加情報</info>
      </entry>
      <entry>
        ...
      </entry>
    </backtrace>
    <start-time>テストの開始時間(ISO 8601形式)[例:2013-11-12T03:32:56.691823Z]</start-time>
    <elapsed>テストの実行時間(単位は秒)[例:0.030883]</elapsed>
  </result>
  <result>
    ...
  </result>
  ...
</report>

テストカバレッジ

システムに LTP tools がイ ンストールされている場合は、Cutterを使ったテストを用いてコー ドカバレッジを出力することができます。カバレッジを出力するに はconfigure.acに以下を追加して、"make coverage"を実行してくだ さい。

AC_CHECK_COVERAGE

リファレンス

表明

cutter/cut-assertions.h を見 てください。


属性

テストに属性を加えて、テスト失敗時により有益な情報を利用する ことができます。例えば、以下のようにテストにBug IDの情報を付 加することができます。

void attributes_invalid_input(void);
void test_invalid_input(void);

void
attributes_invalid_input (void)
{
    cut_set_attributes("bug", "123");
}

void
test_invalid_input (void)
{
    cut_assert_equal("OK", get_input());
}

この例では、test_invalid_inputテストがBug #123のテストである という情報を付加しています。

属性は"「attributes_「テスト名からtest_を除いたもの」"という名 前の関数を定義し、その関数の中でcut_set_attributes()を使って 設定できます。上記の例では「test_invalid_input」テストに 「123」という値の「bug」属性を追加するために 「attributes_invalid_input」という関数を定義し、その中で cut_set_attributes("bug", "123")を呼び、属性を設定しています。


雛型

テストの雛型は以下のようになります.

#include <cutter.h>

#include "自分のプログラムのヘッダファイル"

void test_condition(void);
void test_strstr(void);

static int condition = 0;

void
cut_setup (void)
{
    /* 初期化用コード */
    condition = 1;
}

void
cut_teardown (void)
{
    /* 後片付け用コード */
    condition = 0;
}

void
test_condition(void)
{
    cut_set_message("conditionの値はcut_setup()で1に設定されているはず");
    cut_assert_equal_int(1, condition);
  ...
}

void
test_strstr(void)
{
    cut_assert_equal_string("sub-string",
                            strstr("string sub-string", "sub"));
    ...
}

感謝

  • Kazumasa Matsunagaさん: ビルドの不具合を報告してくれまし た。

  • Daijiro MORIさん: 不具合を報告してくれました。

  • 海野さん:

    • チュートリアルの不具合に気づかせてくれました。

    • Solaris用インストールドキュメントの作成を手伝ってくれ ました。

  • グニャラくん: APIについてアドバイスしてくれました。

  • 山川さん: Cygwinでの動作を教えてくれました。

  • 奥地さん:

    • Localeまわりの不具合を報告してくれました。

    • 新機能を提案してくれました。

  • Zed Shawさん: 不具合を報告してくれました。

  • Romuald Contyさん: ドキュメントの不具合を報告してくれま した。

  • Romain Tartièreさん:

    • 不具合を報告してくれました。

    • 改良方法を提案してくれました。

  • Ilya Baryginさん:

    • テストの不具合を報告してくれました。

  • 中村弘輝さん

    • CentOSでの不具合を報告してくれました。

  • Tobias Gruetzmacherさん:

    • GTK+テストランナーの不具合を直してくれました。