CppUTest is a C /C++ based unit xUnit test framework for unit testing and for test-driving your code.

CppUTest

Where to find more information

Getting test reports on the console

You may need to tailor the file src/Platforms/mbed/UtestPlatform.cpp to your needs. In particular, if you want console output, you might want to look at the function PlatformSpecificPutchar().

Quick introduction (some code!)

To write your first test, all you need is a new cpp file with a TEST_GROUP and a TEST, like:

#include "CppUTest/TestHarness.h"

TEST_GROUP(FirstTestGroup)
{
};

TEST(FirstTestGroup, FirstTest)
{
   FAIL("Fail me!");
}

This test will fail.

You can add new tests to the test group by just writing more tests in the file, like this:

TEST(FirstTestGroup, SecondTest)
{
   STRCMP_EQUAL("hello", "world");
   LONGS_EQUAL(1, 2);
   CHECK(false);
}

You do need to trigger the tests from somewhere in your program. It could look something like:

#include "CppUTest/TestRegistry.h"
#include "CppUTest/CommandLineTestRunner.h"

int main(int ac, char** av)
{
    ....
    unsigned failureCount = 0;
    {
        ConsoleTestOutput output;
        CommandLineTestRunner runner(ac, av, &output, TestRegistry::getCurrentRegistry());
        failureCount = runner.runAllTestsMain();
    }

    if (failureCount == 0) {
        console.printf("PASSED\r\n");
    }
    ...
}

For more information, We’d recommend to read the manual or, even better, check some existing tests such as SimpleStringTest or (a bit more complicated) MemoryLeakDetectorTest or the mocking tests or just check out the Cheat Sheet.

