Notes and samples for CUnit test framework for C

To test with CUnit, you create a C program that, when run, tests your code and displays the results (in one of several formats).  So, if you have mycode.c (and mycode.h), you should create mycode_test.c (or maybe you prefer test_mycode.c, the name doesn't matter).  That file will include mycode.h, and contain a bunch of test functions.  There is some boilerplate code that you use from a sample project; just replace the sample test functions with your own.

Note, a single test program can test many modules, or all of them, from that one file.  Inside the test C program, you can define test suits and add your test functions to one or another suite.  At the end of this program, you state which test suit(s)s you want to be tested, and using which user interface (runner).

Here's what I did on my Windows machine, after installing Cygwin (by downloading and running the setup.exe file, and verifying development tools such as gcc and make were installed):

  1. Launched Cybwin Bash window.
  2. Unpacked the cunit tarball, cd into the new directory, and built it with default options:
    $ ./configure
    $ make
    $ make install

(Note I didn't include the examples or ncurses options; I tried them at first but couldn't get it to work under Cygwin.  If you have any errors, rerun Cygwin's setup.exe to make sure you have any missing stuff installed—the error messages should say what you need.)

Next I tried to compile the example that ships with the package; it didn't work!  But I found the errors in the source and fixed them: Missing #include, TRUE instead of CU_TRUE, and FALSE instead of CU_FALSE.  I also removed the #include line, the one for using the curses interface, as that wasn't built.

Once I made those changes, the sample code from their website ran without problem.

Below are the three files I used to test this stuff on a trivial C program, max.c.  Here are the commands I ran, and the output:


Steps (and their output) to create and run a unit test


$ mkdir max
$ cd max
$ vi max.c
$ vi max.h
$ cp ../sampletest.c max_test.c
$ vi max_test.c
$ gcc -Wall -c max.c
$ gcc -Wall -L/usr/local/lib -o max_test max_test.c max.o -lcunit
$ ./max_test


     CUnit - A unit testing framework for C - Version 2.1-2
     http://cunit.sourceforge.net/


Suite: max_test_suite
  Test: max_test_1 ...passed
  Test: max_test_2 ...passed
  Test: max_test_3 ...passed

Run Summary:    Type  Total    Ran Passed Failed Inactive
              suites      1      1    n/a      0        0
               tests      3      3      3      0        0
             asserts      6      6      6      0      n/a

Elapsed time =    0.000 seconds


max.c

#include "max.h"

int max (int n1, int n2 )
{
   if ( n2 > n1 )  return n2;
   return n1;
}

max.h

#ifndef MAX_H
#define MAX_H
extern int max (int, int);
#endif

max_test.c

#include "CUnit/CUnit.h"
#include "CUnit/Basic.h"
//#include "CUnit/Automated.h"
//#include "CUnit/Console.h"

#include "max.h"

#include <stdio.h>  // for printf

/* Test Suite setup and cleanup functions: */

int init_suite(void) { return 0; }
int clean_suite(void) { return 0; }

/************* Test case functions ****************/

void test_case_sample(void)
{
   CU_ASSERT(CU_TRUE);
   CU_ASSERT_NOT_EQUAL(2, -1);
   CU_ASSERT_STRING_EQUAL("string #1", "string #1");
   CU_ASSERT_STRING_NOT_EQUAL("string #1", "string #2");

   CU_ASSERT(CU_FALSE);
   CU_ASSERT_EQUAL(2, 3);
   CU_ASSERT_STRING_NOT_EQUAL("string #1", "string #1");
   CU_ASSERT_STRING_EQUAL("string #1", "string #2");
}

void max_test_1(void) {
  CU_ASSERT_EQUAL( max(1,2), 2);
  CU_ASSERT_EQUAL( max(2,1), 2);
}

void max_test_2(void) {
  CU_ASSERT_EQUAL( max(2,2), 2);
  CU_ASSERT_EQUAL( max(0,0), 0);
  CU_ASSERT_EQUAL( max(-1,-1), -1);
}

void max_test_3(void) {
  CU_ASSERT_EQUAL( max(-1,-2), -1);
}

/************* Test Runner Code goes here **************/

int main ( void )
{
   CU_pSuite pSuite = NULL;

   /* initialize the CUnit test registry */
   if ( CUE_SUCCESS != CU_initialize_registry() )
      return CU_get_error();

   /* add a suite to the registry */
   pSuite = CU_add_suite( "max_test_suite", init_suite, clean_suite );
   if ( NULL == pSuite ) {
      CU_cleanup_registry();
      return CU_get_error();
   }

   /* add the tests to the suite */
   if ( (NULL == CU_add_test(pSuite, "max_test_1", max_test_1)) ||
        (NULL == CU_add_test(pSuite, "max_test_2", max_test_2)) ||
        (NULL == CU_add_test(pSuite, "max_test_3", max_test_3))
      )
   {
      CU_cleanup_registry();
      return CU_get_error();
   }

   // Run all tests using the basic interface
   CU_basic_set_mode(CU_BRM_VERBOSE);
   CU_basic_run_tests();
   printf("\n");
   CU_basic_show_failures(CU_get_failure_list());
   printf("\n\n");
/*
   // Run all tests using the automated interface
   CU_automated_run_tests();
   CU_list_tests_to_file();

   // Run all tests using the console interface
   CU_console_run_tests();
*/
   /* Clean up registry and return */
   CU_cleanup_registry();
   return CU_get_error();