I need to get up and running with Cmocka unit testing framework. My setup is:
src/math/addition/add.c (+add.h)
int add(int a, int b) {return a + b;}
src/math/subtraction/sub.c (+sub.h)
int sub(int a, int b) {return a - b;}
Makefile
VPATH := src src/math src/math/addition
CFLAGS += -Isrc -Isrc/math -Isrc/math/addition
all: libMath clean
libMath: add.o sub.o
ar rcs bin/libMath add.o sub.o
clean:
rm -rf *.o
%.o: %.c %.h
Unit Tests
test/math/addition/add_test.c
#include "../src/math/addition/add.h"
void test_add() {
assert(add(4, 5), 9);
}
test/math/subtraction/sub_test.c
#include "../src/math/subtraction/sub.h"
void test_sub() {
assert(sub(9, 5), 4);
}
test/math/addition/add_test.c (from cmocka.org)
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>
/* A test case that does nothing and succeeds. */
static void null_test_success(void **state) {
(void) state; /* unused */
}
int main(void) {
const struct CMUnitTest tests[] = {
cmocka_unit_test(null_test_success),
};
return cmocka_run_group_tests(tests, NULL, NULL);
}
I'm new to unit testing in C and basically can't get my head around to setup the unit tests including linking the Cmocka library etc.
My idea is to have several unit test files instead of putting all unit tests in one file.
Scaling up
Going from 1 test file to 2 and 3 and it will be at least 10+ files. Looking for some optimizations and articulations to scale up nicely and for easy management. Here's what I've so far.
VPATH := src/math/add src/math/sub src/math/mul # split src/test path
VPATH += test/math/add test/math/sub test/math/mul
all: libMath clean
libMath: add.o sub.o mul.o
ar rcs bin/libMath add.o sub.o mul.o # suggestion? $^
test: add_test sub_test mul_test clean
./add_test
./sub_test
./mul_test
add_test: add_test.o add.o
$(CC) -o $@ $^
sub_test: sub_test.o sub.o
$(CC) -o $@ $^
mul_test: mul_test.o mul.o
$(CC) -o $@ $^
clean:
$(RM) *.o
%.o: %.c %.h
Here's the observation so far.
test:
target in the prerequisites and the commandWhile scaling up, Is it better this way or there could be better approaches?
P.S. I've removed CFLAGS line, it's working fine without it, helped me to clean up and reduce some clutter. is it ok? My IDE (clion) shows red wiggly lines if the path isn't right to .h files so I'm using full paths in the test files to include src files.
P.P.S It creates test executables on the root of the project, how to have all the binaries created in the bin folder and then delete all at the end of the project.
I would add a test
target. That target would depend on all your test programs and should then execute the programs; you may want to add individual targets to execute the programs and just keep one master test target to make sure all of them are executed. Each test program would depend on the object files that are required for the test; if you're doing an addition test, let the addition test depend on the addition.o and add_test.o. Link them as you would always do and then execute them.
Example:
test: addition_test
./addition_test
addition_test: add_test.o add.o
$(CC) -o $@ $^
You can scale your tests by adding two rules and deleting most of the other rules, related to testing:
test: add_test_run sub_test_run
%_run: %
./$<
%_test: %.o %_test.o
$(CC) -o $@ $^
Should do everything you want. This allows running tests in parallel; you can avoid running tests that doesn't need to be run by creating a file at the end of each run, say: a log file that tells you the result of the test run.
This should do the trick:
test: add_test.log sub_test.log
%.log: %
./$^ > $@
%_test: %.o %_test.o
$(CC) -o $@ $^
You should use $(RM)
instead of rm -rf
in your clean target. $(RM)
is platform independent while rm -rf
only works on UNIXy platforms.