C++ Unit Testing Framework

Unit Testing C Code

One unit testing framework in C is Check; a list of unit testing frameworks in C can be found here and is reproduced below. Depending on how many standard library functions your runtime has, you may or not be able to use one of those.

AceUnit

AceUnit (Advanced C and Embedded Unit) bills itself as a comfortable C code unit test framework. It tries to mimick JUnit 4.x and includes reflection-like capabilities. AceUnit can be used in resource constraint environments, e.g. embedded software development, and importantly it runs fine in environments where you cannot include a single standard header file and cannot invoke a single standard C function from the ANSI / ISO C libraries. It also has a Windows port. It does not use forks to trap signals, although the authors have expressed interest in adding such a feature. See the AceUnit homepage.

GNU Autounit

Much along the same lines as Check, including forking to run unit tests in a separate address space (in fact, the original author of Check borrowed the idea from GNU Autounit). GNU Autounit uses GLib extensively, which means that linking and such need special options, but this may not be a big problem to you, especially if you are already using GTK or GLib. See the GNU Autounit homepage.

cUnit

Also uses GLib, but does not fork to protect the address space of unit tests.

CUnit

Standard C, with plans for a Win32 GUI implementation. Does not currently fork or otherwise protect the address space of unit tests. In early development. See the CUnit homepage.

CuTest

A simple framework with just one .c and one .h file that you drop into your source tree. See the CuTest homepage.

CppUnit

The premier unit testing framework for C++; you can also use it to test C code. It is stable, actively developed, and has a GUI interface. The primary reasons not to use CppUnit for C are first that it is quite big, and second you have to write your tests in C++, which means you need a C++ compiler. If these don’t sound like concerns, it is definitely worth considering, along with other C++ unit testing frameworks. See the CppUnit homepage.

embUnit

embUnit (Embedded Unit) is another unit test framework for embedded systems. This one appears to be superseded by AceUnit. Embedded Unit homepage.

MinUnit

A minimal set of macros and that’s it! The point is to show how easy it is to unit test your code. See the MinUnit homepage.

CUnit for Mr. Ando

A CUnit implementation that is fairly new, and apparently still in early development. See the CUnit for Mr. Ando homepage.

This list was last updated in March 2008.

More frameworks:

CMocka

CMocka is a test framework for C with support for mock objects. It's easy to use and setup.

See the CMocka homepage.

Criterion

Criterion is a cross-platform C unit testing framework supporting automatic test registration, parameterized tests, theories, and that can output to multiple formats, including TAP and JUnit XML. Each test is run in its own process, so signals and crashes can be reported or tested if needed.

See the Criterion homepage for more information.

HWUT

HWUT is a general Unit Test tool with great support for C. It can help to create Makefiles, generate massive test cases coded in minimal 'iteration tables', walk along state machines, generate C-stubs and more. The general approach is pretty unique: Verdicts are based on 'good stdout/bad stdout'. The comparison function, though, is flexible. Thus, any type of script may be used for checking. It may be applied to any language that can produce standard output.

See the HWUT homepage.

CGreen

A modern, portable, cross-language unit testing and mocking framework for C and C++. It offers an optional BDD notation, a mocking library, the ability to run it in a single process (to make debugging easier). A test runner which discover automatically the test functions is available. But you can create your own programmatically.

All those features (and more) are explained in the CGreen manual.

Wikipedia gives a detailed list of C unit testing frameworks under List of unit testing frameworks: C

unit testing framework for C

I have worked some with Check and its very easy to setup. Its used by some big active projects like GStreamer. Here is a simple example of fail if line:

fail_if (0 == get_element_position(spot), "Position should not be 0");

Writing unit tests for C code

In general, I agree with Wes's answer - it is going to be much harder to add tests to code that isn't written with tests in mind. There's nothing inherent in C that makes it impossible to test - but, because C doesn't force you to write in a particular style, it's also very easy to write C code that is difficult to test.

In my opinion, writing code with tests in mind will encourage shorter functions, with few arguments, which helps alleviate some of the pain in your examples.

First, you'll need to pick a unit testing framework. There are a lot of examples in this question (though sadly a lot of the answers are C++ frameworks - I would advise against using C++ to test C).

I personally use TestDept, because it is simple to use, lightweight, and allows stubbing. However, I don't think it is very widely used yet. If you're looking for a more popular framework, many people recommend Check - which is great if you use automake.

Here are some specific answers for your use cases:

Passing around a large 'context' struct pointer

For this case, you can build an instance of the struct with the pre conditions manually set, then check the status of the struct after the function has run. With short functions, each test will be fairly straightforward.

No easy way to test failure on dependent functions

I think this is one of the biggest hurdles with unit testing C.
I've had success using TestDept, which allows run time stubbing of dependent functions. This is great for breaking up tightly coupled code. Here's an example from their documentation:

void test_stringify_cannot_malloc_returns_sane_result() {
replace_function(&malloc, &always_failing_malloc);
char *h = stringify('h');
assert_string_equals("cannot_stringify", h);
}

Depending on your target environment, this may or may not work for you. See their documentation for more details.

Functions with lots of parameters

This probably isn't the answer you're looking for, but I would just break these up into smaller functions with fewer parameters. Much much easier to test.

Static or hidden functions

