Compile the C test runner
Part 1 of exploring the Unity testing framework to do TDD in C.
A minimal starting point
Let's get a Unity test runner to compile!
The Concept: Reduce code complexity
As outlined in TDD in C: Part 0, I won't try to anticipate what the next piece of missing boilerplate, filesystem support, tooling or user code may be. Primarily, I will let build and test failures guide development instead of hunches about upcoming requirements or 'necessary' complexity.
Applying the concept
What does the concept of focusing on satisfying a requirement with the least amount of code complexity imply for our current project? The answer is quite simple: we try to use the least amount of code complexity possible to get a TDD workflow going in C.
What is a key part of a TDD workflow in C? A test runner. Well, what does the Unity framework's test runner need 'to get going'? Since the Unity framework is pure C, a Unity test runner must have an entry point under the hood somewhere: a main
function.
The Unity documentation says the following boilerplate is the entry point for a test runner:
What if we try using a test file that contains just that main
function? We suspend thoughts about whether it is sufficient to compile, whether our dependencies are installed, etc and take this as a minimal starting point.
main
entry point', we can use GitHub's search feature to find candidate starting points: repo:ThrowTheSwitch/Unity "int main("
The Commits
feat: add Unity to project
I'm starting with an empty repository: TDD-with-Unity.
1. I create test_that_unity_works.c
. This is my test file. It has the main
function.
2. I attempt to compile:gcc test_that_unity_works.c -o unity_test_runner.out
Unsurprisingly, I get warnings and errors that need to be fixed.
test_that_something_happens
caused an 'undeclared' error.UNITY_BEGIN
, RUN_TEST
and UNITY_END
caused implicit declaration warnings.3. I stage and commit the change.
fix: declare test function
At this point, all I want is for my minimal unity test runner to compile. I don't need to anticipate implementation details beyond that. If a change is sufficient to remove an error or warning, it is enough.
1. I add an empty function to test_that_unity_works.c
.
2. I check to see if I am one step closer to compiling:gcc test_that_unity_works.c -o unity_test_runner.out
I still get the warnings about the test suite management macros.
UNITY_BEGIN
, RUN_TEST
and UNITY_END
caused implicit declaration warnings.But I no longer get the 'undeclared' error. I've also progressed along the compile toolchain - I have a linking error now instead:
UNITY_BEGIN
, RUN_TEST
and UNITY_END
macros.We are one step closer.
3. I stage, commit and push:
main
with just UNITY_BEGIN
and UNITY_END
- just the test runner macros. Not a test runner and test cases.chore: add Unity as submodule
1. From the repository root, I add the Unity framework as a submodule:git submodule add
https://github.com/ThrowTheSwitch/Unity.git
Unity
unity.c
, unity.h
and unity_internals.h
. Although the Unity repository contains more than that (documentation, plugins, examples, self-tests, and so on) and there are quality-of-life script options available, core Unity is those three files and nothing else. The macros will be in them.2. I confirm that the Unity dependencies are in the filesystem:find -name unity.c -o -name unity.h -o -name unity_internals.h
3. I stage, commit and push.
4. In a different, non-nested directory, I use git clone --recurse-submodules
to check that the repository will supply a collaborator with the Unity dependencies:
I expect the find
command to return three entries and it does.
docs: add clone How To
1. I add a quick note to the README.md
about how to clone the project.
fix: include Unity dependencies
I now move on to fixing the implicit declaration warnings for the test suite management macros.
1. I add #include "unity.h"
to test_that_unity_works.c
.
2. I attempt to compile:gcc -I./Unity/src test_that_unity_works.c ./Unity/src/unity.c -o unity_test_runner.out
setUp
and tearDown.
Great. We have eliminated the warnings about the test suite management macros. A linker error has replaced it. This is progress.
3. I stage, commit and push.
fix: define setUp and tearDown
Again, I focus on defining only what is needed to make the code compile.
1. I define tearDown
and setUp
in test_that_unity_works.c
with empty function bodies.
2. I attempt to compile:gcc -I./Unity/src test_that_unity_works.c ./Unity/src/unity.c -o unity_test_runner.out
There are no warnings and no errors. unity_test_runner.out
compiles and runs.
3. I stage, commit and push.
The Replit
This is the state of the project after doing all the commits in this blog post. When compiled, the file test_that_unity_works.c
becomes the test runner. It will execute the tests defined in the file so long as those test functions are included in the main
function as an argument to a RUN_TEST
macro.
Next: A Deep Dive
The next article in the series will be a deep-dive on the test suite management macros (BEGIN_UNITY
, RUN_TEST
and UNITY_END
).