19750e409Sopenharmony_ci# Unity Helper Scripts
29750e409Sopenharmony_ci
39750e409Sopenharmony_ci## With a Little Help From Our Friends
49750e409Sopenharmony_ci
59750e409Sopenharmony_ciSometimes what it takes to be a really efficient C programmer is a little non-C.
69750e409Sopenharmony_ciThe Unity project includes a couple Ruby scripts for making your life just a tad
79750e409Sopenharmony_cieasier. They are completely optional. If you choose to use them, you'll need a
89750e409Sopenharmony_cicopy of Ruby, of course. Just install whatever the latest version is, and it is
99750e409Sopenharmony_cilikely to work. You can find Ruby at [ruby-lang.org](https://ruby-labg.org/).
109750e409Sopenharmony_ci
119750e409Sopenharmony_ci
129750e409Sopenharmony_ci### `generate_test_runner.rb`
139750e409Sopenharmony_ci
149750e409Sopenharmony_ciAre you tired of creating your own `main` function in your test file? Do you
159750e409Sopenharmony_cikeep forgetting to add a `RUN_TEST` call when you add a new test case to your
169750e409Sopenharmony_cisuite? Do you want to use CMock or other fancy add-ons but don't want to figure
179750e409Sopenharmony_ciout how to create your own `RUN_TEST` macro?
189750e409Sopenharmony_ci
199750e409Sopenharmony_ciWell then we have the perfect script for you!
209750e409Sopenharmony_ci
219750e409Sopenharmony_ciThe `generate_test_runner` script processes a given test file and automatically
229750e409Sopenharmony_cicreates a separate test runner file that includes ?main?to execute the test
239750e409Sopenharmony_cicases within the scanned test file. All you do then is add the generated runner
249750e409Sopenharmony_cito your list of files to be compiled and linked, and presto you're done!
259750e409Sopenharmony_ci
269750e409Sopenharmony_ciThis script searches your test file for void function signatures having a
279750e409Sopenharmony_cifunction name beginning with "test" or "spec". It treats each of these
289750e409Sopenharmony_cifunctions as a test case and builds up a test suite of them. For example, the
299750e409Sopenharmony_cifollowing includes three test cases:
309750e409Sopenharmony_ci
319750e409Sopenharmony_ci```C
329750e409Sopenharmony_civoid testVerifyThatUnityIsAwesomeAndWillMakeYourLifeEasier(void)
339750e409Sopenharmony_ci{
349750e409Sopenharmony_ci  ASSERT_TRUE(1);
359750e409Sopenharmony_ci}
369750e409Sopenharmony_civoid test_FunctionName_should_WorkProperlyAndReturn8(void) {
379750e409Sopenharmony_ci  ASSERT_EQUAL_INT(8, FunctionName());
389750e409Sopenharmony_ci}
399750e409Sopenharmony_civoid spec_Function_should_DoWhatItIsSupposedToDo(void) {
409750e409Sopenharmony_ci  ASSERT_NOT_NULL(Function(5));
419750e409Sopenharmony_ci}
429750e409Sopenharmony_ci```
439750e409Sopenharmony_ci
449750e409Sopenharmony_ciYou can run this script a couple of ways. The first is from the command line:
459750e409Sopenharmony_ci
469750e409Sopenharmony_ci```Shell
479750e409Sopenharmony_ciruby generate_test_runner.rb TestFile.c NameOfRunner.c
489750e409Sopenharmony_ci```
499750e409Sopenharmony_ci
509750e409Sopenharmony_ciAlternatively, if you include only the test file parameter, the script will copy
519750e409Sopenharmony_cithe name of the test file and automatically append "_Runner" to the name of the
529750e409Sopenharmony_cigenerated file. The example immediately below will create TestFile_Runner.c.
539750e409Sopenharmony_ci
549750e409Sopenharmony_ci```Shell
559750e409Sopenharmony_ciruby generate_test_runner.rb TestFile.c
569750e409Sopenharmony_ci```
579750e409Sopenharmony_ci
589750e409Sopenharmony_ciYou can also add a [YAML](http://www.yaml.org/) file to configure extra options.
599750e409Sopenharmony_ciConveniently, this YAML file is of the same format as that used by Unity and
609750e409Sopenharmony_ciCMock. So if you are using YAML files already, you can simply pass the very same
619750e409Sopenharmony_cifile into the generator script.
629750e409Sopenharmony_ci
639750e409Sopenharmony_ci```Shell
649750e409Sopenharmony_ciruby generate_test_runner.rb TestFile.c my_config.yml
659750e409Sopenharmony_ci```
669750e409Sopenharmony_ci
679750e409Sopenharmony_ciThe contents of the YAML file `my_config.yml` could look something like the
689750e409Sopenharmony_ciexample below. If you're wondering what some of these options do, you're going
699750e409Sopenharmony_cito love the next section of this document.
709750e409Sopenharmony_ci
719750e409Sopenharmony_ci```YAML
729750e409Sopenharmony_ci:unity:
739750e409Sopenharmony_ci  :includes:
749750e409Sopenharmony_ci    - stdio.h
759750e409Sopenharmony_ci    - microdefs.h
769750e409Sopenharmony_ci  :cexception: 1
779750e409Sopenharmony_ci  :suit_setup: "blah = malloc(1024);"
789750e409Sopenharmony_ci  :suite_teardown: "free(blah);"
799750e409Sopenharmony_ci```
809750e409Sopenharmony_ci
819750e409Sopenharmony_ciIf you would like to force your generated test runner to include one or more
829750e409Sopenharmony_ciheader files, you can just include those at the command line too. Just make sure
839750e409Sopenharmony_cithese are _after_ the YAML file, if you are using one:
849750e409Sopenharmony_ci
859750e409Sopenharmony_ci```Shell
869750e409Sopenharmony_ciruby generate_test_runner.rb TestFile.c my_config.yml extras.h
879750e409Sopenharmony_ci```
889750e409Sopenharmony_ci
899750e409Sopenharmony_ciAnother option, particularly if you are already using Ruby to orchestrate your
909750e409Sopenharmony_cibuilds - or more likely the Ruby-based build tool Rake - is requiring this
919750e409Sopenharmony_ciscript directly. Anything that you would have specified in a YAML file can be
929750e409Sopenharmony_cipassed to the script as part of a hash. Let's push the exact same requirement
939750e409Sopenharmony_ciset as we did above but this time through Ruby code directly:
949750e409Sopenharmony_ci
959750e409Sopenharmony_ci```Ruby
969750e409Sopenharmony_cirequire "generate_test_runner.rb"
979750e409Sopenharmony_cioptions = {
989750e409Sopenharmony_ci  :includes => ["stdio.h", "microdefs.h"],
999750e409Sopenharmony_ci  :cexception => 1,
1009750e409Sopenharmony_ci  :suite_setup => "blah = malloc(1024);",
1019750e409Sopenharmony_ci  :suite_teardown => "free(blah);"
1029750e409Sopenharmony_ci}
1039750e409Sopenharmony_ciUnityTestRunnerGenerator.new.run(testfile, runner_name, options)
1049750e409Sopenharmony_ci```
1059750e409Sopenharmony_ci
1069750e409Sopenharmony_ciIf you have multiple files to generate in a build script (such as a Rakefile),
1079750e409Sopenharmony_ciyou might want to instantiate a generator object with your options and call it
1089750e409Sopenharmony_cito generate each runner thereafter. Like thus:
1099750e409Sopenharmony_ci
1109750e409Sopenharmony_ci```Ruby
1119750e409Sopenharmony_cigen = UnityTestRunnerGenerator.new(options)
1129750e409Sopenharmony_citest_files.each do |f|
1139750e409Sopenharmony_ci  gen.run(f, File.basename(f,'.c')+"Runner.c"
1149750e409Sopenharmony_ciend
1159750e409Sopenharmony_ci```
1169750e409Sopenharmony_ci
1179750e409Sopenharmony_ci#### Options accepted by generate_test_runner.rb:
1189750e409Sopenharmony_ci
1199750e409Sopenharmony_ciThe following options are available when executing `generate_test_runner`. You
1209750e409Sopenharmony_cimay pass these as a Ruby hash directly or specify them in a YAML file, both of
1219750e409Sopenharmony_ciwhich are described above. In the `examples` directory, Example 3's Rakefile
1229750e409Sopenharmony_cidemonstrates using a Ruby hash.
1239750e409Sopenharmony_ci
1249750e409Sopenharmony_ci
1259750e409Sopenharmony_ci##### `:includes`
1269750e409Sopenharmony_ci
1279750e409Sopenharmony_ciThis option specifies an array of file names to be `#include`'d at the top of
1289750e409Sopenharmony_ciyour runner C file. You might use it to reference custom types or anything else
1299750e409Sopenharmony_ciuniversally needed in your generated runners.
1309750e409Sopenharmony_ci
1319750e409Sopenharmony_ci
1329750e409Sopenharmony_ci##### `:suite_setup`
1339750e409Sopenharmony_ci
1349750e409Sopenharmony_ciDefine this option with C code to be executed _before any_ test cases are run.
1359750e409Sopenharmony_ci
1369750e409Sopenharmony_ciAlternatively, if your C compiler supports weak symbols, you can leave this
1379750e409Sopenharmony_cioption unset and instead provide a `void suiteSetUp(void)` function in your test
1389750e409Sopenharmony_cisuite.  The linker will look for this symbol and fall back to a Unity-provided
1399750e409Sopenharmony_cistub if it is not found.
1409750e409Sopenharmony_ci
1419750e409Sopenharmony_ci
1429750e409Sopenharmony_ci##### `:suite_teardown`
1439750e409Sopenharmony_ci
1449750e409Sopenharmony_ciDefine this option with C code to be executed _after all_ test cases have
1459750e409Sopenharmony_cifinished.  An integer variable `num_failures` is available for diagnostics.
1469750e409Sopenharmony_ciThe code should end with a `return` statement; the value returned will become
1479750e409Sopenharmony_cithe exit code of `main`.  You can normally just return `num_failures`.
1489750e409Sopenharmony_ci
1499750e409Sopenharmony_ciAlternatively, if your C compiler supports weak symbols, you can leave this
1509750e409Sopenharmony_cioption unset and instead provide a `int suiteTearDown(int num_failures)`
1519750e409Sopenharmony_cifunction in your test suite.  The linker will look for this symbol and fall
1529750e409Sopenharmony_ciback to a Unity-provided stub if it is not found.
1539750e409Sopenharmony_ci
1549750e409Sopenharmony_ci
1559750e409Sopenharmony_ci##### `:enforce_strict_ordering`
1569750e409Sopenharmony_ci
1579750e409Sopenharmony_ciThis option should be defined if you have the strict order feature enabled in
1589750e409Sopenharmony_ciCMock (see CMock documentation). This generates extra variables required for
1599750e409Sopenharmony_cieverything to run smoothly. If you provide the same YAML to the generator as
1609750e409Sopenharmony_ciused in CMock's configuration, you've already configured the generator properly.
1619750e409Sopenharmony_ci
1629750e409Sopenharmony_ci
1639750e409Sopenharmony_ci##### `:plugins`
1649750e409Sopenharmony_ci
1659750e409Sopenharmony_ciThis option specifies an array of plugins to be used (of course, the array can
1669750e409Sopenharmony_cicontain only a single plugin). This is your opportunity to enable support for
1679750e409Sopenharmony_ciCException support, which will add a check for unhandled exceptions in each
1689750e409Sopenharmony_citest, reporting a failure if one is detected. To enable this feature using Ruby:
1699750e409Sopenharmony_ci
1709750e409Sopenharmony_ci```Ruby
1719750e409Sopenharmony_ci:plugins => [ :cexception ]
1729750e409Sopenharmony_ci```
1739750e409Sopenharmony_ci
1749750e409Sopenharmony_ciOr as a yaml file:
1759750e409Sopenharmony_ci
1769750e409Sopenharmony_ci```YAML
1779750e409Sopenharmony_ci:plugins:
1789750e409Sopenharmony_ci  -:cexception
1799750e409Sopenharmony_ci```
1809750e409Sopenharmony_ci
1819750e409Sopenharmony_ciIf you are using CMock, it is very likely that you are already passing an array
1829750e409Sopenharmony_ciof plugins to CMock. You can just use the same array here. This script will just
1839750e409Sopenharmony_ciignore the plugins that don't require additional support.
1849750e409Sopenharmony_ci
1859750e409Sopenharmony_ci
1869750e409Sopenharmony_ci### `unity_test_summary.rb`
1879750e409Sopenharmony_ci
1889750e409Sopenharmony_ciA Unity test file contains one or more test case functions. Each test case can
1899750e409Sopenharmony_cipass, fail, or be ignored. Each test file is run individually producing results
1909750e409Sopenharmony_cifor its collection of test cases. A given project will almost certainly be
1919750e409Sopenharmony_cicomposed of multiple test files. Therefore, the suite of tests is comprised of
1929750e409Sopenharmony_cione or more test cases spread across one or more test files. This script
1939750e409Sopenharmony_ciaggregates individual test file results to generate a summary of all executed
1949750e409Sopenharmony_citest cases. The output includes how many tests were run, how many were ignored,
1959750e409Sopenharmony_ciand how many failed. In addition, the output includes a listing of which
1969750e409Sopenharmony_cispecific tests were ignored and failed. A good example of the breadth and
1979750e409Sopenharmony_cidetails of these results can be found in the `examples` directory. Intentionally
1989750e409Sopenharmony_ciignored and failing tests in this project generate corresponding entries in the
1999750e409Sopenharmony_cisummary report.
2009750e409Sopenharmony_ci
2019750e409Sopenharmony_ciIf you're interested in other (prettier?) output formats, check into the
2029750e409Sopenharmony_ciCeedling build tool project (ceedling.sourceforge.net) that works with Unity and
2039750e409Sopenharmony_ciCMock and supports xunit-style xml as well as other goodies.
2049750e409Sopenharmony_ci
2059750e409Sopenharmony_ciThis script assumes the existence of files ending with the extensions
2069750e409Sopenharmony_ci`.testpass` and `.testfail`.The contents of these files includes the test
2079750e409Sopenharmony_ciresults summary corresponding to each test file executed with the extension set
2089750e409Sopenharmony_ciaccording to the presence or absence of failures for that test file. The script
2099750e409Sopenharmony_cisearches a specified path for these files, opens each one it finds, parses the
2109750e409Sopenharmony_ciresults, and aggregates and prints a summary. Calling it from the command line
2119750e409Sopenharmony_cilooks like this:
2129750e409Sopenharmony_ci
2139750e409Sopenharmony_ci```Shell
2149750e409Sopenharmony_ciruby unity_test_summary.rb build/test/
2159750e409Sopenharmony_ci```
2169750e409Sopenharmony_ci
2179750e409Sopenharmony_ciYou can optionally specify a root path as well. This is really helpful when you
2189750e409Sopenharmony_ciare using relative paths in your tools' setup, but you want to pull the summary
2199750e409Sopenharmony_ciinto an IDE like Eclipse for clickable shortcuts.
2209750e409Sopenharmony_ci
2219750e409Sopenharmony_ci```Shell
2229750e409Sopenharmony_ciruby unity_test_summary.rb build/test/ ~/projects/myproject/
2239750e409Sopenharmony_ci```
2249750e409Sopenharmony_ci
2259750e409Sopenharmony_ciOr, if you're more of a Windows sort of person:
2269750e409Sopenharmony_ci
2279750e409Sopenharmony_ci```Shell
2289750e409Sopenharmony_ciruby unity_test_summary.rb build\teat\ C:\projects\myproject\
2299750e409Sopenharmony_ci```
2309750e409Sopenharmony_ci
2319750e409Sopenharmony_ciWhen configured correctly, you'll see a final summary, like so:
2329750e409Sopenharmony_ci
2339750e409Sopenharmony_ci```Shell
2349750e409Sopenharmony_ci--------------------------
2359750e409Sopenharmony_ciUNITY IGNORED TEST SUMMARY
2369750e409Sopenharmony_ci--------------------------
2379750e409Sopenharmony_ciblah.c:22:test_sandwiches_should_HaveBreadOnTwoSides:IGNORE
2389750e409Sopenharmony_ci
2399750e409Sopenharmony_ci-------------------------
2409750e409Sopenharmony_ciUNITY FAILED TEST SUMMARY
2419750e409Sopenharmony_ci-------------------------
2429750e409Sopenharmony_ciblah.c:87:test_sandwiches_should_HaveCondiments:FAIL:Expected 1 was 0
2439750e409Sopenharmony_cimeh.c:38:test_soda_should_BeCalledPop:FAIL:Expected "pop" was "coke"
2449750e409Sopenharmony_ci
2459750e409Sopenharmony_ci--------------------------
2469750e409Sopenharmony_ciOVERALL UNITY TEST SUMMARY
2479750e409Sopenharmony_ci--------------------------
2489750e409Sopenharmony_ci45 TOTAL TESTS 2 TOTAL FAILURES 1 IGNORED
2499750e409Sopenharmony_ci```
2509750e409Sopenharmony_ci
2519750e409Sopenharmony_ciHow convenient is that?
2529750e409Sopenharmony_ci
2539750e409Sopenharmony_ci
2549750e409Sopenharmony_ci*Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)*
255