CUnitTest


A unit test framework for C
Updated: March 20, 2007
Includes: "CUnitTest.h", "CUnitTest.h", <stdlib.h>, <stdio.h>



A simple but fairly complete unit test framework for C in a single header file. Features fixtures, test suites and integration with xcode!

To use: Write some test cases in implementation (.c) files. The test cases must take no parameters and return an int. If the test passes, it should return 0. Include this header file in each of the test case implementation files. The test cases should use the various CUT_ASSERT_* macros to test for failure. In order to run the tests, a test harness must be created using the CUT_BEGIN_TEST_HARNESS and CUT_END_TEST_HARNESS macros. These macros will generate a main method, so should only be called once. Test cases can be added to the test harness using the CUT_RUN_TEST() macro with the name of the test case function as the argument. For example, the following code creates a simple test that will always fail, together with a test harness to run it.

    #include "CUnitTest.h"
 
    int test1(void) {
        CUT_ASSERT(1==0);
        return 0;    
    }
 
    CUT_BEGIN_TEST_HARNESS
    CUT_RUN_TEST(test1);
    CUT_END_TEST_HARNESS
    

It is also possible to create suites of test cases using the CUT_BEGIN_SUITE/CUT_BEGIN_SUITE_F and CUT_END_SUITE/CUT_END_SUITE_F macros. The _F versions of the macros enable fixtures to be defined which will set up global variables before each test and tear the variables down after each test. The fixture setup and teardown functions must have void arguments and return types. Test suites must be given a name which follows standard C function naming conventions (i.e. no spaces, semi-colons, etc). Whole test suits can be run by adding them to the test harness with the CUT_RUN_SUITE_TESTS() macro with the name of the suite. The following example demonstrates the use of two test suites with a single function, one of which uses a fixture, together with a single stand-alone test case.

    #include "CUnitTest.h"
    #include <stdlib.h>
 
    int *val = NULL;
    void setup(void) {
     	val = malloc(sizeof(int));
    	*val=255;
    }
 
    void teardown(void) {
    	free(val);
	val = NULL;
    }
 
    int test1(void) {
	CUT_ASSERT(1==1);
	return 0;    
    }
 
    int test2(void) {
	CUT_ASSERT_NULL(val);
	return 0;    
    }
 
    int test3(void) {
	CUT_ASSERT_NOT_NULL(val);
        CUT_ASSERT(*val == 255);
	return 0;
    }

    CUT_BEGIN_SUITE(suite1)
    CUT_RUN_TEST(test2);
    CUT_END_SUITE
 
    CUT_BEGIN_SUITE_F(suite2, &setup, &teardown)
    CUT_RUN_TEST(test3);
    CUT_END_SUITE_F
 
    CUT_BEGIN_TEST_HARNESS
    CUT_RUN_TEST(test1);
    CUT_RUN_SUITE_TESTS(suite1);
    CUT_RUN_SUITE_TESTS(suite2);
    CUT_END_TEST_HARNESS
    

Running the above test code will yield:

    suite1: tests-run: 1, assertions: 1, passes: 1, failures: 0
    suite2: tests-run: 1, assertions: 2, passes: 1, failures: 0
    Overall Results: tests-run: 3, assertions: 4, passes: 3, failures: 0
    

XCode integration: In order to integrate with XCode, create a "Shell Tool" target and add the test files. Add a new shell script build phase to the end of the build phases that contains the following script (with the parentheses):

"$BUILT_PRODUCTS_DIR/$PRODUCT_NAME"

Building the test target will automatically run the test executable and any test-case failures will be displayed in the build pane. These failures can be double-clicked to take you to the corresponding line of the source code.





© 2007 University of Southampton. All rights reserved. Last Updated: March 20, 2007
HTML documentation generated by HeaderDoc
SourceForge.net Logo