/* -*- Indented-Text -*- */ /* Copyright (C) 2003, 2010 TSUTSUMI Kikuo. This file is part of the CCUnit Library. The CCUnit Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The CCUnit Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the CCUnit Library; see the file COPYING.LESSER. If not, see */ /* $Id$ */ /** @english @page cookbook CCUnit Cookbook @japanese @page cookbook CCUnit クックブック @endif @~english Here is a short cookbook to help you get started. @~japanese これは CCUnit を使い始めるにあたって、 理解の助けとなるような短いクックブックです。 @~ @english [see also Japanese documents] @japanese [see also English documents] @endif @english @section simple_test_case Simple Test Case @japanese @section simple_test_case シンプルなテストケース @endif @~english Tests in CCUnit can be run automatically. They are easy to set up and once you have written them, they are always there to help you keep confidence in the quality of your code. @~japanese CCUnitを使ったテストは自動的に実行することができます。 CCUnit のテストは簡単にセットアップすることができ、 一度テストを書いてしまえば、 いつでもプログラムの品質を信頼できるものに保つことができるでしょう。 @~ @~english To make a simple test, here is what you do: @~japanese 単純なテストを作るには、次のようにします。 @~
  1. @~english Create a test function @~japanese テスト関数を作る @~
  2. @~english When you want to check a value, call @~japanese 値をチェックしたい場合は、@~ @link CCUNIT_ASSERT() CCUNIT_ASSERT(bool) @endlink @~english and pass a bool that is true if the test succeeds @~japanese を呼び出して、 もしテストが成功するなら真を返すような真偽値を渡します@~ @~english ASSERT macro is listed in others as well in @link Assertions Making assertions @endlink. @~japanese ASSERT 関係のマクロは他にも @link Assertions Making assertions @endlink にリストしてあります。 @~
@~english For example, to test that the sum of two complex number which is the sum of the values of two complex numbers, write: @~japanese 例えば、二つの複素数の合計が、 二つの複素数の値を加算した値と同じであることをテストするとします。 (ここで使用するサンプルプログラムは examples/complex ディレクトリにあります。) @~ @~english This sample program is in the examples/complex directory. @~ @code 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))); } @endcode @~english That was a very simple test. Ordinarily, you'll have many little test cases that you'll want to run on the same set of objects. To do this, use a fixture. @~japanese これは大変単純なテストです。 通常、同じデータのセットで走らせるために、 たくさんの小さなテストケースを作らなければならないでしょう。 そこでフィクスチャ(備品)を使います。 @~ @english @section fixture Fixture @japanese @section fixture フィクスチャ @endif @~english What if you have two or more tests that operate on the same similar set of objects? @~japanese もし二つ以上のテストがあるなら、 同じ類似のデータのセットで操作するのではないでしょうか。 @~ @~english Tests need to run against the background of a known set of objects. This set of objects is called a test fixture. When you are writing tests you will often find that you spend more time writing the code to set up the fixture than you do in actually testing values. @~japanese テストは周知のデータのセットを背景にして実行される必要があります。 このデータのセットをフィクスチャと呼ぶことにします。 テストを書いていると、 実際のテストする値をフィクスチャにセットアップするコードを書く方に、 より時間をかけていることに気づくことがよくあります。 @~ @~english Often, you will be able to use the same fixture for several different tests. Each case will send slightly different messages or parameters to the fixture and will check for different results. @~japanese 多くの場合、いくつかの異なったテストのために同じフィクスチャを使うことができます。 それぞれのテストケースは少し異なったメッセージ、 あるいはパラメータをフィクスチャに送り、 異なる結果を調べます。 @~ @~english When you have a common fixture, here is what you do: @~japanese もし共通するフィクスチャがあれば、こんなふうにすることになります。 @~
  1. @~english Create a @link CCUnitTestCase TestCase @endlink object @~japanese @link CCUnitTestCase TestCase @endlink 構造体にメモリを割り当てます (以降、構造体に割り当てたメモリを、オブジェクトと呼ぶことにします) @~
  2. @~english Add an global variable for each part of the fixture @~japanese フィクスチャのそれぞれの部分に大域変数を追加します @~
  3. @~english Write setUp() function to initialize the valiables @~japanese setUp() 関数を書いて変数を初期化します @~
  4. @~english Write tearDown() to release any permanent resources you allocated in setUp @~japanese tearDown() 関数を書いてsetUp で割り当てた永続的リソースを解放します @~
  5. @~english Create a @link CCUnitTestFixture TestFixture @endlink object @~japanese @link CCUnitTestFixture CCUnitTestFixture @endlink 構造体にメモリを割り当てます @~
  6. @~english Add @link CCUnitTestCase TestCase @endlink objects to fixture object @~japanese @link CCUnitTestCase TestCase @endlink オブジェクトを @link CCUnitTestFixture TestFixture @endlink フィクスチャオブジェクトに登録します。 @~
@~english For example, to write several test cases, first create a fixture: @~japanese 例えば、いくつかのテストケースを書く場合、 最初にフィクスチャを作成します。 @~ @code //** 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_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); } ... CCUnitTestFixture* fixture; fixture = ccunit_newTestFixture ("complex test", CCUNIT_NEWTESTFUNC(setUp_complex_test), CCUNIT_NEWTESTFUNC(tearDown_complex_test)); @endcode @~english Once you have the Fixture in place, you can write as complex Test Cases as you'd like. @~japanese 一度決まったところにフィクスチャを書いてしまえば、 あなたが好きなように複素数のテストケースを書くことができます。 @~ @english @section test_case Test Case @japanese @section test_case テストケース @endif @~english How do you write and invoke an individual test case when you have a Fixture? @~japanese フィクスチャを一つ書いたとして、 どうやって個々のテストケースを書いて実行すれば良いでしょうか。 @~ @~english For example, to test the equality of two complex number, write: @~japanese 例えば、二つの複素数が等しい(または等しくない)ことをテストするには、 次のように書きます。 @~ @code 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); @endcode @~english One may create and run objects for each test case like this: @~japanese 一つには次のように、 フィクスチャを作成してそれぞれのテストケースを実行させることができます。 @~ @code CCUnitTestResult* result; result = ccunit_runTestFixture (fixture); @endcode @~english When the test fixture is run, that specific test functions will be run. This is not a useful thing to do, however, as no diagnostics will be displayed. One will normally use a @link ExecutingTest TestRunner @endlink (see below) to display the results. @~japanese テストフィクスチャが実行されると、 特定のテスト関数が呼び出されます。 これはあまり便利ではありません、 なぜなら、診断が表示されないからです。 通常は @link ExecutingTest TestRunner @endlink (@ref test_runner 後述) で結果を表示します。 @~ @~english Once you have several tests, organize them into a suite. @~japanese 一度いくつかのテストを作ったら、 それらをスーツに整理します。 @~ @english @section suite Suite @japanese @section suite スーツ @endif @~english How do you set up your tests so that you can run them all at once? @~japanese 一度にテストを実行することができるように準備するには、 どのようにしたらいいでしょうか? @~ @~english CCUnit provides a @link CCUnitTestSuite TestSuite @endlink module that runs any number of TestCases together. @~japanese CCUnit はいくつもの @link CCUnitTestCase TestCases @endlink を一緒に実行する @link CCUnitTestSuite TestSuite @endlink モジュールを提供します。 @~ @~english You saw, above, how to run test fixture. @~japanese テストフィクスチャを実行する方法は上述しました。 @~ @~english To create a suite of two or more tests, you do the following: @~japanese 二つ以上のテストを含む一つのスーツを作るには、次のようにします。 @~ @code 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); @endcode @~english @link CCUnitTestSuite TestSuites @endlink don't only have to contain @link CCUnitTestFixture TestFixtures @endlink. They can contain any object that implements the @link CCUnitTest Test @endlink interface. For example, you can create a @link CCUnitTestSuite TestSuite @endlink (complex_add_sub_suite ()) in your code and I can create one in mine (complex_mul_div_suite ()), and we can run them together by creating a @link CCUnitTestSuite TestSuite @endlink that contains both: @~japanese @link CCUnitTestSuite TestSuites @endlink は @link CCUnitTestFixture TestFixtures @endlink を含むだけではありません。 @link CCUnitTestSuite TestSuites @endlink 自身を含むこともできます。 例えば、あなたはあなたのコードに @link CCUnitTestSuite TestSuite @endlink (complex_add_sub_suite ()) を作ることができ、 そして私は私のスーツ (complex_mul_div_suite ()) を作ることができます、 そして私達は両方ともを含んでいる @link CCUnitTestSuite TestSuite @endlink を作って一緒にそれぞれのスーツを動かすことができるのです。 @~ @code CCUnitTestSuite* suite; CCUnitTestResult* result; suite = ccunit_newTestSuite ("Complex add/sub/mul/div test suite"); ccunit_addTestSuite (suite, complex_add_sub_suite ()); ccunit_addTestSuite (suite, complex_mul_div_suite ()); result = ccunit_runTestSuite(suite, NULL); @endcode @english @section test_runner TestRunner @japanese @section test_runner テストランナー @endif @~english How do you run your tests and collect their results? @~japanese どうやってテストを実行し、その結果を集めたら良いでしょうか。 @~ @~english Once you have a test suite, you'll want to run it. %CCUnit provides tools to define the suite to be run and to display its results. You make your suite accessible to a @link CreatingTestSuite ccunit_makeSuite @endlink tool that generate a creating test suite code. @~japanese 一つテストスーツを書いたら、 それを実行したいでしょう。 CCUnit はスーツを実行するために定義し、 結果を表示するためのツールを提供します。 スーツを @link CreatingTestSuite ccunit_makeSuite @endlink ツールに入力できるような形式で書くことで、 テストスーツを作成するコードを自動的に生成することができます。 @~ @~english For example, to make a ComplexTest suite available to a @link CreatingTestSuite ccunit_makeSuite @endlink, excute the following tool to testComplex.c: @~japanese 例えば、ComplexTest スーツを @link CreatingTestSuite ccunit_makeSuite @endlink を使って使用できるようにするには、 以下のツールを testComplex.c に実行します。 @~ @code $ ccunit_makeSuite -f complex_suite -o suiteComplex.c testComplex.c @endcode @anchor test_runner_code @~english @~japanese complex_suite という関数が定義された、 suiteComplex.c というファイルが作成されます。 @~ @~english To use the TestRunner, include the header files for the tests in runTest.c: @~japanese TestRunner を使用するには、 例えば runTest.c でテストのためのファイルのヘッダをインクルードします。 @~ @code #include #include @endcode @~english And call to @link ccunit_runTestRunner() ccunit_runTestRunner (CCUnitTestRunner*, CCUnitTestSuite *) @endlink in the main() function: @~japanese そして@link ccunit_runTestRunner() ccunit_runTestRunner (CCUnitTestRunner*, CCUnitTestSuite *) @endlink をmain()関数で実行します。 @~ @code 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); } @endcode @~english The @link ExecutingTest TestRunner @endlink will run the tests. If all the tests pass, you'll get an informative message. If any fail, you'll get the following information: @~japanese @link ExecutingTest TestRunner @endlink はテストを実行します。 もしすべてのテストがパスすれば、その情報のメッセージが表示されます。 もしどれかが失敗すれば、それについて以下のような情報が表示されます。 @~
  • @~english The name of the source file that contains the test @~japanese テストを含んでいるソースファイル名 @~
  • @~english The line number where the failure occurred @~japanese 失敗が起こった行番号 @~
  • @~english The name of the test case that failed @~japanese 失敗したテストケースの名前 @~
  • @~english All of the text inside the call to CCUNIT_ASSERT () which detected the failure @~japanese 失敗を検知したCCUNIT_ASSERT ()が呼び出された時の条件の文字列。 @~
@english @section helper_macros Helper Tool @japanese @section helper_macros ヘルパーツール @endif @~english As you might have noticed, implementing the suite () function of fixture is a repetitive and error prone task. A @ref CreatingTestSuite set of functions and command have been created to automatically implements the suite() function. @~japanese お気づきのように、フィクスチャの suite ()関数を実装するのは、 反復的で間違いやすい作業です。 @ref CreatingTestSuite の関数のセットとコマンドはsuite () 関数の実装を自動的に作成することができます。 @~ @dontinclude complex/testComplex.c @~english The following code is a rewrite of ComplexTest using those command: @~japanese 以下のコードはそれらのコマンドが使うようにComplexTestを書換えたものです。 @~ @code #include @endcode @~english First, you declare the fixture, passing the test fixture name to the javaDoc style comment, which consist of a C-style comment block starting with two *'s: @~japanese 最初に、フィクスチャを宣言します。 これはjavaDocスタイルのコメント内にフィクスチャの名前を記述します。 javaDocスタイルのコメントとは C スタイルのコメントブロックの開始が 二つのアスタリスク ** になっているものです。 @~ @code //** test case: complex number test *\/ @endcode @~english The function to make @link CCUnitTestSuite TestSuite @endlink is ccunit_suite. But, it can be changed to another name by the -f option of the ccunit_makeSuite command, too. Then, you define each test case of the fixture with prefix test, setUp, tearDown: @~japanese @link CCUnitTestSuite TestSuite @endlink を作成する関数は ccunit_suite です、 しかし ccunit_makeSuite コマンドの -f オプションで別の名前に変えることもできます。 そして、フィクスチャのテストケースにはそれぞれ名前の先頭に、 test, setUp, tearDown をつけてください。 @~ @code #include 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); } @endcode @~english Finally, you end the fixture declaration: @~japanese 最後に、フィクスチャの終りを宣言します。 @~ @code //** end test case *\/ @endcode @~english To generate creating suite function code, run ccunit_makeSuite tool. @~japanese スーツ作成関数のコードを生成するには、 ccunit_makeSuiteツールを実行します。 @~ @code $ ccunit_makeSuite -f complex_suite -o suiteComplex.c testComplex.c $ cat suiteComplex.c #include #include #include //* 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); } $ @endcode @english @section post_build_check Post-build check @japanese @section post_build_check ビルド後のチェック @endif @~english Now that we have our unit tests running, how about integrating unit testing to our build process ? @~japanese さあユニットテストを実行する準備ができました。 ではビルドプロセスにユニットテストを統合するにはどうしたらい いでしょう。 @~ @~english To do that, the application must returns a value different than 0 to indicate that there was an error. @~japanese そうするには、アプリケーションは、エラーが発生したことを示す 0以外の値を返さなければなりません。 @~ @~english @link ccunit_runTestRunner() ccunit_runTestRunner() @endlink returns a integer indicating if the run was successful. @~japanese @link ccunit_runTestRunner() ccunit_runTestRunner() @endlink は、実行が成功したかどうかを示す整数を返します。 @~ @~english Updating our main programm, we obtains: @~japanese 次のようにメインプログラムを更新します。 @~ @code #include 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; } @endcode @~english Now, you need to run your application after compilation. The sample program made in the above is in the examples/complex directory. @~japanese それではアプリケーションをコンパイルした後に実行してみましょう。 以上で作成したサンプルプログラムは examples/complex ディレクトリにあります。 @~ */