TDD using CUnit: First Steps

I made this article last semester to help some friends in a college’s project, so I hope this might be useful for someone else.

First, we need to install CUnit libraries. I use Ubuntu, so all that I had to do was

# apt-get install libcunit1 libcunit1-doc libcunit1-dev

I made some research and some guys recommend Cygwin on Windows, but I never tried it.

Our HelloWorld project is based on testing a method that returns the sum of two numbers. I hope that some day I’ll finish the original project sending test cases for data structures, like lists, heaps and queues.

In sum_test.c, we need to setup CUnit and initialize it.

#include "CUnit/Basic.h"
int main() {
// Initialize the CUnit test registry
if (CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();
   // Sets the basic run mode, CU_BRM_VERBOSE will show maximum output of run details
// Other choices are: CU_BRM_SILENT and CU_BRM_NORMAL
CU_basic_set_mode(CU_BRM_VERBOSE);
   // Run the tests and show the run summary
CU_basic_run_tests();
return CU_get_error();
}

You can check if everything is alright running

$ gcc -o sum_test sum_test.c -lcunit
$ ./sum_test
     CUnit - A unit testing framework for C - Version 2.1-2
http://cunit.sourceforge.net/
Run Summary:    Type  Total    Ran Passed Failed Inactive
suites 0 0 n/a 0 0
tests 0 0 0 0 0
asserts 0 0 0 0 n/a
Elapsed time =    0.000 seconds

We are going to have only one suite and one test case which will check if we are getting the right sum[1].

void sum_test() {
// Check if first param matches with second[2]
CU_ASSERT_EQUAL(sum(2, 14), 16);
CU_ASSERT_EQUAL(sum(0, 0), 0);
CU_ASSERT_EQUAL(sum(-1 ,6), 5);
}

But to be able to run this, it’s necessary to add those tests into a suite at main().

CU_pSuite pSuite = NULL;
// Add a suite to the registry
pSuite = CU_add_suite("sum_test_suite", 0, 0);
// Always check if add was successful
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
}
// Add the test to the suite
if (NULL == CU_add_test(pSuite, "sum_test", sum_test)) {
CU_cleanup_registry();
return CU_get_error();
}

If you try to compile this, it’ll fail, because we don’t have a method sum(), but don’t worry because that’s how TDD works[3]. Just to make sure that everything is ok, you can comment the lines that contain sum() and check the output of run summary.

Now it’s when you’ll really start to code. First, create a file sum.c and then write your sum().

int sum(int a, int b){
return a + b;
}

Remember to add #include “sum.c” in sum_test.c and run your tests again.

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

Suite: sum_test_suite
Test: sum_test ...passed
Run Summary:    Type  Total    Ran Passed Failed Inactive
suites 1 1 n/a 0 0
tests 1 1 1 0 0
asserts 3 3 3 0 n/a
Elapsed time =    0.000 seconds

Using TDD your flow will always look like write test — watch it fail — make it pass, but don’t try to make all the test cases on beginning, TDD uses baby steps[4]. You can check how this test case it’ll look in the end here.

[1] You can search about “happy path” and “sad path” on TDD if you want to get a better coverage.
[2] Get more assertions on CUnit Docs
[3] Test-driven development cycle
[4] How baby are your baby-steps in TDD?