How to Actually Run Criterion Tests? #516
-
Hello All, I am extremely new to unit testing and I am trying to use the Criterion Unit Test Framework for the first time in C (it seems perfect for my needs) . I have read these online documentation pages on Criterion (https://criterion.readthedocs.io/en/master/intro.html, https://criterion.readthedocs.io/en/master/setup.html, https://criterion.readthedocs.io/en/master/starter.html, https://criterion.readthedocs.io/en/master/assert.html, https://criterion.readthedocs.io/en/master/hooks.html, https://criterion.readthedocs.io/en/master/assert_old.html#old-assertions-ref). However, the one thing I did not see is how to actually run the Criterion test(s) once they have been written. Perhaps that should be added to the “Getting started” page (https://criterion.readthedocs.io/en/master/starter.html)? I would imagine that I need to pass some sort of pre-compiler option to Visual Studio Code or CMake? My current code is a small main.c and another file which contains all the Criterion testing code called Michaels_tests_Criterion.c. main.c
Michaels_tests_Criterion.c
These tests are mostly copy and pastes from the documentation. I am aware they do not test any specific part of my code in main.c. But I wanted to get these basic tests to run, before I start testing out signals from my signal handler. Michaels_test_Criterion.h
In short, how do I get my tests to actually run? Do I call them in main.c (I get errors when I do that)? I need to define the functions in Michaels_test_Criterion.h? Something else? Any help would be appreciated! :) Also, here is my CMake file if I am suppose to do this from CMake:
|
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Hey there, The main problem is that you're mixing your library code with your executable code. You seem to be linking criterion to your executable, which defines main, but your main overrides the default main that criterion provides. Instead, you should introduce a third file that contains your code, and leave your main function in main.c. You'd then have two executables: one for your main project, which links main.o and all of your library object files, and one for the tests, which links your library object files, your test object files, and libcriterion. You can see this in action by compiling and linking directly one of the samples of this repo. Alternatively, here's something I cooked up to show how this is supposed to be working: in the following directory, lib.c contains a small implementation of the fibonacci function, main.c is an executable that prints the nth fibonacci number, and test.c contains tests for the fibonacci function. $ cat <<'EOF' > lib.c
int fib(int n) {
int a = 0, b = 1;
for (int i = 0; i < n; i++) {
int tmp = b;
b = b + a;
a = tmp;
}
return a;
}
EOF
$ cat <<'EOF' > lib.h
#ifndef LIB_H_
#define LIB_H_
int fib(int n);
#endif /* !LIB_H_ */
EOF
$ cat <<'EOF' > main.c
#include <stdio.h>
#include <stdlib.h>
#include "lib.h"
int main(int argc, char *argv[])
{
printf("%d\n", fib(atoi(argv[1])));
return 0;
}
EOF
$ cat <<'EOF' > test.c
#include <criterion/criterion.h>
#include <criterion/new/assert.h>
#include "lib.h"
Test(example, fib) {
cr_assert(eq(int, fib(0), 0));
cr_assert(eq(int, fib(1), 1));
cr_assert(eq(int, fib(2), 1));
cr_assert(eq(int, fib(3), 2));
cr_assert(eq(int, fib(4), 3));
cr_assert(eq(int, fib(5), 5));
cr_assert(eq(int, fib(6), 8));
}
Test(example, bad) {
cr_assert(eq(int, fib(0), 42));
}
EOF
$ # Building your application's executable
$ gcc -o fib main.c lib.c
$ ./fib 8
21
$ # Building the tests
$ gcc -o test test.c lib.c -lcriterion
$ ./test
[----] sample.c:16: Assertion Failed
[----] eq(int, fib(0), 42):
[----] diff: [-0-]{+42+}
[FAIL] example::bad: (0.00s)
[====] Synthesis: Tested: 2 | Passing: 1 | Failing: 1 | Crashing: 0 |
Beta Was this translation helpful? Give feedback.
Hey there,
The main problem is that you're mixing your library code with your executable code. You seem to be linking criterion to your executable, which defines main, but your main overrides the default main that criterion provides.
Instead, you should introduce a third file that contains your code, and leave your main function in main.c.
You'd then have two executables: one for your main project, which links main.o and all of your library object files, and one for the tests, which links your library object files, your test object files, and libcriterion.
You can see this in action by compiling and linking directly one of the samples of this repo.
Alternatively, here's something I cooked…