1 /* -*- Indented-Text -*- */
3 /** @page cookbook CCUnit Cookbook
5 Here is a short cookbook to help you get started.
7 @section simple_test_case Simple Test Case
9 Tests in <b>CCUnit</b> can be run automatically. They are
10 easy to set up and once you have written them, they are
11 always there to help you keep confidence in the quality of
14 To make a simple test, here is what you do:
17 <li> Create a test function</li>
18 <li> When you want to check a value, call
19 @link CCUNIT_ASSERT() CCUNIT_ASSERT(bool) @endlink
20 and pass a bool that is true if the test succeeds</li>
23 For example, to test that the sum of two Moneys with the
24 same currency contains a value which is the sum of the
25 values of two Moneys, write:
30 Money* m120JPY = Money_new (120, "JPY");
31 Money* m140JPY = Money_new (140, "JPY");
32 Money* expected = Money_new (260, "JPY");
33 Money* result = Money_add (m120JPY, m140JPY);
34 CCUNIT_ASSERT (Money_equals (expected, result));
35 Money_delete (m120JPY);
36 Money_delete (m140JPY);
37 Money_delete (expected);
38 Money_delete (result);
42 That was a very simple test. Ordinarily, you'll have many
43 little test cases that you'll want to run on the same set of
44 objects. To do this, use a fixture.
46 @section fixture Fixture
48 What if you have two or more tests that operate on the same
49 similar set of objects?
51 Tests need to run against the background of a known set of
52 objects. This set of objects is called a test fixture. When
53 you are writing tests you will often find that you spend
54 more time writing the code to set up the fixture than you do
55 in actually testing values.
57 Often, you will be able to use the same fixture for sevral
58 different tests. Each case will send slightly different
59 messages or parameteres to the fixture and will check for
62 When you have a common fixture, here is what you do:
65 <li>Create a @link CCUnitTestCase TestCase @endlink object</li>
66 <li>Add an global variable for each part of the fixture</li>
67 <li>Write <code>setUp()</code> function to initialize the valiables</li>
68 <li>Write <code>tearDown()</code> to release any permanent
69 resources you allocated in <code>setUp</code></li>
70 <li>Create a @link CCUnitTestFixture TestFixture @endlink object</li>
71 <li>Add test case objects to fixture object</li>
74 For example, to write several test cases that want to work
75 with different combinations of 120 Japanese Yen, 140
76 Japanese Yen, and 28 US Dollars, first create a fixture:
79 //** TEST CASE: Money test *\/
83 static Money* s120JPY;
84 static Money* s140JPY;
87 void setUp_moneyTest ()
89 s120JPY = Money_new (120, "JPY");
90 s140JPY = Money_new (140, "JPY");
91 s23USD = Money_new (23, "USD");
94 void tearDown_moneyTest ()
96 Money_delete (s120JPY);
97 Money_delete (s140JPY);
98 Money_delete (s23USD);
103 CCUnitTestFixture* fixture;
104 fixture = ccunit_newTestFixture ("MoneyTest",
109 Once you have the Fixture in place, you can write as many
110 Test Cases as you'd like.
112 @section test_case Test Case
114 How do you write and invoke an individual test case when you
117 For example, to test the addition of a Money and a MoneyBag,
121 void testMoneyMoneyBag ()
123 Money* bag[] = { s260JPY, s28USD };
124 MoneyBag expected = MoneyBag_new (2, bag);
125 Money* subtotal = Money_add (s120JPY, s28USD);
126 Money* total = Money_add (subtotal, s140JPY);
127 CCUNIT_ASSERT (MoneyBag_equals (expected, total));
128 MoneyBag_delete (expected);
129 Money_delete (subtotal);
130 Money_delete (total);
135 ccunit_addNewTestCase (fixture,
139 ccunit_addNewTestCase (fixture,
145 One may create and run objects for each test case like this:
148 CCUnitTestResult* result;
149 result = ccunit_runTestFixture (fixture);
152 When the test fixture is run, that specific test functions
153 will be run. This is not a useful thing to do, however, as
154 no diagnostics will be displayed. One will normally use a
155 @link ExecutingTest TestRunner @endlink (see below) to
158 Once you have several tests, organize them into a suite.
162 How do you set up your tests so that you can run them all at once?
164 %CCUnit provides a @link CCUnitTestSuite TestSuite @endlink
165 module that runs any number of TestCases together.
167 You saw, above, how to run test fixture.
169 To create a suite of two or more tests, you do the following:
172 CCUnitTestSuite* suite;
173 CCUnitTestFixture* fixture;
174 CCUnitTestResult* result;
175 suite = ccunit_newTestSuite ("Money test suite");
176 fixture = ccunit_newTestFixture ("Money Tests", setUp_moneyTest, tearDown_moneyTest);
177 ccunit_addNewTestCase (fixture,
178 "testSimpleAdd", "simple add test", testSympleAdd);
179 ccunit_addNewTestCase (fixture,
180 "testMoneyMoneyBag", "money bag test", testMoneyMoneyBag);
181 ccunit_addTestFixture (suite, fixtuer);
182 result = ccunit_runTestSuite (suite, NULL);
185 @link CCUnitTestSuite TestSuites @endlink don't only have to
186 contain @link CCUnitTestFixture TestFixtures @endlink. They
187 can contain any object that implements the @link CCUnitTest
188 Test @endlink interface. For example, you can create a
189 @link CCUnitTestSuite TestSuite @endlink in your code and I
190 can create one in mine, and we can run them together by
191 creating a @link CCUnitTestSuite TestSuite @endlink that
195 CCUnitTestSuite* suite;
196 CCUnitTestResult* result;
197 suite = ccunit_newTestSuite ("suite");
198 ccunit_addTestSuite (suite, moneyTestSuite);
199 ccunit_addTestSuite (suite, complexNumberTestSuite);
200 result = ccunit_runTestSuite(suite, NULL);
204 @section test_runner TestRunner
206 How do you run your tests and collect their results?
208 Once you have a test suite, you'll want to run it. %CCUnit
209 provides tools to define the suite to be run and to display
210 its results. You make your suite accessible to a @link
211 CreatingTestSuite ccunit_makeSuite @endlink tool that generate a
212 creating test suite code.
214 For example, to make a MoneyTest suite available to a
215 @link CreatingTestSuite ccunit_makeSuite @endlink,
216 excute the following tool to
220 $ ccunit_makeSuite -f MoneyTest_suite -o makeMoneyTestSuite.c MoneyTest.c
223 @anchor test_runner_code
224 To use the TestRunner, include the header files for the tests in Main.c:
227 #include <ccunit/CCUnitTestRunner.h>
228 #include <ccunit/CCUnitTestSuite.h>
232 @link ccunit_runTestRunner()
233 ccunit_runTestRunner (CCUnitTestRunner*, CCUnitTestSuite *) @endlink
234 in the <code>main()</code> function:
237 extern CCUnitTestSuite* MoneyTest_suite(const char* name);
239 int main( int argc, char **argv)
241 CCUnitTestRunner* runner;
242 CCUnitTestSuite* suite;
243 runner = ccunit_newTestRunner (stdout);
244 suite = MoneyTest_suite ("MathTest Suite");
245 ccunit_runTestRunner (runner, suite);
250 The @link ExecutingTest TestRunner @endlink will run the tests.
251 If all the tests pass, you'll get an informative message.
252 If any fail, you'll get the following information:
255 <li> The name of the source file that contains the test</li>
256 <li> The line number where the failure occurred</li>
257 <li> The name of the test case that failed</li>
258 <li> All of the text inside the call to
259 <code>CCUNIT_ASSERT ()</code> which detected the failure</li>
262 @section helper_macros Helper Tool
264 As you might have noticed, implementing the fixture
265 <code>suite ()</code> function is a repetitive and error
266 prone task. A @ref CreatingTestSuite set of functions and
267 command have been created to automatically implements the
268 <code>suite()</code> method.
270 The following code is a rewrite of MoneyTest using those command:
273 #include <cppunit/CCUnitAssert.h>
276 First, you declare the fixture, passing the test fixture
277 name to the javaDoc style comment, which consist of a
278 C-style comment block starting with two <tt>*</tt>'s:
281 //** test case: Money test *\/
284 The suite created by the <code>ccunit_suite()</code>
285 function is specified <code>-f</code> option of command
286 <code>ccunit_makeSuite</code>. Then, you define each test
287 case of the fixture with prefix <code>test</code>,
288 <code>setUp</code>, <code>tearDown</code>:
291 static Money* s120JPY;
292 static Money* s140JPY;
293 static Money* s260JPY;
294 static Money* s23USD;
296 void setUp_MathTest ()
298 s120JPY = Money_new (120, "JPY");
299 s140JPY = Money_new (140, "JPY");
300 s260JPY = Money_new (260, "JPY");
301 s23USD = Money_new (23, "USD");
304 void tearDown_Mathtest ()
306 Money_delete (s120JPY);
307 Money_delete (s140JPY);
308 Money_delete (s260JPY);
309 Money_delete (s23USD);
312 //** simple add test *\/
313 void test_simpleAdd ()
315 Money* result = Money_add (s120JPY, s140JPY);
316 CCUNIT_ASSERT (Money_equals (s260JPY, result));
317 Money_delete (result);
320 //** money bug test *\/
323 Money* bag[] = { s260JPY, s28USD };
324 MoneyBag expected = MoneyBag_new (2, bag);
325 Money* subtotal = Money_add (s120JPY, s28USD);
326 Money* total = Money_add (subtotal, s140JPY);
327 CCUNIT_ASSERT (MoneyBag_equals (expected, total));
328 MoneyBag_delete (expected);
329 Money_delete (subtotal);
330 Money_delete (total);
334 Finally, you end the fixture declaration:
337 //** end test case *\/
340 To generate creating suite function code, run
341 <code>ccunit_makeSuite</code> tool.
344 $ ccunit_makeSuite MoneyTest.c
346 #include <ccunit/CCUnitTestSuite.h>
348 static CCUnitTestSuite* newSuite_001 (const char* name);
349 //* test fixture: Money test *\/
350 //* setUp_MathTest *\/
351 extern void setUp_MathTest ();
352 //* tearDown_Mathtest *\/
353 extern void tearDown_Mathtest ();
354 //* simple add test *\/
355 extern void test_simpleAdd ();
356 //* money bug test *\/
357 extern void test_moneyBag ();
359 static CCUnitTestSuite* newSuite_001 (const char* name)
361 CCUnitTestSuite* suite;
362 suite = ccunit_newTestSuite (name);
364 CCUnitTestFixture* testFixture;
365 testFixture = ccunit_newTestFixture ("Money test",
368 if (testFixture != NULL)
369 ccunit_addTestFixture (suite, testFixture);
371 CCUnitTestCase* newCase;
372 newCase = ccunit_newTestCase ("test_simpleAdd",
376 ccunit_addTestCase (testFixture, newCase);
379 CCUnitTestCase* newCase;
380 newCase = ccunit_newTestCase ("test_moneyBag",
384 ccunit_addTestCase (testFixture, newCase);
392 CCUnitTestSuite* ccunit_suite (const char* name)
394 return newSuite_001 (name);
399 @section post_build_check Post-build check
401 Now that we have our unit tests running, how about
402 integrating unit testing to our build process ?
404 To do that, the application must returns a value different than 0 to indicate that
407 @link ccunit_runTestRunner() ccunit_runTestRunner() @endlink returns
408 a integer indicating if the run was successful.
410 Updating our main programm, we obtains:
412 #include <ccunit/CCUnitTestRunner.h>
414 int main (int argc, char** argv)
416 CCUnitTestRunner* runner;
417 CCUnitTestSuite* suite;
419 runner = ccunit_newTestRunner (stdout);
420 suite = ccunit_suite ();
421 wasSucessful = ccunit_runTestRunner (runner, suite);
426 Now, you need to run your application after compilation.