aboutsummaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'README.md')
-rw-r--r--README.md63
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.