diff options
Diffstat (limited to 'README.md')
-rw-r--r-- | README.md | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..935b98d --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +# 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. |