AceUnitAceUnit Manual

Table of Contents

Introduction

AceUnit (Advanced C and Embedded Unit): a comfortable C code unit test framework. AceUnit is JUnit 4.x style, easy, modular and flexible. AceUnit can be used in resource constraint environments, e.g. embedded software development.

Quick Overview

Unit Tests in AceUnit are declared using annotations. This works pretty much the same as JUnit 4.x. JUnit 4.x can be considered industry reference for unit test frameworks. Much of AceUnit was modelled after JUnit 4.x.

The most important annotation that you will need is A_Test. The A_Test annotation tells AceUnit that a function is a unit test. Simply place this as a modifier before your function declaration, where you would write static in case you would declare your function static. This annotation will be the main interface between your unit tests and the AceUnit framework which will run them.

Example

A_Test void someTestMethod() [
    // test case implementation for this test case goes here
}

Assume your source is named MyTest.c. There are only two more things which you will need in your source. Both of these things are very easy.

That's all what you need.

What is AceUnit.jar?

AceUnit.jar is a Java program and the core for automation in AceUnit. It scans a test source code and will generate all required information that the AceUnit framework will need to run your tests. That information will be placed in the specified header file.

We know that running Java in a C environment is not convenient in

Variants of Unit Test Declaration

AceUnit supports the following styles of declaring unit tests:

Annotation based testing

When declaring tests with annotations, the following annotations are available:

A_Test
Test annotation, use for test cases.
A_Before
Before annotation, use for methods that should be invoked before each test case in a fixture.
A_After
After annotation, use for methods that should be invoked after each test case in a fixture.
A_BeforeClass
BeforeClass annotation, use for methods that should be invoked once for the fixture before all of its test cases.
A_AfterClass
AfterClass annotation, use for methods that should be invoked once for the fixture after all of its test cases.
A_Ignore
Ignore annotation, use for test cases to ignore. This annotation is only allowed for methods annotated as A_Test.

AceUnit Glossary

Annotation
A C preprocessor macro that is defined empty for the compiler but meaningful for the AceUnit test code generator.
Class
See Fixture.
Fixture
A fixture, aka Test Class, is a collection of tests along with operations that shall be performed before or after all or each of the tests contained in the fixture.
Test
A single test case is a simple C function that will be called to perform the test.
Test Case
See Test.
Test Class
See Fixture.
Test Fixture
See Fixture.

The scheme of writing AceUnit tests

Writing AceUnit tests is easy, very easy.

Writing your first AceUnit test first software.

Our scenario is developing a sorting algorithm. A sorting algorithm works if the list that it was sorting is sorted after the algorithm is done. To verify whether a sorting algorithm works, we need verify that its data was sorted. Both, the sorting and the verification need a comparator that determines whether an element should be sorted before or after another element.

Testing Comparator

The comparator works when it returns the expected result for each pair of values.

/** A Comparator compares two values and returns a comparison result.
 * @param o1 Pointer to first object to compare.
 * @param o2 Pointer to second object to compare.
 * @return Comparison result
 * @retval 0 if o1 and o2 are equal.
 * @retval <0 if o1 should be sorted before o2.
 * @retval >0 if o1 should be sorted after o2.
 */
typedef sint8_least_t(*comparator)(const void *o1, const void *o2);

For testing purposes, we want to sort ints. So the first thing that we do is we test whether our comparator implementation works.

/** Comparator for int values.
 * @see comparator
 */
sint8_least_t compareInt(const void *o1, const void *o2) {
    return 0;
}

It is obvious that our current implementation is bogus. In test first programming, you intentionally start with a bogus implementation to verify that your test actually detects that the implementation is bogus.

/** Tests that {@link compareInt()} works. */
A_Test void testCompareInt() {
    int n1;
    int n2;

    n1 = 0;
    n2 = 0;
    assertEquals("Comparing two equal numbers must return 0.", 0, compareInt(&0, &1));

    n1 = 1;
    n2 = 2;
    assertTrue("Comparing 1 with 2 must return a value <0.", compareInt(&n1, &n2) < 0);

    n1 = 2;
    n2 = 1;
    assertTrue("Comparing 2 with 1 must return a value >0.", compareInt(&n1, &n2) > 0);
}

Options

AceUnit supports the following options:

#define ACEUNIT_STATIC_ASSERTIONS
By defining this macro you will cause annotations to be equivalent to static. That way you have easy and flexible control over whether test methods are static or not.

Declaring test methods as static has a significant advantage. You will be able to use the same name in different fixtures and still build and run them all together. For logging, it is not required that test methods have unique names. Logging will always also include the associated fixture (e.g. filename + line number). So you will always uniquely identify which test case failed, even if the names of the test cases are not unique.

However, there are debuggers which will cause head ache if you try to debug functions which are static. Some tool chains (compilers / linkers) will not emit proper debug information for functions which are static.

The pros and cons for static test methods are both very significant. Whether or not you want to use static depends on your environment. Because of that, we've left the choice to you.

But we've prepared everything for you. Toggling between these two options is as simple as (not) defining this macro.
#define ACEUNIT_EMBEDDED
By defining this macro you will turn AceUnit into embedded mode. In embedded mode, AceUnit tries to consume as little memory as possible. For instance, all strings are replaced by 16 bit values. Note: Currently this macro is not 100% functional.
Feedback: webmaster
$Id: manual.xhtml 224 2007-11-18 23:16:20Z christianhujer $
Copyright © 2007 - 2008 The AceUnit Developers. All Rights Reserved.