aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 9836808edfb82bd27fdf812eda717bac40b56ef5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# Unity test runner
## A mostly-auto-discovering unity unit test runner

The excellent [unity][unity-homepage] unit testing library leaves the
implementation of the test runner program to the user. This is a nice way to
make the library more portable and generic, but it means that anyone as lazy
as me is left running one of the bundled Ruby scripts to generate a test runner.
I don't like the idea of mandating Ruby as a dependency for unit testing some
embedded software, so I decided to make an equally "auto-discovering" method
of running unit tests across multiple suites.

So unity-test-runner was born.


### Theory of operation

In stock unity, without using the auto-generator ruby scripts, you need to keep
updating a list of the tests you would like to run, often separate from the
tests themselves. This is error prone and no doubt one day you will
accidentally leave a test missing from this list.

In order to use unity-test-runner, it is linked into the same executable as the
tests in a suite. It provides the `int main`, which will iterate through a list
of unit tests to run, and run each in sequence with unity.

In order to let the magic discovery happen, you need to cast a spell. Instead
of declaring tests as plain functions as you would under stock unity, we must
"decorate" them with a macro:

	#include "unity.h"
	#inlcude "test_runner.h"

	RUNNER_DECLARE_TEST(test_one_is_not_zero)
	{
		TEST_ASSERT_NOT_EQUAL(0, 1);
	}

...and use a custom linker script after compiling tests modules, unity, and
this package into objects:

	cc -o -Wl,-T,unity-test-runner/linker_list.ld test_runner test_runner.o unity.o test_foo.o ...

Running the resulting executable should show `test_one_is_not_zero` run and
pass:

	$ ./test_runner
	Suite has 1 tests
	test_foo.c:4:test_one_is_not_zero:PASS

	-----------------------
	1 Tests 0 Failures 0 Ignored
	OK


The magic trick is simply that `RUNNER_DECLARE_TEST` along with
`linker_list.ld` declare a so-called *linker list* residing in the symbol table
of the test runner executable. This list is picked up by the test runner `int
main` which iterates over the whole list and runs each test in sequence.

Notice that this requires no secondary list of test functions to be explicitly
maintained, and no function prototypes for each of the unit tests to be
declared in the test runner. If you look at `test_runner.c` you will see how
it is very plain (naive?) and portable between different suites and projects.

[unity-homepage]: http://www.throwtheswitch.org/unity