• 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 of 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 afterwards. 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##### `:externc`
164
165This option should be defined if you are mixing C and CPP and want your test
166runners to automatically include extern "C" support when they are generated.
167
168##### `:mock_prefix` and `:mock_suffix`
169
170Unity automatically generates calls to Init, Verify and Destroy for every file
171included in the main test file that starts with the given mock prefix and ends
172with the given mock suffix, file extension not included. By default, Unity
173assumes a `Mock` prefix and no suffix.
174
175##### `:plugins`
176
177This option specifies an array of plugins to be used (of course, the array can
178contain only a single plugin). This is your opportunity to enable support for
179CException support, which will add a check for unhandled exceptions in each
180test, reporting a failure if one is detected. To enable this feature using Ruby:
181
182```Ruby
183:plugins => [ :cexception ]
184```
185
186Or as a yaml file:
187
188```YAML
189:plugins:
190  -:cexception
191```
192
193If you are using CMock, it is very likely that you are already passing an array
194of plugins to CMock. You can just use the same array here. This script will just
195ignore the plugins that don't require additional support.
196
197##### `:include_extensions`
198
199This option specifies the pattern for matching acceptable header file extensions.
200By default it will accept hpp, hh, H, and h files. If you need a different combination
201of files to search, update this from the default `'(?:hpp|hh|H|h)'`.
202
203##### `:source_extensions`
204
205This option specifies the pattern for matching acceptable source file extensions.
206By default it will accept cpp, cc, C, c, and ino files. If you need a different combination
207of files to search, update this from the default `'(?:cpp|cc|ino|C|c)'`.
208
209
210### `unity_test_summary.rb`
211
212A Unity test file contains one or more test case functions. Each test case can
213pass, fail, or be ignored. Each test file is run individually producing results
214for its collection of test cases. A given project will almost certainly be
215composed of multiple test files. Therefore, the suite of tests is comprised of
216one or more test cases spread across one or more test files. This script
217aggregates individual test file results to generate a summary of all executed
218test cases. The output includes how many tests were run, how many were ignored,
219and how many failed. In addition, the output includes a listing of which
220specific tests were ignored and failed. A good example of the breadth and
221details of these results can be found in the `examples` directory. Intentionally
222ignored and failing tests in this project generate corresponding entries in the
223summary report.
224
225If you're interested in other (prettier?) output formats, check into the
226Ceedling build tool project (ceedling.sourceforge.net) that works with Unity and
227CMock and supports xunit-style xml as well as other goodies.
228
229This script assumes the existence of files ending with the extensions
230`.testpass` and `.testfail`.The contents of these files includes the test
231results summary corresponding to each test file executed with the extension set
232according to the presence or absence of failures for that test file. The script
233searches a specified path for these files, opens each one it finds, parses the
234results, and aggregates and prints a summary. Calling it from the command line
235looks like this:
236
237```Shell
238ruby unity_test_summary.rb build/test/
239```
240
241You can optionally specify a root path as well. This is really helpful when you
242are using relative paths in your tools' setup, but you want to pull the summary
243into an IDE like Eclipse for clickable shortcuts.
244
245```Shell
246ruby unity_test_summary.rb build/test/ ~/projects/myproject/
247```
248
249Or, if you're more of a Windows sort of person:
250
251```Shell
252ruby unity_test_summary.rb build\teat\ C:\projects\myproject\
253```
254
255When configured correctly, you'll see a final summary, like so:
256
257```Shell
258--------------------------
259UNITY IGNORED TEST SUMMARY
260--------------------------
261blah.c:22:test_sandwiches_should_HaveBreadOnTwoSides:IGNORE
262
263-------------------------
264UNITY FAILED TEST SUMMARY
265-------------------------
266blah.c:87:test_sandwiches_should_HaveCondiments:FAIL:Expected 1 was 0
267meh.c:38:test_soda_should_BeCalledPop:FAIL:Expected "pop" was "coke"
268
269--------------------------
270OVERALL UNITY TEST SUMMARY
271--------------------------
27245 TOTAL TESTS 2 TOTAL FAILURES 1 IGNORED
273```
274
275How convenient is that?
276
277
278*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)*
279