261 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			261 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
|   | # Unity Helper Scripts
 | ||
|  | 
 | ||
|  | ## With a Little Help From Our Friends
 | ||
|  | 
 | ||
|  | Sometimes what it takes to be a really efficient C programmer is a little non-C. | ||
|  | The Unity project includes a couple of Ruby scripts for making your life just a tad | ||
|  | easier. They are completely optional. If you choose to use them, you'll need a | ||
|  | copy of Ruby, of course. Just install whatever the latest version is, and it is | ||
|  | likely to work. You can find Ruby at [ruby-lang.org](https://ruby-labg.org/). | ||
|  | 
 | ||
|  | 
 | ||
|  | ### `generate_test_runner.rb`
 | ||
|  | 
 | ||
|  | Are you tired of creating your own `main` function in your test file? Do you | ||
|  | keep forgetting to add a `RUN_TEST` call when you add a new test case to your | ||
|  | suite? Do you want to use CMock or other fancy add-ons but don't want to figure | ||
|  | out how to create your own `RUN_TEST` macro? | ||
|  | 
 | ||
|  | Well then we have the perfect script for you! | ||
|  | 
 | ||
|  | The `generate_test_runner` script processes a given test file and automatically | ||
|  | creates a separate test runner file that includes ?main?to execute the test | ||
|  | cases within the scanned test file. All you do then is add the generated runner | ||
|  | to your list of files to be compiled and linked, and presto you're done! | ||
|  | 
 | ||
|  | This script searches your test file for void function signatures having a | ||
|  | function name beginning with "test" or "spec". It treats each of these | ||
|  | functions as a test case and builds up a test suite of them. For example, the | ||
|  | following includes three test cases: | ||
|  | 
 | ||
|  | ```C | ||
|  | void testVerifyThatUnityIsAwesomeAndWillMakeYourLifeEasier(void) | ||
|  | { | ||
|  |   ASSERT_TRUE(1); | ||
|  | } | ||
|  | void test_FunctionName_should_WorkProperlyAndReturn8(void) { | ||
|  |   ASSERT_EQUAL_INT(8, FunctionName()); | ||
|  | } | ||
|  | void spec_Function_should_DoWhatItIsSupposedToDo(void) { | ||
|  |   ASSERT_NOT_NULL(Function(5)); | ||
|  | } | ||
|  | ``` | ||
|  | 
 | ||
|  | You can run this script a couple of ways. The first is from the command line: | ||
|  | 
 | ||
|  | ```Shell | ||
|  | ruby generate_test_runner.rb TestFile.c NameOfRunner.c | ||
|  | ``` | ||
|  | 
 | ||
|  | Alternatively, if you include only the test file parameter, the script will copy | ||
|  | the name of the test file and automatically append "_Runner" to the name of the | ||
|  | generated file. The example immediately below will create TestFile_Runner.c. | ||
|  | 
 | ||
|  | ```Shell | ||
|  | ruby generate_test_runner.rb TestFile.c | ||
|  | ``` | ||
|  | 
 | ||
|  | You can also add a [YAML](http://www.yaml.org/) file to configure extra options. | ||
|  | Conveniently, this YAML file is of the same format as that used by Unity and | ||
|  | CMock. So if you are using YAML files already, you can simply pass the very same | ||
|  | file into the generator script. | ||
|  | 
 | ||
|  | ```Shell | ||
|  | ruby generate_test_runner.rb TestFile.c my_config.yml | ||
|  | ``` | ||
|  | 
 | ||
|  | The contents of the YAML file `my_config.yml` could look something like the | ||
|  | example below. If you're wondering what some of these options do, you're going | ||
|  | to love the next section of this document. | ||
|  | 
 | ||
|  | ```YAML | ||
|  | :unity: | ||
|  |   :includes: | ||
|  |     - stdio.h | ||
|  |     - microdefs.h | ||
|  |   :cexception: 1 | ||
|  |   :suit_setup: "blah = malloc(1024);" | ||
|  |   :suite_teardown: "free(blah);" | ||
|  | ``` | ||
|  | 
 | ||
|  | If you would like to force your generated test runner to include one or more | ||
|  | header files, you can just include those at the command line too. Just make sure | ||
|  | these are _after_ the YAML file, if you are using one: | ||
|  | 
 | ||
|  | ```Shell | ||
|  | ruby generate_test_runner.rb TestFile.c my_config.yml extras.h | ||
|  | ``` | ||
|  | 
 | ||
|  | Another option, particularly if you are already using Ruby to orchestrate your | ||
|  | builds - or more likely the Ruby-based build tool Rake - is requiring this | ||
|  | script directly. Anything that you would have specified in a YAML file can be | ||
|  | passed to the script as part of a hash. Let's push the exact same requirement | ||
|  | set as we did above but this time through Ruby code directly: | ||
|  | 
 | ||
|  | ```Ruby | ||
|  | require "generate_test_runner.rb" | ||
|  | options = { | ||
|  |   :includes => ["stdio.h", "microdefs.h"], | ||
|  |   :cexception => 1, | ||
|  |   :suite_setup => "blah = malloc(1024);", | ||
|  |   :suite_teardown => "free(blah);" | ||
|  | } | ||
|  | UnityTestRunnerGenerator.new.run(testfile, runner_name, options) | ||
|  | ``` | ||
|  | 
 | ||
|  | If you have multiple files to generate in a build script (such as a Rakefile), | ||
|  | you might want to instantiate a generator object with your options and call it | ||
|  | to generate each runner afterwards. Like thus: | ||
|  | 
 | ||
|  | ```Ruby | ||
|  | gen = UnityTestRunnerGenerator.new(options) | ||
|  | test_files.each do |f| | ||
|  |   gen.run(f, File.basename(f,'.c')+"Runner.c" | ||
|  | end | ||
|  | ``` | ||
|  | 
 | ||
|  | #### Options accepted by generate_test_runner.rb:
 | ||
|  | 
 | ||
|  | The following options are available when executing `generate_test_runner`. You | ||
|  | may pass these as a Ruby hash directly or specify them in a YAML file, both of | ||
|  | which are described above. In the `examples` directory, Example 3's Rakefile | ||
|  | demonstrates using a Ruby hash. | ||
|  | 
 | ||
|  | 
 | ||
|  | ##### `:includes`
 | ||
|  | 
 | ||
|  | This option specifies an array of file names to be `#include`'d at the top of | ||
|  | your runner C file. You might use it to reference custom types or anything else | ||
|  | universally needed in your generated runners. | ||
|  | 
 | ||
|  | 
 | ||
|  | ##### `:suite_setup`
 | ||
|  | 
 | ||
|  | Define this option with C code to be executed _before any_ test cases are run. | ||
|  | 
 | ||
|  | Alternatively, if your C compiler supports weak symbols, you can leave this | ||
|  | option unset and instead provide a `void suiteSetUp(void)` function in your test | ||
|  | suite.  The linker will look for this symbol and fall back to a Unity-provided | ||
|  | stub if it is not found. | ||
|  | 
 | ||
|  | 
 | ||
|  | ##### `:suite_teardown`
 | ||
|  | 
 | ||
|  | Define this option with C code to be executed _after all_ test cases have | ||
|  | finished.  An integer variable `num_failures` is available for diagnostics. | ||
|  | The code should end with a `return` statement; the value returned will become | ||
|  | the exit code of `main`.  You can normally just return `num_failures`. | ||
|  | 
 | ||
|  | Alternatively, if your C compiler supports weak symbols, you can leave this | ||
|  | option unset and instead provide a `int suiteTearDown(int num_failures)` | ||
|  | function in your test suite.  The linker will look for this symbol and fall | ||
|  | back to a Unity-provided stub if it is not found. | ||
|  | 
 | ||
|  | 
 | ||
|  | ##### `:enforce_strict_ordering`
 | ||
|  | 
 | ||
|  | This option should be defined if you have the strict order feature enabled in | ||
|  | CMock (see CMock documentation). This generates extra variables required for | ||
|  | everything to run smoothly. If you provide the same YAML to the generator as | ||
|  | used in CMock's configuration, you've already configured the generator properly. | ||
|  | 
 | ||
|  | ##### `:mock_prefix` and `:mock_suffix`
 | ||
|  | 
 | ||
|  | Unity automatically generates calls to Init, Verify and Destroy for every file | ||
|  | included in the main test file that starts with the given mock prefix and ends | ||
|  | with the given mock suffix, file extension not included. By default, Unity | ||
|  | assumes a `Mock` prefix and no suffix. | ||
|  | 
 | ||
|  | ##### `:plugins`
 | ||
|  | 
 | ||
|  | This option specifies an array of plugins to be used (of course, the array can | ||
|  | contain only a single plugin). This is your opportunity to enable support for | ||
|  | CException support, which will add a check for unhandled exceptions in each | ||
|  | test, reporting a failure if one is detected. To enable this feature using Ruby: | ||
|  | 
 | ||
|  | ```Ruby | ||
|  | :plugins => [ :cexception ] | ||
|  | ``` | ||
|  | 
 | ||
|  | Or as a yaml file: | ||
|  | 
 | ||
|  | ```YAML | ||
|  | :plugins: | ||
|  |   -:cexception | ||
|  | ``` | ||
|  | 
 | ||
|  | If you are using CMock, it is very likely that you are already passing an array | ||
|  | of plugins to CMock. You can just use the same array here. This script will just | ||
|  | ignore the plugins that don't require additional support. | ||
|  | 
 | ||
|  | 
 | ||
|  | ### `unity_test_summary.rb`
 | ||
|  | 
 | ||
|  | A Unity test file contains one or more test case functions. Each test case can | ||
|  | pass, fail, or be ignored. Each test file is run individually producing results | ||
|  | for its collection of test cases. A given project will almost certainly be | ||
|  | composed of multiple test files. Therefore, the suite of tests is comprised of | ||
|  | one or more test cases spread across one or more test files. This script | ||
|  | aggregates individual test file results to generate a summary of all executed | ||
|  | test cases. The output includes how many tests were run, how many were ignored, | ||
|  | and how many failed. In addition, the output includes a listing of which | ||
|  | specific tests were ignored and failed. A good example of the breadth and | ||
|  | details of these results can be found in the `examples` directory. Intentionally | ||
|  | ignored and failing tests in this project generate corresponding entries in the | ||
|  | summary report. | ||
|  | 
 | ||
|  | If you're interested in other (prettier?) output formats, check into the | ||
|  | Ceedling build tool project (ceedling.sourceforge.net) that works with Unity and | ||
|  | CMock and supports xunit-style xml as well as other goodies. | ||
|  | 
 | ||
|  | This script assumes the existence of files ending with the extensions | ||
|  | `.testpass` and `.testfail`.The contents of these files includes the test | ||
|  | results summary corresponding to each test file executed with the extension set | ||
|  | according to the presence or absence of failures for that test file. The script | ||
|  | searches a specified path for these files, opens each one it finds, parses the | ||
|  | results, and aggregates and prints a summary. Calling it from the command line | ||
|  | looks like this: | ||
|  | 
 | ||
|  | ```Shell | ||
|  | ruby unity_test_summary.rb build/test/ | ||
|  | ``` | ||
|  | 
 | ||
|  | You can optionally specify a root path as well. This is really helpful when you | ||
|  | are using relative paths in your tools' setup, but you want to pull the summary | ||
|  | into an IDE like Eclipse for clickable shortcuts. | ||
|  | 
 | ||
|  | ```Shell | ||
|  | ruby unity_test_summary.rb build/test/ ~/projects/myproject/ | ||
|  | ``` | ||
|  | 
 | ||
|  | Or, if you're more of a Windows sort of person: | ||
|  | 
 | ||
|  | ```Shell | ||
|  | ruby unity_test_summary.rb build\teat\ C:\projects\myproject\ | ||
|  | ``` | ||
|  | 
 | ||
|  | When configured correctly, you'll see a final summary, like so: | ||
|  | 
 | ||
|  | ```Shell | ||
|  | -------------------------- | ||
|  | UNITY IGNORED TEST SUMMARY | ||
|  | -------------------------- | ||
|  | blah.c:22:test_sandwiches_should_HaveBreadOnTwoSides:IGNORE | ||
|  | 
 | ||
|  | ------------------------- | ||
|  | UNITY FAILED TEST SUMMARY | ||
|  | ------------------------- | ||
|  | blah.c:87:test_sandwiches_should_HaveCondiments:FAIL:Expected 1 was 0 | ||
|  | meh.c:38:test_soda_should_BeCalledPop:FAIL:Expected "pop" was "coke" | ||
|  | 
 | ||
|  | -------------------------- | ||
|  | OVERALL UNITY TEST SUMMARY | ||
|  | -------------------------- | ||
|  | 45 TOTAL TESTS 2 TOTAL FAILURES 1 IGNORED | ||
|  | ``` | ||
|  | 
 | ||
|  | How convenient is that? | ||
|  | 
 | ||
|  | 
 | ||
|  | *Find The Latest of This And More at [ThrowTheSwitch.org](https://throwtheswitch.org)* |