View クックブックcategory(Tag) treefile info
CCUnit クックブックこれは CCUnit を使い始めるにあたって、 理解の助けとなるような短いクックブックです。[see also English documents] シンプルなテストケースCCUnitを使ったテストは自動的に実行することができます。 CCUnit のテストは簡単にセットアップすることができ、 一度テストを書いてしまえば、 いつでもプログラムの品質を信頼できるものに保つことができるでしょう。単純なテストを作るには、次のようにします。
例えば、二つの複素数の合計が、 二つの複素数の値を加算した値と同じであることをテストするとします。
void test_complex_add () { complex_t c10_1 = { 10.0, 1.0 }; complex_t c1_1 = { 1.0, 1.0 }; complex_t result; complex_t c11_2 = { 11.0, 2.0 }; CCUNIT_ASSERT (complex_equals (&c11_2, complex_add (&result, c10_1, c1_1))); } これは大変単純なテストです。 通常、同じデータのセットで走らせるために、 たくさんの小さなテストケースを作らなければならないでしょう。 そうするにはフィクスチャ(備品)を使います。 フィクスチャもし二つ以上のテストがあるなら、 同じ類似のデータのセットで操作するのではないでしょうか。テストは周知のデータのセットを背景にして実行される必要があります。 このデータのセットをフィクスチャと呼ぶことにします。 テストを書いていると、 実際のテストする値をフィクスチャにセットアップするコードを書く方に、 もっと時間をかけていることに気づくことがよくあります。 多くの場合、いくつかの異なったテストのために同じフィクスチャを使うことができます。 それぞれのテストケースは少し異なったメッセージ、 あるいはパラメータをフィクスチャに送り、 異なる結果を調べます。 もし共通するフィクスチャがあれば、こんなふうにすることになり ます。
例えば、いくつかのテストケースを書く場合、 最初にフィクスチャを作成します。
/** TEST CASE: complex number test */ #include "complex.h" static complex_t* s10_1; static complex_t* s1_1; static complex_t* s11_2; void setUp_ComplexTest () { s10_1 = complex_new (10, 1); s1_1 = complex_new (1, 1); s11_2 = complex_new (11, 2); } void tearDown_ComplexTest () { complex_delete (s10_1); complex_delete (s1_1); complex_delete (s11_2); } ... CCUnitTestFixture* fixture; fixture = ccunit_newTestFixture ("ComplexTest", CCUNIT_NEWTESTFUNC(setUp_ComplexTest), CCUNIT_NEWTESTFUNC(tearDown_ComplexTest)); 一度決まったところにフィクスチャを書いてしまえば、 あなたが好きなように複素数のテストケースを書くことができます。 テストケースフィクスチャを一つ書いたとして、 どうやって個々のテストケースを書いて実行すれば良いでしょうか。例えば、二つの複素数が等しい(または等しくない)ことをテストするには、 次のように書きます。
void test_complex_equals () { CCUNIT_ASSERT_TEST_OBJ (s10_1, complex_equals, s10_1, complex_to_string); CCUNIT_ASSERT_TEST_OBJ (s10_1, !complex_equals, s1_1, complex_to_string); } ... ccunit_addNewTestCase (fixture, "test_complex_equals", "complex equals test", test_complex_equals); ccunit_addNewTestCase (fixture, "test_complex_add", "complex add test", test_complex_add); 一つには次のように、 フィクスチャを作成してそれぞれのテストケースを実行させること ができます。
CCUnitTestResult* result; result = ccunit_runTestFixture (fixture); テストフィクスチャが実行されると、 特定のテスト関数が呼び出されます。 これはあまり便利ではありません、 なぜなら、診断が表示されないからです。 通常は TestRunner (テストランナー 後述) で結果を表示します。 一度いくつかのテストを作ったら、 それらをスイートに整理します。 スイートどのようにして、一度にテストを実行することができるよう、 準備したらいいでしょうか?CCUnit はいくつもの TestCases を一緒に実行する TestSuite モジュールを提供します。 テストフィクスチャを実行する方法は上述しました。 二つ以上のテストを含む一つのスイートを作るには、次のようにします。
CCUnitTestSuite* suite; CCUnitTestFixture* fixture; CCUnitTestResult* result; suite = ccunit_newTestSuite ("Complex test suite"); fixture = ccunit_newTestFixture ("Complex Tests", CCUNIT_NEWTESTFUNC(setUp_complex_test), CCUNIT_NEWTESTFUNC(tearDown_complex_test)); ccunit_addNewTestCase (fixture, "test_complex_equals", "complex equals test", test_complex_equals); ccunit_addNewTestCase (fixture, "test_complex_add", "complex add test", test_complex_add); ccunit_addNewTestCase (fixture, "test_complex_sub", "complex sub test", test_complex_sub); ccunit_addTestFixture (suite, fixtuer); result = ccunit_runTestSuite (suite, NULL); TestSuites は TestFixtures を含むだけではありません。 それらは Test インタフェースを実装するどんなオブジェクトでも含められます。 例えば、あなたはあなたのコードにTestSuite を作ることができ、そして私は私のスイートを作ることができます、 そして私達は両方ともを含んでいる TestSuite を作って一緒に個々のスイートを動かすことができるのです。
CCUnitTestSuite* suite; CCUnitTestResult* result; suite = ccunit_newTestSuite ("suite"); ccunit_addTestSuite (suite, complex_add_sub_suite ()); ccunit_addTestSuite (suite, complex_mul_div_suite ()); result = ccunit_runTestSuite(suite, NULL); テストランナーどうやってテストを実行し、その結果を集めたら良いでしょうか。一つテストスイートを書いたら、 それを実行したいでしょう。 CCUnit はスイートを実行するために定義し、 結果を表示するためのツールを提供します。 スーツをccunit_makeSuite ツールに入力できるような形式で書くことで、 テストスーツを作成するコードを自動的に生成することができます。 例えば、ComplexTest スイートを ccunit_makeSuite を使って使用できるようにするには、 以下のツールを ComplexTest.c に実行します。
$ ccunit_makeSuite -f complex_suite -o suiteComplex.c ComplexTest.c TestRunner を使用するには、 Main.cでテストのためのファイルのヘッダをインクルードします。
#include <ccunit/CCUnitTestRunner.h> #include <ccunit/CCUnitTestSuite.h>
そしてccunit_runTestRunner (CCUnitTestRunner*, CCUnitTestSuite *) を
extern CCUnitTestSuite* complex_suite(const char* name); int main( int argc, char **argv) { CCUnitTestRunner* runner; CCUnitTestSuite* suite; runner = ccunit_newTestRunner (stdout); suite = complex_suite ("complex test suite"); return ccunit_runTestRunner (runner, suite); } TestRunner はテストを実行します。 もしすべてのテストがパスすれば、その情報のメッセージが表示されます。 もしどれかが失敗すれば、それについて以下のような情報が表示されます。
ヘルパーツールお気づきのように、フィクスチャのsuite () 関数を実装するのは、 反復的で間違いやすい作業です。 Creating TestSuite の関数のセットとコマンドはsuite () 関数の実装を自動的に作成することができます。
以下のコードはそれらのコマンドが使うようにComplexTestを書換えたものです。
#include <cppunit/CCUnitAssert.h>
最初に、フィクスチャを宣言します。 これはjavaDocスタイルのコメント内にフィクスチャの名前を記述します。 javaDocスタイルのコメントとは C スタイルのコメントブロックの開始が 二つのアスタリスク
/** test case: complex number test */
TestSuite を作成する関数は
#include <complex.h> static complex_t* s10_1; static complex_t* s1_1; static complex_t* s11_2; void setUp_complex_test () { s10_1 = complex_new (10, 1); s1_1 = complex_new (1, 1); s11_2 = complex_new (11, 2); } void tearDown_complex_test () { complex_delete (s10_1); complex_delete (s1_1); complex_delete (s11_2); } /** test equals */ void test_complex_equals () { CCUNIT_ASSERT_TEST_OBJ (s10_1, complex_equals, s10_1, complex_to_string); CCUNIT_ASSERT_TEST_OBJ (s10_1, !complex_equals, s1_1, complex_to_string); } /** test add */ void test_complex_add () { complex_t c10_1 = { 10.0, 1.0 }; complex_t c1_1 = { 1.0, 1.0 }; complex_t result; complex_t c11_2 = { 11.0, 2.0 }; CCUNIT_ASSERT (complex_equals (&c11_2, complex_add (&result, &c10_1, &c1_1))); } /** test sub */ void test_complex_sub () { complex_t c9_0 = { 9, 0 }; complex_t result; CCUNIT_ASSERT_TEST_OBJ (&c9_0, complex_equals, complex_sub (&result, s10_1, s1_1), complex_to_string); } 最後に、フィクスチャの終りを宣言します。
/** end test case */
スイート作成関数のコードを生成するには、
$ ccunit_makeSuite -f complex_suite -o suiteComplex.c testComplex.c $ cat suiteComplex.c #include <ccunit/CCUnitTestSuite.h> #include <ccunit/CCUnitTestFixture.h> #include <ccunit/CCUnitTestCase.h> /* test fixture: complex number test */ /* setUp_complex_test */ extern void setUp_complex_test (); /* tearDown_complex_test */ extern void tearDown_complex_test (); /* test_complex_equals */ extern void test_complex_equals (); /* test_complex_add */ extern void test_complex_add (); /* test_complex_sub */ extern void test_complex_sub (); static CCUnitTestFunc fx_001_cases[] = { { "test_complex_equals", "test equals", test_complex_equals }, { "test_complex_add", "test add", test_complex_add }, { "test_complex_sub", "test sub", test_complex_sub }, { NULL, NULL, NULL }, }; static CCUnitTestFixtureDfn fx_001 = { { ccunitTypeFixture }, "complex number test", { "setUp_complex_test", "setUp_complex_test", setUp_complex_test }, { "tearDown_complex_test", "tearDown_complex_test", tearDown_complex_test }, fx_001_cases, }; static CCUnitTestDfn* suite_001_test[] = { &fx_001.test, NULL, }; static CCUnitTestSuiteDfn suite_001 = { { ccunitTypeSuite }, "", suite_001_test }; CCUnitTestSuite* complex_suite (const char* name) { if (!suite_001.name[0]) suite_001.name = name; return ccunit_newTestSuiteFromDfn (&suite_001); } $ ビルド後のチェックさあユニットテストを実行する準備ができました。 ではビルドプロセスにユニットテストを統合するにはどうしたらい いでしょう。そうするには、アプリケーションは、エラーが発生したことを示す 0以外の値を返さなければなりません。 ccunit_runTestRunner() は、実行が成功したかどうかを示す整数を返します。 次のようにメインプログラムを更新します。
#include <ccunit/CCUnitTestRunner.h> int main (int argc, char** argv) { CCUnitTestRunner* runner; CCUnitTestSuite* suite; int wasSucessful; runner = ccunit_newTestRunner (stdout); suite = ccunit_suite (); wasSucessful = ccunit_runTestRunner (runner, suite); return wasSucessful; } それではアプリケーションをコンパイルした後に実行してみましょ う。 以上で作成したサンプルプログラムは example/complex ディレク トリにあります。
|