• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Unity Helper Scripts
2
3## With a Little Help From Our Friends
4
5Sometimes what it takes to be a really efficient C programmer is a little non-C.
6The Unity project includes a couple Ruby scripts for making your life just a tad
7easier. They are completely optional. If you choose to use them, you'll need a
8copy of Ruby, of course. Just install whatever the latest version is, and it is
9likely to work. You can find Ruby at [ruby-lang.org](https://ruby-labg.org/).
10
11
12### `generate_test_runner.rb`
13
14Are you tired of creating your own `main` function in your test file? Do you
15keep forgetting to add a `RUN_TEST` call when you add a new test case to your
16suite? Do you want to use CMock or other fancy add-ons but don't want to figure
17out how to create your own `RUN_TEST` macro?
18
19Well then we have the perfect script for you!
20
21The `generate_test_runner` script processes a given test file and automatically
22creates a separate test runner file that includes ?main?to execute the test
23cases within the scanned test file. All you do then is add the generated runner
24to your list of files to be compiled and linked, and presto you're done!
25
26This script searches your test file for void function signatures having a
27function name beginning with "test" or "spec". It treats each of these
28functions as a test case and builds up a test suite of them. For example, the
29following includes three test cases:
30
31```C
32void testVerifyThatUnityIsAwesomeAndWillMakeYourLifeEasier(void)
33{
34  ASSERT_TRUE(1);
35}
36void test_FunctionName_should_WorkProperlyAndReturn8(void) {
37  ASSERT_EQUAL_INT(8, FunctionName());
38}
39void spec_Function_should_DoWhatItIsSupposedToDo(void) {
40  ASSERT_NOT_NULL(Function(5));
41}
42```
43
44You can run this script a couple of ways. The first is from the command line:
45
46```Shell
47ruby generate_test_runner.rb TestFile.c NameOfRunner.c
48```
49
50Alternatively, if you include only the test file parameter, the script will copy
51the name of the test file and automatically append "_Runner" to the name of the
52generated file. The example immediately below will create TestFile_Runner.c.
53
54```Shell
55ruby generate_test_runner.rb TestFile.c
56```
57
58You can also add a [YAML](http://www.yaml.org/) file to configure extra options.
59Conveniently, this YAML file is of the same format as that used by Unity and
60CMock. So if you are using YAML files already, you can simply pass the very same
61file into the generator script.
62
63```Shell
64ruby generate_test_runner.rb TestFile.c my_config.yml
65```
66
67The contents of the YAML file `my_config.yml` could look something like the
68example below. If you're wondering what some of these options do, you're going
69to love the next section of this document.
70
71```YAML
72:unity:
73  :includes:
74    - stdio.h
75    - microdefs.h
76  :cexception: 1
77  :suit_setup: "blah = malloc(1024);"
78  :suite_teardown: "free(blah);"
79```
80
81If you would like to force your generated test runner to include one or more
82header files, you can just include those at the command line too. Just make sure
83these are _after_ the YAML file, if you are using one:
84
85```Shell
86ruby generate_test_runner.rb TestFile.c my_config.yml extras.h
87```
88
89Another option, particularly if you are already using Ruby to orchestrate your
90builds - or more likely the Ruby-based build tool Rake - is requiring this
91script directly. Anything that you would have specified in a YAML file can be
92passed to the script as part of a hash. Let's push the exact same requirement
93set as we did above but this time through Ruby code directly:
94
95```Ruby
96require "generate_test_runner.rb"
97options = {
98  :includes => ["stdio.h", "microdefs.h"],
99  :cexception => 1,
100  :suite_setup => "blah = malloc(1024);",
101  :suite_teardown => "free(blah);"
102}
103UnityTestRunnerGenerator.new.run(testfile, runner_name, options)
104```
105
106If you have multiple files to generate in a build script (such as a Rakefile),
107you might want to instantiate a generator object with your options and call it
108to generate each runner thereafter. Like thus:
109
110```Ruby
111gen = UnityTestRunnerGenerator.new(options)
112test_files.each do |f|
113  gen.run(f, File.basename(f,'.c')+"Runner.c"
114end
115```
116
117#### Options accepted by generate_test_runner.rb:
118
119The following options are available when executing `generate_test_runner`. You
120may pass these as a Ruby hash directly or specify them in a YAML file, both of
121which are described above. In the `examples` directory, Example 3's Rakefile
122demonstrates using a Ruby hash.
123
124
125##### `:includes`
126
127This option specifies an array of file names to be `#include`'d at the top of
128your runner C file. You might use it to reference custom types or anything else
129universally needed in your generated runners.
130
131
132##### `:suite_setup`
133
134Define this option with C code to be executed _before any_ test cases are run.
135
136Alternatively, if your C compiler supports weak symbols, you can leave this
137option unset and instead provide a `void suiteSetUp(void)` function in your test
138suite.  The linker will look for this symbol and fall back to a Unity-provided
139stub if it is not found.
140
141
142##### `:suite_teardown`
143
144Define this option with C code to be executed _after all_ test cases have
145finished.  An integer variable `num_failures` is available for diagnostics.
146The code should end with a `return` statement; the value returned will become
147the exit code of `main`.  You can normally just return `num_failures`.
148
149Alternatively, if your C compiler supports weak symbols, you can leave this
150option unset and instead provide a `int suiteTearDown(int num_failures)`
151function in your test suite.  The linker will look for this symbol and fall
152back to a Unity-provided stub if it is not found.
153
154
155##### `:enforce_strict_ordering`
156
157This option should be defined if you have the strict order feature enabled in
158CMock (see CMock documentation). This generates extra variables required for
159everything to run smoothly. If you provide the same YAML to the generator as
160used in CMock's configuration, you've already configured the generator properly.
161
162
163##### `:plugins`
164
165This option specifies an array of plugins to be used (of course, the array can
166contain only a single plugin). This is your opportunity to enable support for
167CException support, which will add a check for unhandled exceptions in each
168test, reporting a failure if one is detected. To enable this feature using Ruby:
169
170```Ruby
171:plugins => [ :cexception ]
172```
173
174Or as a yaml file:
175
176```YAML
177:plugins:
178  -:cexception
179```
180
181If you are using CMock, it is very likely that you are already passing an array
182of plugins to CMock. You can just use the same array here. This script will just
183ignore the plugins that don't require additional support.
184
185
186### `unity_test_summary.rb`
187
188A Unity test file contains one or more test case functions. Each test case can
189pass, fail, or be ignored. Each test file is run individually producing results
190for its collection of test cases. A given project will almost certainly be
191composed of multiple test files. Therefore, the suite of tests is comprised of
192one or more test cases spread across one or more test files. This script
193aggregates individual test file results to generate a summary of all executed
194test cases. The output includes how many tests were run, how many were ignored,
195and how many failed. In addition, the output includes a listing of which
196specific tests were ignored and failed. A good example of the breadth and
197details of these results can be found in the `examples` directory. Intentionally
198ignored and failing tests in this project generate corresponding entries in the
199summary report.
200
201If you're interested in other (prettier?) output formats, check into the
202Ceedling build tool project (ceedling.sourceforge.net) that works with Unity and
203CMock and supports xunit-style xml as well as other goodies.
204
205This script assumes the existence of files ending with the extensions
206`.testpass` and `.testfail`.The contents of these files includes the test
207results summary corresponding to each test file executed with the extension set
208according to the presence or absence of failures for that test file. The script
209searches a specified path for these files, opens each one it finds, parses the
210results, and aggregates and prints a summary. Calling it from the command line
211looks like this:
212
213```Shell
214ruby unity_test_summary.rb build/test/
215```
216
217You can optionally specify a root path as well. This is really helpful when you
218are using relative paths in your tools' setup, but you want to pull the summary
219into an IDE like Eclipse for clickable shortcuts.
220
221```Shell
222ruby unity_test_summary.rb build/test/ ~/projects/myproject/
223```
224
225Or, if you're more of a Windows sort of person:
226
227```Shell
228ruby unity_test_summary.rb build\teat\ C:\projects\myproject\
229```
230
231When configured correctly, you'll see a final summary, like so:
232
233```Shell
234--------------------------
235UNITY IGNORED TEST SUMMARY
236--------------------------
237blah.c:22:test_sandwiches_should_HaveBreadOnTwoSides:IGNORE
238
239-------------------------
240UNITY FAILED TEST SUMMARY
241-------------------------
242blah.c:87:test_sandwiches_should_HaveCondiments:FAIL:Expected 1 was 0
243meh.c:38:test_soda_should_BeCalledPop:FAIL:Expected "pop" was "coke"
244
245--------------------------
246OVERALL UNITY TEST SUMMARY
247--------------------------
24845 TOTAL TESTS 2 TOTAL FAILURES 1 IGNORED
249```
250
251How convenient is that?
252
253
254*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)*
255