OSDN Git Service

new
authortsutsumi <>
Tue, 23 Sep 2003 21:11:10 +0000 (21:11 +0000)
committertsutsumi <>
Tue, 23 Sep 2003 21:11:10 +0000 (21:11 +0000)
doc/cookbook.dox [new file with mode: 0644]

diff --git a/doc/cookbook.dox b/doc/cookbook.dox
new file mode 100644 (file)
index 0000000..5cebf44
--- /dev/null
@@ -0,0 +1,426 @@
+/* -*- Indented-Text -*- */
+/** @page cookbook CCUnit Cookbook
+
+Here is a short cookbook to help you get started.
+
+@section simple_test_case Simple Test Case
+
+Tests in <b>CCUnit</b> 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.
+
+To make a simple test, here is what you do:
+
+<ol>
+<li> Create a test function
+<li> When you want to check a value, call 
+     @link CCUNIT_ASSERT() CCUNIT_ASSERT(bool) @endlink
+     and pass a bool that is true if the test succeeds
+</ol>
+
+For example, to test that the sum of two Moneys with the
+same currency contains a value which is the sum of the
+values of two Moneys, write:
+
+@code
+void testSimpleAdd ()
+{
+  Money* m120Yen = Money_new (120, "Yen");
+  Money* m140Yen = Money_new (140, "Yen");
+  Money* expected = Money_new (260, "Yen");
+  Money* result = Money_add (m120Yen, m140Yen);
+  CCUNIT_ASSERT (Money_equals (expected, result));
+  Money_delete (m120Yen);
+  Money_delete (m140Yen);
+  Money_delete (expected);
+  Money_delete (result);
+}
+@endcode
+
+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.
+
+@section fixture Fixture
+
+What if you have two or more tests that operate on the same
+similar set of objects?
+
+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.
+
+Often, you will be able to use the same fixture for sevral
+different tests. Each case will send slightly different
+messages or parameteres to the fixture and will check for
+different results.
+
+When you have a common fixture, here is what you do:
+
+<ol>
+<li> Create a @link CCUnitTestCase TestCase @endlink object
+<li> Add an global variable for each part of the fixture
+<li> Write @c setUp() function to initialize the valiables
+<li> Write @c tearDown() to release any permanent resources
+you allocated in @c setUp
+<li> Create a @link CCUnitTestFixture TestFixture @endlink
+object
+<li> Add test case objects to fixture object
+</ol>
+
+For example, to write several test cases that want to work
+with different combinations of 120 Japanese Yen, 140
+Japanese Yen, and 28 US Dollars, first create a fixture:
+
+@code
+/*\* TEST CASE: Money test */
+
+static Money* s120Yen;
+static Money* s140Yen;
+static Money* s23USD;
+
+void setUp_moneyTest ()
+{
+  s120Yen = Money_new (120, "Yen");
+  s140Yen = Money_new (140, "Yen");
+  s23USD = Money_new (23, "USD");
+}
+
+void tearDown_moneyTest ()
+{
+  Money_delete (s120Yen);
+  Money_delete (s140Yen);
+  Money_delete (s23USD);
+}
+
+...
+
+  CCUnitTestFixture* fixture;
+  fixture = ccunit_newTestFixture ("MoneyTest",
+                                   setUp_moneyTest,
+                                   tearDown_moneyTest);
+@endcode
+
+Once you have the Fixture in place, you can write as many
+Test Cases as you'd like.
+
+@section test_case Test Case
+
+How do you write and invoke an individual test case when you
+have a Fixture?
+
+For example, to test the addition of a Money and a MoneyBag,
+write:
+
+@code
+void testMoneyMoneyBag ()
+{
+  Money* bag[] = { s260Yen, s28USD };
+  MoneyBag expected = MoneyBag_new (2, bag);
+  Money* subtotal = Money_add (s120Yen, s28USD);
+  Money* total = Money_add (subtotal, s140Yen);
+  CCUNIT_ASSERT (MoneyBag_equals (expected, total));
+  MoneyBag_delete (expected);
+  Money_delete (subtotal);
+  Money_delete (total);
+}
+
+...
+
+  ccunit_addNewTestCase (fixture,
+                         "testSimpleAdd",
+                         "simple add test",
+                         testSympleAdd);
+  ccunit_addNewTestCase (fixture, 
+                         "testMoneyMoneyBag",
+                         "money bag test",
+                         testMoneyMoneyBag);
+@endcode  
+
+One may create and run objects for each test case like this:
+
+@code
+  CCUnitTestResult* result;
+  result = ccunit_runTestFixture (fixture);
+@endcode
+
+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.
+
+Once you have several tests, organize them into a suite.
+
+@section suite Suite
+
+How do you set up your tests so that you can run them all at once?
+
+%CCUnit provides a @link CCUnitTestSuite TestSuite @endlink
+module that runs any number of TestCases together.
+
+You saw, above, how to run test fixture.
+
+To create a suite of two or more tests, you do the following:
+
+@code
+CCUnitTestSuite* suite;
+CCUnitTestFixture* fixture;
+CCUnitTestResult* result;
+suite = ccunit_newTestSuite ("Money test suite");
+fixture = ccunit_newTestFixture ("Money Tests", setUp_moneyTest, tearDown_moneyTest);
+ccunit_addNewTestCase (fixture,
+                       "testSimpleAdd", "simple add test", testSympleAdd);
+ccunit_addNewTestCase (fixture, 
+                       "testMoneyMoneyBag", "money bag test", testMoneyMoneyBag);
+ccunit_addTestFixture (suite, fixtuer);
+result = ccunit_runTestSuite (suite, NULL);
+@endcode         
+
+@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 in your code and I
+can create one in mine, and we can run them together by
+creating a @link CCUnitTestSuite TestSuite @endlink that
+contains both:
+
+@code
+CCUnitTestSuite* suite;
+CCUnitTestResult* result;
+suite = ccunit_newTestSuite ("suite");
+ccunit_addTestSuite (suite, moneyTestSuite);
+ccunit_addTestSuite (suite, complexNumberTestSuite);
+result = ccunit_runTestSuite(suite, NULL);
+@endcode
+
+
+@section test_runner TestRunner
+
+How do you run your tests and collect their results?
+
+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.
+
+For example, to make a MoneyTest suite available to a 
+@link CreatingTestSuite ccunit_makeSuite @endlink, 
+excute the following tool to 
+MoneyTest.c:
+
+@code
+$ ccunit_makeSuite -f makeSuite -o makeMoneyTestSuite.c MoneyTest.c
+@endcode
+
+@anchor test_runner_code
+To use the TestRunner, include the header files for the tests in Main.c:
+
+@code
+\#include <ccunit/CCUnitTestRunner.h>
+\#include <ccunit/CCUnitTestSuite.h>
+@endcode
+
+And add a call to 
+@link ccunit_addTestSuite()
+ccunit_addTestSuite (CCUnitTestRunner*, CCUnitTestSuite *) @endlink 
+in the <code>main()</code> function:
+
+@code
+extern CCUnitTestSuite* makeSuite ();
+
+int main( int argc, char **argv)
+{
+  CCUnitTestRunner* runner;
+  CCUnitTestSuite* suite;
+  runner = ccunit_newTestRunner (stdout);
+  suite = makeSuite ("MathTest Suite");
+  ccunit_runTestRunner (runner, suite);
+  return 0;
+}
+@endcode
+
+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:
+
+<ul>
+<li> The name of the source file that contains the test</li>
+<li> The line number where the failure occurred</li>
+<li> The name of the test case that failed</li>
+<li> All of the text inside the call to
+     <code>CCUNIT_ASSERT ()</code> which detected the failure</li>
+</ul>
+
+@section helper_macros Helper Tool
+
+As you might have noticed, implementing the fixture
+<code>suite ()</code> function is a repetitive and error
+prone task. A @ref CreatingTestSuite set of functions and
+command have been created to automatically implements the
+<code>suite()</code> method.
+
+The following code is a rewrite of MoneyTest using those command:
+
+@code
+\#include <cppunit/CCUnitAssert.h>
+@endcode
+
+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 <tt>*</tt>'s:
+
+@code
+/*\* test case: Money test */
+@endcode
+
+The suite created by the <code>ccunit_suite()</code>
+function is specified <code>-f</code> option of command
+<code>ccunit_makeSuite</code>.  Then, you define each test
+case of the fixture with prefix <code>test</code>,
+<code>setUp</code>, <code>tearDown</code>:
+
+@code
+static Money* s120Yen;
+static Money* s140Yen;
+static Money* s260Yen;
+static Money* s23USD;
+
+void setUp_MathTest ()
+{
+  s120Yen = Money_new (120, "Yen");
+  s140Yen = Money_new (140, "Yen");
+  s260Yen = Money_new (260, "Yen");
+  s23USD = Money_new (23, "USD");
+}
+
+void tearDown_Mathtest ()
+{
+  Money_delete (s120Yen);
+  Money_delete (s140Yen);
+  Money_delete (s260Yen);
+  Money_delete (s23USD);
+}
+
+/*\* simple add test */
+void test_simpleAdd ()
+{
+  Money* result = Money_add (s120Yen, s140Yen);
+  CCUNIT_ASSERT (Money_equals (s260Yen, result));
+  Money_delete (result);
+}
+
+/*\* money bug test */
+void test_moneyBag()
+{
+  Money* bag[] = { s260Yen, s28USD };
+  MoneyBag expected = MoneyBag_new (2, bag);
+  Money* subtotal = Money_add (s120Yen, s28USD);
+  Money* total = Money_add (subtotal, s140Yen);
+  CCUNIT_ASSERT (MoneyBag_equals (expected, total));
+  MoneyBag_delete (expected);
+  Money_delete (subtotal);
+  Money_delete (total);
+}
+@endcode
+
+Finally, you end the fixture declaration:
+
+@code
+/*\* end test case */
+@endcode
+
+To generate creating suite function code, run
+<code>ccunit_makeSuite</code> tool.
+
+@code
+$ ccunit_makeSuite MoneyTest.c
+
+\#include <ccunit/CCUnitTestSuite.h>
+
+static CCUnitTestSuite* newSuite_001 (const char* name);
+/* test fixture: Money test */
+/* setUp_MathTest */
+extern void setUp_MathTest ();
+/* tearDown_Mathtest */
+extern void tearDown_Mathtest ();
+/* simple add test */
+extern void test_simpleAdd ();
+/* money bug test */
+extern void test_moneyBag ();
+
+static CCUnitTestSuite* newSuite_001 (const char* name)
+{
+  CCUnitTestSuite* suite;
+  suite = ccunit_newTestSuite (name);
+  {
+    CCUnitTestFixture* testFixture;
+    testFixture = ccunit_newTestFixture ("Money test",
+                                         setUp_MathTest,
+                                         tearDown_Mathtest);
+    if (testFixture != NULL)
+      ccunit_addTestFixture (suite, testFixture);
+    {
+      CCUnitTestCase* newCase;
+      newCase = ccunit_newTestCase ("test_simpleAdd",
+                                    "simple add test",
+                                    test_simpleAdd);
+      if (newCase != NULL)
+        ccunit_addTestCase (testFixture, newCase);
+    }
+    {
+      CCUnitTestCase* newCase;
+      newCase = ccunit_newTestCase ("test_moneyBag",
+                                    "money bug test",
+                                    test_moneyBag);
+      if (newCase != NULL)
+        ccunit_addTestCase (testFixture, newCase);
+    }
+  }
+
+  return suite;
+}
+
+
+CCUnitTestSuite* ccunit_suite (const char* name)
+{
+  return newSuite_001 (name);
+}
+$
+@endcode
+
+@section post_build_check Post-build check
+
+Now that we have our unit tests running, how about
+integrating unit testing to our build process ?
+
+To do that, the application must returns a value different than 0 to indicate that
+there was an error.
+
+@link ccunit_runTestRunner() ccunit_runTestRunner() @endlink returns 
+a integer indicating if the run was successful.
+
+Updating our main programm, we obtains:
+@code
+\#include <ccunit/TestRunner.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;
+}
+@endcode
+
+Now, you need to run your application after compilation.
+
+*/