It's not super clean, but I have tested static functions by including the source file directly, enabling calls of static functions. Combined with TestDept for stubbing out anything not under test, this works fairly well.

 #include "implementation.c"

/* Now I can call foo(), defined static in implementation.c */

A lot of C code is legacy code with few tests - and in those cases, it is generally easier to add integration tests that test large parts of the code first, rather than finely grained unit tests. This allows you to start refactoring the code underneath the integration test to a unit-testable state - though it may or may not be worth the investment, depending on your situation. Of course, you'll want to be able to add unit tests to any new code written during this period, so having a solid framework up and running early is a good idea.

If you are working with legacy code, this book
(Working effectively with legacy code by Michael Feathers) is great further reading.

Which unit testing framework to use for C development on Windows?

Awesome slides from a talk on TDD with C, using nothing but C99 standard stuff.

Personally I like the stuff in glib, which you may be able to use in MinGW.

Using C unit testing framework Check without Autotools?

You certainly don't need to learn autotools to use Check in small projects.
Let's say our main() is in main.c and our implementation.c have a function that sums 2 ints.
(implementation.h contains just the function prototype)

#include "implementation.h"

int sum(int a, int b) {

return a + b;
}

You can write a test like so:

#include "implementation.h"

#test sum2test
fail_unless(sum(3, 2) == 5, "sum function borked");
fail_unless(sum(-3, 2) == -1, "sum function borked");
fail_unless(sum(3, -2) == 1, "sum function borked");
fail_unless(sum(-3, -2) == -5, "sum function borked");

Save the file in implementation-test.check (you can pick any name / extension you want, but stay with those if you want to follow my guide) and then run the included awk script that comes with Check.
You don't even have to bother with the boilerplate code for the check framework! (for more details man checkmk)

checkmk implementation-test.check >implementation-test.c

The output will be the following:

/*
* DO NOT EDIT THIS FILE. Generated by checkmk.
* Edit the original source file "implementation-test.check" instead.
*/

#include <check.h>

#line 1 "implementation-test.check"
#include "implementation.h"

START_TEST(sum2test)
{
#line 4
fail_unless(sum(3, 2) == 5, "sum function borked");
fail_unless(sum(-3, 2) == -1, "sum function borked");
fail_unless(sum(3, -2) == 1, "sum function borked");
fail_unless(sum(-3, -2) == -5, "sum function borked");
}
END_TEST

int main(void)
{
Suite *s1 = suite_create("Core");
TCase *tc1_1 = tcase_create("Core");
SRunner *sr = srunner_create(s1);
int nf;

suite_add_tcase(s1, tc1_1);
tcase_add_test(tc1_1, sum2test);

srunner_run_all(sr, CK_ENV);
nf = srunner_ntests_failed(sr);
srunner_free(sr);

return nf == 0 ? 0 : 1;
}

Then just include -lcheck when you compile to get the check library linked in and run the program!

gcc -Wall -o sum2ints-test implementation.c implementation-test.c -lcheck
./sum2ints

Below is a simple makefile to get you started. Save it in sum2ints.makefile and then to build the implementation.c along with main, run:

make -f sum2ints.makefile

To build & run the implementation.c with our implementation-test.c that got created from checkmk, run:

make -f sum2ints.makefile test

-

CFLAGS=-Wall
LIBS=-lcheck

all: sum2ints

sum2ints: main.o implementation.o
gcc -o sum2ints main.o implementation.o

main.o: main.c implementation.h
gcc $(CFLAGS) -c main.c

implementation.o: implementation.c implementation.h
gcc $(CFLAGS) -c implementation.c

test: sum2ints-test
./sum2ints-test

sum2ints-test: implementation-test.o implementation.o
gcc -o sum2ints-test implementation.o implementation-test.o $(LIBS)

implementation-test.o: implementation-test.c implementation.h
gcc $(CFLAGS) -c implementation-test.c

I've prepared a .zip file for you containing all the above.

https://dl.dropbox.com/u/1987095/test-check.zip

Comparison of C++ unit test frameworks

See this question for some discussion.

They recommend the articles:
Exploring the C++ Unit Testing Framework Jungle, By Noel Llopis.
And the more recent: C++ Test Unit Frameworks

I have not found an article that compares googletest to the other frameworks yet.

Unit Testing Frameworks for C: Comparison

You can use any C or C++ unit testing framework. Its easy enough to call C functions from C++.

My opinion is that you want to have as little output as possible from your tests. ie if everything is OK, it should print '100% passed'. Otherwise it should only print out details of test failures.

see xprogramming.com (original link broken; here it is on the way back machine), scroll down to the Unit Testing table and look for the C Language or C++ frameworks. The most 'standard' it seems is cppUnit.

Basic unit test and C, how do I get started?

You created a first test case. Now you need to create a test suite (a group of test cases) and a runner.

I would recommend you try to compile their example first to validate your environment, although their documentation introduces new code via diff (source patch) which I do not find very convenient.


If ever you decide to try with another framework (minunit came to my mind immediately), I can point you to a "tutorial".

Unit test framework for Vala

There is a simple unit test facility already built into Vala: GLib.Test.

Unity, the user interface for the Ubuntu desktop, is partly written in Vala (the rest is C++.)



Related Topics



Leave a reply



Submit