Committer:
rgrover1
Date:
Tue Jan 28 09:27:41 2014 +0000
Revision:
0:0b799af9d58e
Child:
1:4769360130ed
CppUTest unit test framework.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
rgrover1 0:0b799af9d58e 1 /*
rgrover1 0:0b799af9d58e 2 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
rgrover1 0:0b799af9d58e 3 * All rights reserved.
rgrover1 0:0b799af9d58e 4 *
rgrover1 0:0b799af9d58e 5 * Redistribution and use in source and binary forms, with or without
rgrover1 0:0b799af9d58e 6 * modification, are permitted provided that the following conditions are met:
rgrover1 0:0b799af9d58e 7 * * Redistributions of source code must retain the above copyright
rgrover1 0:0b799af9d58e 8 * notice, this list of conditions and the following disclaimer.
rgrover1 0:0b799af9d58e 9 * * Redistributions in binary form must reproduce the above copyright
rgrover1 0:0b799af9d58e 10 * notice, this list of conditions and the following disclaimer in the
rgrover1 0:0b799af9d58e 11 * documentation and/or other materials provided with the distribution.
rgrover1 0:0b799af9d58e 12 * * Neither the name of the <organization> nor the
rgrover1 0:0b799af9d58e 13 * names of its contributors may be used to endorse or promote products
rgrover1 0:0b799af9d58e 14 * derived from this software without specific prior written permission.
rgrover1 0:0b799af9d58e 15 *
rgrover1 0:0b799af9d58e 16 * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
rgrover1 0:0b799af9d58e 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
rgrover1 0:0b799af9d58e 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
rgrover1 0:0b799af9d58e 19 * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
rgrover1 0:0b799af9d58e 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
rgrover1 0:0b799af9d58e 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
rgrover1 0:0b799af9d58e 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
rgrover1 0:0b799af9d58e 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
rgrover1 0:0b799af9d58e 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
rgrover1 0:0b799af9d58e 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
rgrover1 0:0b799af9d58e 26 */
rgrover1 0:0b799af9d58e 27
rgrover1 0:0b799af9d58e 28 #include "CppUTest/TestHarness.h"
rgrover1 0:0b799af9d58e 29 #include "CppUTest/CommandLineTestRunner.h"
rgrover1 0:0b799af9d58e 30 #include "CppUTest/TestOutput.h"
rgrover1 0:0b799af9d58e 31 #include "CppUTest/JUnitTestOutput.h"
rgrover1 0:0b799af9d58e 32 #include "CppUTest/TestRegistry.h"
rgrover1 0:0b799af9d58e 33
rgrover1 0:0b799af9d58e 34 CommandLineTestRunner::CommandLineTestRunner(int ac, const char** av, TestOutput* output, TestRegistry* registry) :
rgrover1 0:0b799af9d58e 35 output_(output), jUnitOutput_(NULL), arguments_(NULL), registry_(registry)
rgrover1 0:0b799af9d58e 36 {
rgrover1 0:0b799af9d58e 37 arguments_ = new CommandLineArguments(ac, av);
rgrover1 0:0b799af9d58e 38 }
rgrover1 0:0b799af9d58e 39
rgrover1 0:0b799af9d58e 40 CommandLineTestRunner::~CommandLineTestRunner()
rgrover1 0:0b799af9d58e 41 {
rgrover1 0:0b799af9d58e 42 delete arguments_;
rgrover1 0:0b799af9d58e 43 delete jUnitOutput_;
rgrover1 0:0b799af9d58e 44 }
rgrover1 0:0b799af9d58e 45
rgrover1 0:0b799af9d58e 46 int CommandLineTestRunner::RunAllTests(int ac, char** av)
rgrover1 0:0b799af9d58e 47 {
rgrover1 0:0b799af9d58e 48 return RunAllTests(ac, const_cast<const char**> (av));
rgrover1 0:0b799af9d58e 49 }
rgrover1 0:0b799af9d58e 50
rgrover1 0:0b799af9d58e 51 int CommandLineTestRunner::RunAllTests(int ac, const char** av)
rgrover1 0:0b799af9d58e 52 {
rgrover1 0:0b799af9d58e 53 int result = 0;
rgrover1 0:0b799af9d58e 54 ConsoleTestOutput output;
rgrover1 0:0b799af9d58e 55
rgrover1 0:0b799af9d58e 56 MemoryLeakWarningPlugin memLeakWarn(DEF_PLUGIN_MEM_LEAK);
rgrover1 0:0b799af9d58e 57 memLeakWarn.destroyGlobalDetectorAndTurnOffMemoryLeakDetectionInDestructor(true);
rgrover1 0:0b799af9d58e 58 TestRegistry::getCurrentRegistry()->installPlugin(&memLeakWarn);
rgrover1 0:0b799af9d58e 59
rgrover1 0:0b799af9d58e 60 {
rgrover1 0:0b799af9d58e 61 CommandLineTestRunner runner(ac, av, &output, TestRegistry::getCurrentRegistry());
rgrover1 0:0b799af9d58e 62 result = runner.runAllTestsMain();
rgrover1 0:0b799af9d58e 63 }
rgrover1 0:0b799af9d58e 64
rgrover1 0:0b799af9d58e 65 if (result == 0) {
rgrover1 0:0b799af9d58e 66 output << memLeakWarn.FinalReport(0);
rgrover1 0:0b799af9d58e 67 }
rgrover1 0:0b799af9d58e 68 TestRegistry::getCurrentRegistry()->removePluginByName(DEF_PLUGIN_MEM_LEAK);
rgrover1 0:0b799af9d58e 69 return result;
rgrover1 0:0b799af9d58e 70 }
rgrover1 0:0b799af9d58e 71
rgrover1 0:0b799af9d58e 72 int CommandLineTestRunner::runAllTestsMain()
rgrover1 0:0b799af9d58e 73 {
rgrover1 0:0b799af9d58e 74 int testResult = 0;
rgrover1 0:0b799af9d58e 75
rgrover1 0:0b799af9d58e 76 SetPointerPlugin pPlugin(DEF_PLUGIN_SET_POINTER);
rgrover1 0:0b799af9d58e 77 registry_->installPlugin(&pPlugin);
rgrover1 0:0b799af9d58e 78
rgrover1 0:0b799af9d58e 79 if (parseArguments(registry_->getFirstPlugin()))
rgrover1 0:0b799af9d58e 80 testResult = runAllTests();
rgrover1 0:0b799af9d58e 81
rgrover1 0:0b799af9d58e 82 registry_->removePluginByName(DEF_PLUGIN_SET_POINTER);
rgrover1 0:0b799af9d58e 83 return testResult;
rgrover1 0:0b799af9d58e 84 }
rgrover1 0:0b799af9d58e 85
rgrover1 0:0b799af9d58e 86 void CommandLineTestRunner::initializeTestRun()
rgrover1 0:0b799af9d58e 87 {
rgrover1 0:0b799af9d58e 88 registry_->groupFilter(arguments_->getGroupFilter());
rgrover1 0:0b799af9d58e 89 registry_->nameFilter(arguments_->getNameFilter());
rgrover1 0:0b799af9d58e 90 if (arguments_->isVerbose()) output_->verbose();
rgrover1 0:0b799af9d58e 91 if (arguments_->runTestsInSeperateProcess()) registry_->setRunTestsInSeperateProcess();
rgrover1 0:0b799af9d58e 92 }
rgrover1 0:0b799af9d58e 93
rgrover1 0:0b799af9d58e 94 int CommandLineTestRunner::runAllTests()
rgrover1 0:0b799af9d58e 95 {
rgrover1 0:0b799af9d58e 96 initializeTestRun();
rgrover1 0:0b799af9d58e 97 int loopCount = 0;
rgrover1 0:0b799af9d58e 98 int failureCount = 0;
rgrover1 0:0b799af9d58e 99 int repeat_ = arguments_->getRepeatCount();
rgrover1 0:0b799af9d58e 100
rgrover1 0:0b799af9d58e 101 while (loopCount++ < repeat_) {
rgrover1 0:0b799af9d58e 102 output_->printTestRun(loopCount, repeat_);
rgrover1 0:0b799af9d58e 103 TestResult tr(*output_);
rgrover1 0:0b799af9d58e 104 registry_->runAllTests(tr);
rgrover1 0:0b799af9d58e 105 failureCount += tr.getFailureCount();
rgrover1 0:0b799af9d58e 106 }
rgrover1 0:0b799af9d58e 107
rgrover1 0:0b799af9d58e 108 return failureCount;
rgrover1 0:0b799af9d58e 109 }
rgrover1 0:0b799af9d58e 110
rgrover1 0:0b799af9d58e 111 bool CommandLineTestRunner::parseArguments(TestPlugin* plugin)
rgrover1 0:0b799af9d58e 112 {
rgrover1 0:0b799af9d58e 113 if (arguments_->parse(plugin)) {
rgrover1 0:0b799af9d58e 114 if (arguments_->isJUnitOutput()) {
rgrover1 0:0b799af9d58e 115 output_ = jUnitOutput_ = new JUnitTestOutput;
rgrover1 0:0b799af9d58e 116 }
rgrover1 0:0b799af9d58e 117 return true;
rgrover1 0:0b799af9d58e 118 }
rgrover1 0:0b799af9d58e 119 else {
rgrover1 0:0b799af9d58e 120 output_->print(arguments_->usage());
rgrover1 0:0b799af9d58e 121 return false;
rgrover1 0:0b799af9d58e 122 }
rgrover1 0:0b799af9d58e 123 }
rgrover1 0:0b799af9d58e 124
rgrover1 0:0b799af9d58e 125 bool CommandLineTestRunner::isVerbose()
rgrover1 0:0b799af9d58e 126 {
rgrover1 0:0b799af9d58e 127 return arguments_->isVerbose();
rgrover1 0:0b799af9d58e 128 }
rgrover1 0:0b799af9d58e 129
rgrover1 0:0b799af9d58e 130 int CommandLineTestRunner::getRepeatCount()
rgrover1 0:0b799af9d58e 131 {
rgrover1 0:0b799af9d58e 132 return arguments_->getRepeatCount();
rgrover1 0:0b799af9d58e 133 }
rgrover1 0:0b799af9d58e 134
rgrover1 0:0b799af9d58e 135 TestFilter CommandLineTestRunner::getGroupFilter()
rgrover1 0:0b799af9d58e 136 {
rgrover1 0:0b799af9d58e 137 return arguments_->getGroupFilter();
rgrover1 0:0b799af9d58e 138 }
rgrover1 0:0b799af9d58e 139
rgrover1 0:0b799af9d58e 140 TestFilter CommandLineTestRunner::getNameFilter()
rgrover1 0:0b799af9d58e 141 {
rgrover1 0:0b799af9d58e 142 return arguments_->getNameFilter();
rgrover1 0:0b799af9d58e 143 }