Embunit User Guide
Embunit User Guide
Release 1.0.1
Table of contents
Embunit is a unit testing tool aimed at the particular needs of embedded systems development. It has been
developed with flexibility in mind and makes no assumptions about the resources available on the target
system, or the tools used to download and run the unit tests.
It allows you to specify and organise your unit tests at a high level.
It automatically generates the source code for your unit tests, including code to log the test results.
Your test specification is stored as a text file in XML format. It can be kept under version control and
changes can be reviewed using a file comparison utility. The automatic code generation means that you
have more time to focus on what needs to be tested. You can write tests first, even if you have not finished
defining the interface. The generated source code can be reviewed and also kept under version control.
Due to the wide range of tools used for embedded systems development Embunit cannot build and run
your tests, you must do this yourself. Many modern IDE's can be scripted to automate this process, consult
the documentation for the tools you are using. The way that your system indicates whether the tests have
passed or failed is heavily dependent on the tools you are using and the available I/O. Embunit uses a set
of functions that can be customised to suit your target. The example implementation supplied with Embunit
uses the standard output to report test results.
Conventions
The following conventions are adopted throughout this User Guide:
When the location of a folder or file created at installation time is specified, the default installation folder
(C:\Program Files\Apollo Systems\Embunit) is assumed.
Installing Embunit
License management
Once Embunit is running you can start creating unit tests straight away.
Embunit creates an empty test suite, to which you add your test cases, specify what header files to include,
and reference any stub files that are needed.
The tree view (top left) shows the hierarchical organisation of the test suite.
The list view (top right) shows a list of elements at the current node in the tree.
The details box (bottom left) displays more detail about the current node.
The output box (bottom right) displays messages when generating the test harness.
Use the New, Edit, and Delete buttons to create and edit the various elements of the test suite.
Use the Up and Down buttons to change the order of the elements.
Use the Generate test harness button to generate the source code for your unit tests.
1. Run the self-extracting .exe file and follow the prompts to unzip the files to a suitable location.
2. Locate the setup.exe file that has just been unzipped and run it.
3. If necessary, the .NET 4.0 Client Profile is installed and you are prompted to restart your computer.
4. Following the restart the main Embunit installer starts automatically. If it does not, run setup.exe again.
Pre-requisites
Admin rights are required in order to install the .NET 4.0 Client Profile.
If the .NET 4.0 Client Profile is already installed Embunit can be installed by users without admin rights.
You can also access the form from the Help menu.
To start the 30-day evaluation of Embunit, click the button labelled "I want to evaluate the software".
The number of days left for evaluation is displayed in the box above the button.
If you have been supplied with a license key; enter it in the "New license key:" edit box, and click the
Activate button.
If the license is accepted it moves to the "License key:" box at the top of the form, otherwise an error
message is displayed in the box at the bottom of the form.
This comprises a header and source file for the test suite (containing the main() function), and a separate
source file for each test case.
To build a fully functioning test harness the generated source files need to be compiled and linked with:
The test framework source files contain common functions for indicating test results, counting failures, and
so on. The functions are spilt into two groups; those that need to be customised for each target, and those
that do not. Furthermore, there are different versions for C and C++, so you need to build with the
appropriate version:
OR
Configuration
There are currently no configuration options for Embunit.
The only thing you have to do is customise a small set of functions to suit each of your target systems.
Examples are provided that work straight out of the box if your target supports printf or std::cout.
Target-specific functions
Getting help
You can access this user guide from the Help menu. It is also supplied in PDF and Word format in the Doc
folder:
You can obtain the latest version of this guide and further information at:
http://www.embunit.com
Uninstalling Embunit
To uninstall Embunit; go to Control Panel and then, depending on your operating system, select:
If necessary (Windows 7), click the "Uninstall a program" link to obtain a list of programs.
Find Embunit in the list of programs, select it and click the appropriate button (Uninstall or Remove).
System requirements
The minimum system requirements for Embunit are:
512MB of RAM
Embunit uses the .NET 4.0 Client Profile; this is installed automatically if not already present.
All the unit tests, includes, and stub file references that together make up your test specification are known
as a 'test suite'.
Embunit allows you to create, save, and open existing test suites using the File menu.
File extensions
Save your test suites with the file extension .eut.
The installer associates files with the extension .eut with Embunit.
GUI
The test suite is at the root of the tree in the tree view.
When you click the test suite a list of test cases is displayed in the list view, and information about the test
suite appears in the details box.
To edit information about the test suite select it in the tree view and click the Edit button.
Note: The New and Delete buttons have no effect on the test suite. If you want to create a new test suite
use the File menu.
Name
The name you choose for the test suite is used during test harness generation to create a name for the test
suite header and source files, and in the case of C++ the test suite class name as well.
File names
Description
The description is inserted in the test suite header and source files during test harness generation.
Warning: Do NOT insert newlines in the test case description (using ctrl-return) or the generated files may
not compile.
Use the radio buttons to select whether you want to generate C or C++ code.
Click the Results button to edit the test result generation options.
Verbose output
Check this box if you want the test harness to generate a string containing the parameters of each test.
This can be useful to quickly identify which test has failed, but does increase the size of the test harness.
If this box is checked a call to embunit_Info() is inserted for every test during test harness generation (see
Target-independent functions).
Source file
Specify the source file that contains your target-specific test framework functions.
Target-specific functions
Import
Check this box if you want to import the code during test harness generation.
If the code is not being imported, Embunit inserts a comment specifying the path and file name in the
test suite source file.
If the code is being imported, Embunit inserts a comment and then inserts the entire contents of the file
in the test suite source file, followed by another comment to indicate the end of the code. If the file
cannot be opened Embunit inserts a comment to that effect.
The Includes 'folder' contains a list of files that need to be included in the test case source code.
Typically these are the header files for the classes and functions you are testing.
There is an Includes 'folder' at the top (test suite) level where you can add files that need to be included in
every test case.
Each test case also has its own Includes 'folder' where you can add files that are specific to that particular
test case.
List view
When you click the Includes 'folder' a list of file names (without any path information) is displayed in the list
view.
If you expand the Includes 'folder' and click on an individual file (in the tree view) the path and file name is
displayed in the list view.
The Stubs 'folder' contains a list of files containing stub code that need to be built with the test harness.
There is a Stubs 'folder' at the top (test suite) level where you can add files that need to be imported into
the test suite source file.
Tip: Use this if you have stub code that is common to all test cases.
Each test case also has its own Stubs 'folder' where you can add files that only need to be imported into
one particular test case source file.
List view
When you click the Stubs 'folder' a list of file names (without any path information) is displayed in the list
view.
If you expand the Stubs 'folder' and click on an individual file (in the tree view) two columns are displayed in
the list view. The first contains the path and file name; the second indicates whether the stub file will be
imported when the test harness is generated.
If the stub file is not being imported, Embunit inserts a comment specifying the path and file name in
the source file.
If the stub file is being imported, Embunit inserts a comment and then inserts the entire contents of the
stub file in the source file, followed by another comment to indicate the end of the stub code. If the stub
file cannot be opened Embunit inserts a comment to that effect.
Test cases are central to Embunit; they are where you define what your unit tests should do.
The core of a test case is a list of operations known as test case items. These are the building blocks from
which you construct your tests.
Each test case is a separate function/method in your test harness, so its name must be unique (within the
test suite).
Each test case also has its own Includes and Stubs 'folders'.
Includes
Stubs
When you click on the test suite (in the tree view) a list of test cases is displayed in the list view.
When you expand the test suite 'node' the test cases are displayed in the tree view.
When you click a test case in the tree view a list of its test case items is displayed in the list view, and
information about the test case appears in the details box.
The order of test cases and test case items can be changed using the Up/Down controls.
A dialog box is displayed allowing you to enter the test case name etc.
The new test case is appended to the end of the list. To insert a new test case at a particular position;
select the test suite as before and then select the desired insertion point in the list view. Finally, click the
New button.
The new test case item is appended to the end of the list. To insert an item at a particular position; select
the test case as before and then select the desired insertion point in the list view. Finally, click the New
button.
To edit the information about the test case; select the test case and click the Edit button.
Name
The name you choose for the test case is used during test harness generation to create a name for the test
case source file, and the test case function/method.
File names
Description
The description is inserted in the test case source file during test harness generation.
Warning: Do NOT insert newlines in the test case description (using ctrl-return) or the generated files may
not compile.
Test case items are the building blocks of your test cases.
They comprise a simple set of operations that can be used to define your test specification.
Select the type of test case item you want to create, and click OK.
Call
Context
Create
Delete
Test
Object
If you are calling a method of an object, enter the name of the object. Otherwise leave this field blank.
Do not add a member access operator. Embunit automatically generates the correct operator ('.' or '->')
depending on how the object is created (see Create).
Function
Arguments
The arguments are shown in a list, and are passed to the function/method in the order they are listed.
Use the Edit and Delete buttons to edit or delete existing arguments.
Select the position in the list where you want to insert a new argument.
Value
Variable
Function/method call
Use the radio buttons to specify whether the new argument is a value, a variable, or a function/method call.
Using the text box, enter the value, the name of the variable, or the name of the function/method, and
click the Add button.
You should now edit the argument and enter any further information that may be required.
Value
This dialog is displayed when you edit a 'Value'.
Embunit inserts values in your test harness source code exactly as you specify them, without any checks or
special formatting.
This makes values very flexible, but also means that you have to take care of any quotes, brackets, or
other formatting that may be necessary.
Examples:
Object
If the variable is a member of an object, enter the name of the object. Otherwise leave this field blank.
Do not add a member access operator. Embunit automatically generates the correct operator ('.' or '->')
depending on how the object is created.
Create
Variable
Context
The Context dialog is displayed when you create or edit an existing 'Context' test case item.
The context is an integer value that can be accessed from stub code.
It can be set anywhere in a test case and retains its value until set by another context test case item.
For readability it is recommended that you use an enum or a set of #define statements to specify the
context values. These should be put in a header file and included in the test suite (see Includes).
Note: A 'Create' item can be nested in a 'Test' item for the purpose of testing constructor exceptions.
Type
Enter the type of the object. You can use built in types or your own classes, structures, and enums.
Name
Note: You cannot use the same name to create different objects in the same test case.
Array
Check the box if you want to create an array, and enter the Size of the array in the text box.
Note: If you have already specified initialization values before checking the box, Embunit converts them to
a comma separated list of values. If any initializer is a 'Variable' or function/method 'Call' the conversion is
aborted and Embunit displays an error message.
Initializers
Initializers
Array initializers
Note: Arrays created on the heap cannot have initializers, Embunit warns you about this situation when you
click the OK button.
By default objects are created as local variables on the stack. Check the Create on the heap box if you
want the object to be created on the heap and accessed using a pointer.
All objects created on the heap must have a corresponding 'Delete' test case item, otherwise a
memory leak will occur when running the test harness.
Note: Embunit automatically generates the correct member access operator, so you can switch between
creating on the stack and the heap without affecting any other test case items.
Initializers
This dialog is displayed when you edit the initializers of a 'Create' test case item.
If you generate C code, only the first initializer is used; any others are ignored.
If you generate C++ code, the initializers are passed to the constructor in the order they are listed.
Use the Edit and Delete buttons to edit or delete existing initializers.
Select the position in the list where you want to insert a new initializer.
Value
Variable
Use the radio buttons to specify whether the new initializer is a value, a variable, or a function/method call.
Using the text box, enter the value, the name of the variable, or the name of the function/method, and
click the Add button.
You should now edit the initializer and enter any further information that may be required.
Array initializers
This dialog is displayed when you edit the initializers of a 'Create' test case item.
Note: This dialog is only used for arrays, for single objects see Initializers.
Delete
The Delete dialog is displayed when you create or edit an existing 'Delete' test case item.
All objects created on the heap must have a corresponding 'Delete' test case item (see Create).
Name
This is the key building block of your unit tests, it is where you specify what you expect from the software
under test.
If the assertion is true the test has passed, if it is false the test has failed.
Embunit displays error/warning messages if the operands and assertion you select are not compatible.
Operand 1
Value
Variable
Function/method Call
Create
Note: The Create type can only be used to test constructor exceptions, and is greyed out unless the
assertion is 'throws'.
Use the radio buttons to select the type of operand then click the Edit button.
If the type of operand has already been defined the radio buttons are greyed out.
You are prompted to confirm that you want to reset the operand.
Assertion
Assertions
Tolerance
The tolerance is used when testing that two floating point numbers are equal (or not equal). It is greyed out
at all other times.
Operand 2
Operand 2 is greyed out if the selected assertion only takes one operand.
Value
Variable
Function/method Call
none
Note: The default operand type 'none' cannot be used with assertions that require two operands.
Use the radio buttons to select the type of operand then click the Edit button.
If the type of operand has already been defined the radio buttons are greyed out.
You are prompted to confirm that you want to reset the operand.
Assertions
You can choose from the following assertions:
Assert # Test
ion operand
s
true 1 Test that Operand 1 is true
false 1 Test that Operand 1 is false
== 2 Test that Operand 1 equals Operand 2
!= 2 Test that Operand 1 does not equal Operand 2
> 2 Test that Operand 1 is greater than Operand 2
>= 2 Test that Operand 1 is greater than or equal to Operand 2
< 2 Test that Operand 1 is less than Operand 2
<= 2 Test that Operand 1 is less than or equal to Operand 2
2 Test that Operand 1 is almost equal to Operand 2 (see Note)
! 2 Test that Operand 1 is not almost equal to Operand 2 (see Note)
throws 1 or 2 Test that Operand 1 throws an exception. Operand 2 is optional and is used to specify
the exception type.
Note: These assertions compare two floating point numbers for (non-)equivalence using the tolerance
value. This is achieved by calling the embunit_IsAlmostEqual() test framework function (see Target-specific
functions).
To test whether two C-style strings are the same call the standard library function strcmp(), passing the two
strings, and test the return value.
Tolerance
The tolerance is used when testing that two floating point numbers are equal (or not equal).
This is achieved by calling the embunit_IsAlmostEqual() test framework function (see Target-specific
functions).
The default implementation of embunit_IsAlmostEqual() uses the value in the tolerance box as a power of
ten (exponent).
OR
You are free to change the implementation of embunit_IsAlmostEqual() and the interpretation of the value
entered in the GUI if you so wish.
New items can be created by selecting the tree view or the list view and clicking the New button.
Tree View
To create a new item, select a node in the tree view and click the New button.
In general, the new item is created at the end of the corresponding list in the list view.
The exception to this is when you have selected an individual file in the Includes or Stubs 'folder'. In this
case the selected file serves as the insertion point and the new item is inserted above it.
List view
To create a new item in the list view, select the insertion point and click the New button.
The last row in the list is a dummy item containing text in square brackets (e.g. [New test case]). To add a
new item at the end of the list select this row and click the New button.
There are Edit and Delete buttons on the main GUI, and on some of the test case item dialog boxes (Call,
Create-Initializers).
On the main GUI the Edit and Delete buttons operate on items in the tree view and the list view.
Note: Includes and Stubs 'folders' cannot be edited or deleted. The test suite cannot be deleted, but it can
be edited.
Delete control
You can delete more than one item at a time by selecting multiple items using the Shift or Ctrl keys (does
not apply to the tree view).
When you delete something on the main GUI you are given the option to cancel the operation.
When you delete something in a test case item dialog box you do not get an option to cancel the operation.
There are Up/Down buttons on the main GUI, and on some of the test case item dialog boxes (Call, Create-
Initializers).
On the main GUI the Up and Down buttons operate on items in the list view. They do not operate on items
in the tree view.
Select the required item in the list and use the appropriate button to move it up or down.
Note: Only one item is moved, if you select multiple items only the top item is moved.
You can generate the source code for your unit tests by clicking the Generate test harness button on the
GUI, or using the Command line interface.
Embunit automatically saves the test suite before generating the source code, or prompts you to enter a file
name if it is a new test suite that has never been saved.
The results of the code generation operation are displayed in the output box and also saved in a log file.
The log file is overwritten each time you generate the test harness.
Embunit generates a header and source file for the test suite (containing the main() function), and a
separate source file for each test case.
If you generate C code, each test case is a separate function called by main().
If you generate C++ code, a test suite class is created and each test case is a separate method called by
main().
Parameter Description
/c (optional) generate C code (the default is C++)
"test_suite_file" an XML test suite file (created using Embunit)
"output_folder" (optional) path of the output folder
If "output_folder" is not specified the files are created in the Projects folder (see Output folder).
Note: Quotation marks are only necessary where the path or filename contains spaces.
Where is thgen?
The executable thgen.exe is located in the Bin folder (below the main installation folder).
The name of the folder is the same as your test suite file, minus the file extension. If there is no file
extension Embunit appends an underscore to differentiate between the two names.
If Embunit fails to create the output folder it uses the Projects folder instead:
If the Projects folder does not exist (and cannot be created) Embunit uses the local application folder:
File names
The test suite header and source file name is generated from the test suite name by replacing any invalid
characters with underscores, and appending "_ts".
The test case source file name is generated from the test case name by replacing any invalid characters
with underscores, and appending "_tc".
The name of the log file is the same as your test suite file, but with the extension .log.
If the original extension is .log Embunit appends another .log to differentiate between the files.
The test framework functions are common functions for indicating test results, counting failures, and so on.
The functions are spilt into two groups; those that are target-specific, and those that are not.
The source files are located in the Lib folder. Separate versions are supplied for C:
and C++:
Note: If you have a number of different targets, you may prefer to keep your customised files with the rest
of your project files, rather than the Lib folder.
Header files
embunitc.h
embunit.h
The test framework functions that are called by the generated source files are declared in these header
files. The interfaces should not be changed.
Customisation
Target-specific functions
Target-independent functions
Memory allocation in C
embunit_IsAlmostEqual() is declared in the header files embunitc.h and embunit.h. You can change the
implementation of the function but you cannot change the interface.
As far as the other functions are concerned, you can change both the implementation and the interface to
suit your requirements. The functions are declared in embunitc.c and embunit.cpp using the extern
keyword.
You must tailor the functions to suit the I/O available on your target system.
embunitc.c
Note: The C++ get/set functions embunit_Case(), embunit_Step(), and embunit_Context() are overloaded.
Memory allocation in C
When an object is created on the heap the C code generator calls the macro embunit_calloc (defined in
embunitc.h).
Similarly, when the object is deleted the C code generator calls the macro embunit_free (also defined in
embunitc.h).
These macros are implemented using the standard library functions malloc() and free().
If you have a custom memory allocator you can redefine these macros to suit.
This section contains useful tips to help you get the most out of Embunit.
If your system does not have a serial port there are several other options (depending on the I/O that is
available to you) including:
Ethernet
Saving to a file
Storing in non-volatile memory
Toggling a digital I/O line
If none of these approaches are suitable you may have to store the results in memory and use your
debugger to retrieve them.
As an alternative to running on the target hardware, some tools provide a simulator that allows you to run
your code on the PC while still interacting with simulated on-chip peripherals. These usually have a console
window to which you can send your test results.
As a last resort, algorithms that do not interact with hardware can be tested by creating a console
application to run on the PC, but watch out for portability issues concerning word sizes and endianness.
Example implementations are given in TestResultToFile.c and TestResultToFile.cpp, which can be found in
the Lib folder.
If your test harness is in C you need to include embunitc.h and use these functions:
If your test harness is in C++ you need to include embunit.h and use these functions:
By making the test suite class a friend of the class under test you gain access to its private members.
Example:
These should be put in a header file and included in the test suite (see Includes).
However this can be achieved by adding a Call test case item and leaving the Object and Function fields
blank.
Add a Variable argument to the call and put the code to do the assignment in the Variable field.
The same technique can be used for increment and decrement operators.
Structure my tests
When starting out it can be difficult to judge whether to have big test cases with lots of tests, or lots of
smaller test cases.
You could have one test case per function/method, or you might decide to group several tests together.
Ultimately the answer depends on your own circumstances and preferences.
The main thing to bear in mind when making your choice is the scope of objects.
Each test case is a separate function/method in a separate source file, so any objects that are created are
local to that test case.
Note: You cannot insert a copyright block in the test suite header file using a stub file.
Simply add the copyright text to the test suite and test case descriptions.
You need to create a stub file that contains the copyright text (as a comment).
To insert the copyright block in the test suite source file; add the stub file at the top level and check the
Import box.
To insert the copyright block in a test case source file; add the stub file at the test case level and check the
Import box.
Note: The steps described above compare the arrays for equality. Testing for inequality can be achieved by
changing the assertion to "!=". Refer to documentation on memcmp() for more information.
An example, which compares the first 16 bytes of two arrays called int_array and other_int_array, is shown
below:
Note: The steps described above compare the strings for equality. Testing for inequality can be achieved
by changing the assertion to "!=", and more specific tests can be performed using the "<" and ">"
assertions. Refer to documentation on strcmp() for more information.
An example, which compares the string returned by the function call person_name(&uut) with the string
"Frederick", is shown below:
This section lists the error and warning messages you may encounter when using Embunit.
Error messages generally prevent you from continuing with the current operation, whereas warning
messages do not.
Code generation errors are stored in the log file and displayed in the output box or on the command line, as
appropriate.
Errors
Error opening file
The file does not contain a test suite
The test suite file you are trying to open does not conform to the Embunit XML DTD. Make sure you are
using a file that was generated by Embunit.
The test suite file you are trying to open does not contain XML. Make sure you are using a file that was
generated by Embunit.
You have a Create item that specifies an array, but you have not specified the size of the array.
You have a Create item and have already specified the initializers. You are now changing it to be an array,
but at least one of the initializers is a function call or variable.
You have a Test item with no operands, and are trying to edit Operand 2. You must define Operand 1
before you can edit Operand 2.
You have a Test item with no operands, and have clicked the OK button. You must either define an
operand, or click the Cancel button.
The only Test item assertions that take a single operand are 'true', 'false', and 'throws' (optional second
operand). All other assertions require two operands.
You have a Test item that checks that an exception is thrown. Operand 2 specifies the exception type,
You have a Test item that is comparing two floating point numbers for (non-)equivalence. You must specify
a tolerance for the comparison.
If you want to check whether two floating point numbers are exactly the same use the '==' assertion.
Warnings
Embunit - Array initializers will be ignored
Arrays created on the heap cannot have initializers.
You have a Create item that specifies an array with initializers. Initializers can only be used with arrays that
are created on the stack. When you generate the test harness the initializers will be ignored.
You have a Test item assertion that only requires Operand 1, but you have also defined Operand 2. Check
that you have specified the correct assertion.
You can delete Operand 2 by clicking the Reset button, and then selecting the 'none' radio button.
The test suite file does not conform to the Embunit XML DTD. Make sure you are using a file that was
generated by Embunit.
A folder could not be created. Make sure the application has the right permissions to create the folder.
A folder could not be created. Make sure the application has the right permissions to create the folder.