Unit Testing framework based on http://cpputest.github.io/

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/TestOutput.h"
rgrover1 0:0b799af9d58e 30 #include "CppUTest/PlatformSpecificFunctions.h"
rgrover1 0:0b799af9d58e 31
rgrover1 0:0b799af9d58e 32 TestOutput::WorkingEnvironment TestOutput::workingEnvironment_ = TestOutput::detectEnvironment;
rgrover1 0:0b799af9d58e 33
rgrover1 0:0b799af9d58e 34 void TestOutput::setWorkingEnvironment(TestOutput::WorkingEnvironment workEnvironment)
rgrover1 0:0b799af9d58e 35 {
rgrover1 0:0b799af9d58e 36 workingEnvironment_ = workEnvironment;
rgrover1 0:0b799af9d58e 37 }
rgrover1 0:0b799af9d58e 38
rgrover1 0:0b799af9d58e 39 TestOutput::WorkingEnvironment TestOutput::getWorkingEnvironment()
rgrover1 0:0b799af9d58e 40 {
rgrover1 0:0b799af9d58e 41 if (workingEnvironment_ == TestOutput::detectEnvironment)
rgrover1 0:0b799af9d58e 42 return PlatformSpecificGetWorkingEnvironment();
rgrover1 0:0b799af9d58e 43 return workingEnvironment_;
rgrover1 0:0b799af9d58e 44 }
rgrover1 0:0b799af9d58e 45
rgrover1 0:0b799af9d58e 46
rgrover1 0:0b799af9d58e 47 TestOutput::TestOutput() :
rgrover1 0:0b799af9d58e 48 dotCount_(0), verbose_(false), progressIndication_(".")
rgrover1 0:0b799af9d58e 49 {
rgrover1 0:0b799af9d58e 50 }
rgrover1 0:0b799af9d58e 51
rgrover1 0:0b799af9d58e 52 TestOutput::~TestOutput()
rgrover1 0:0b799af9d58e 53 {
rgrover1 0:0b799af9d58e 54 }
rgrover1 0:0b799af9d58e 55
rgrover1 0:0b799af9d58e 56 void TestOutput::verbose()
rgrover1 0:0b799af9d58e 57 {
rgrover1 0:0b799af9d58e 58 verbose_ = true;
rgrover1 0:0b799af9d58e 59 }
rgrover1 0:0b799af9d58e 60
rgrover1 0:0b799af9d58e 61 void TestOutput::print(const char* str)
rgrover1 0:0b799af9d58e 62 {
rgrover1 0:0b799af9d58e 63 printBuffer(str);
rgrover1 0:0b799af9d58e 64 }
rgrover1 0:0b799af9d58e 65
rgrover1 0:0b799af9d58e 66 void TestOutput::print(long n)
rgrover1 0:0b799af9d58e 67 {
rgrover1 0:0b799af9d58e 68 print(StringFrom(n).asCharString());
rgrover1 0:0b799af9d58e 69 }
rgrover1 0:0b799af9d58e 70
rgrover1 0:0b799af9d58e 71 void TestOutput::printDouble(double d)
rgrover1 0:0b799af9d58e 72 {
rgrover1 0:0b799af9d58e 73 print(StringFrom(d).asCharString());
rgrover1 0:0b799af9d58e 74 }
rgrover1 0:0b799af9d58e 75
rgrover1 0:0b799af9d58e 76 void TestOutput::printHex(long n)
rgrover1 0:0b799af9d58e 77 {
rgrover1 0:0b799af9d58e 78 print(HexStringFrom(n).asCharString());
rgrover1 0:0b799af9d58e 79 }
rgrover1 0:0b799af9d58e 80
rgrover1 0:0b799af9d58e 81 TestOutput& operator<<(TestOutput& p, const char* s)
rgrover1 0:0b799af9d58e 82 {
rgrover1 0:0b799af9d58e 83 p.print(s);
rgrover1 0:0b799af9d58e 84 return p;
rgrover1 0:0b799af9d58e 85 }
rgrover1 0:0b799af9d58e 86
rgrover1 0:0b799af9d58e 87 TestOutput& operator<<(TestOutput& p, long int i)
rgrover1 0:0b799af9d58e 88 {
rgrover1 0:0b799af9d58e 89 p.print(i);
rgrover1 0:0b799af9d58e 90 return p;
rgrover1 0:0b799af9d58e 91 }
rgrover1 0:0b799af9d58e 92
rgrover1 0:0b799af9d58e 93 void TestOutput::printCurrentTestStarted(const UtestShell& test)
rgrover1 0:0b799af9d58e 94 {
rgrover1 0:0b799af9d58e 95 if (verbose_) print(test.getFormattedName().asCharString());
rgrover1 0:0b799af9d58e 96 }
rgrover1 0:0b799af9d58e 97
rgrover1 0:0b799af9d58e 98 void TestOutput::printCurrentTestEnded(const TestResult& res)
rgrover1 0:0b799af9d58e 99 {
rgrover1 0:0b799af9d58e 100 if (verbose_) {
rgrover1 0:0b799af9d58e 101 print(" - ");
rgrover1 0:0b799af9d58e 102 print(res.getCurrentTestTotalExecutionTime());
rgrover1 0:0b799af9d58e 103 print(" ms\n");
rgrover1 0:0b799af9d58e 104 }
rgrover1 0:0b799af9d58e 105 else {
rgrover1 0:0b799af9d58e 106 printProgressIndicator();
rgrover1 0:0b799af9d58e 107 }
rgrover1 0:0b799af9d58e 108 }
rgrover1 0:0b799af9d58e 109
rgrover1 0:0b799af9d58e 110 void TestOutput::printProgressIndicator()
rgrover1 0:0b799af9d58e 111 {
rgrover1 0:0b799af9d58e 112 print(progressIndication_);
rgrover1 0:0b799af9d58e 113 if (++dotCount_ % 50 == 0) print("\n");
rgrover1 0:0b799af9d58e 114 }
rgrover1 0:0b799af9d58e 115
rgrover1 0:0b799af9d58e 116 void TestOutput::setProgressIndicator(const char* indicator)
rgrover1 0:0b799af9d58e 117 {
rgrover1 0:0b799af9d58e 118 progressIndication_ = indicator;
rgrover1 0:0b799af9d58e 119 }
rgrover1 0:0b799af9d58e 120
rgrover1 0:0b799af9d58e 121 void TestOutput::printTestsStarted()
rgrover1 0:0b799af9d58e 122 {
rgrover1 0:0b799af9d58e 123 }
rgrover1 0:0b799af9d58e 124
rgrover1 0:0b799af9d58e 125 void TestOutput::printCurrentGroupStarted(const UtestShell& /*test*/)
rgrover1 0:0b799af9d58e 126 {
rgrover1 0:0b799af9d58e 127 }
rgrover1 0:0b799af9d58e 128
rgrover1 0:0b799af9d58e 129 void TestOutput::printCurrentGroupEnded(const TestResult& /*res*/)
rgrover1 0:0b799af9d58e 130 {
rgrover1 0:0b799af9d58e 131 }
rgrover1 0:0b799af9d58e 132
rgrover1 0:0b799af9d58e 133 void TestOutput::flush()
rgrover1 0:0b799af9d58e 134 {
rgrover1 0:0b799af9d58e 135 }
rgrover1 0:0b799af9d58e 136
rgrover1 0:0b799af9d58e 137 void TestOutput::printTestsEnded(const TestResult& result)
rgrover1 0:0b799af9d58e 138 {
rgrover1 0:0b799af9d58e 139 if (result.getFailureCount() > 0) {
rgrover1 0:0b799af9d58e 140 print("\nErrors (");
rgrover1 0:0b799af9d58e 141 print(result.getFailureCount());
rgrover1 0:0b799af9d58e 142 print(" failures, ");
rgrover1 0:0b799af9d58e 143 }
rgrover1 0:0b799af9d58e 144 else {
rgrover1 0:0b799af9d58e 145 print("\nOK (");
rgrover1 0:0b799af9d58e 146 }
rgrover1 0:0b799af9d58e 147 print(result.getTestCount());
rgrover1 0:0b799af9d58e 148 print(" tests, ");
rgrover1 0:0b799af9d58e 149 print(result.getRunCount());
rgrover1 0:0b799af9d58e 150 print(" ran, ");
rgrover1 0:0b799af9d58e 151 print(result.getCheckCount());
rgrover1 0:0b799af9d58e 152 print(" checks, ");
rgrover1 0:0b799af9d58e 153 print(result.getIgnoredCount());
rgrover1 0:0b799af9d58e 154 print(" ignored, ");
rgrover1 0:0b799af9d58e 155 print(result.getFilteredOutCount());
rgrover1 0:0b799af9d58e 156 print(" filtered out, ");
rgrover1 0:0b799af9d58e 157 print(result.getTotalExecutionTime());
rgrover1 0:0b799af9d58e 158 print(" ms)\n\n");
rgrover1 0:0b799af9d58e 159 }
rgrover1 0:0b799af9d58e 160
rgrover1 0:0b799af9d58e 161 void TestOutput::printTestRun(int number, int total)
rgrover1 0:0b799af9d58e 162 {
rgrover1 0:0b799af9d58e 163 if (total > 1) {
rgrover1 0:0b799af9d58e 164 print("Test run ");
rgrover1 0:0b799af9d58e 165 print(number);
rgrover1 0:0b799af9d58e 166 print(" of ");
rgrover1 0:0b799af9d58e 167 print(total);
rgrover1 0:0b799af9d58e 168 print("\n");
rgrover1 0:0b799af9d58e 169 }
rgrover1 0:0b799af9d58e 170 }
rgrover1 0:0b799af9d58e 171
rgrover1 0:0b799af9d58e 172 void TestOutput::print(const TestFailure& failure)
rgrover1 0:0b799af9d58e 173 {
rgrover1 0:0b799af9d58e 174 if (failure.isOutsideTestFile() || failure.isInHelperFunction())
rgrover1 0:0b799af9d58e 175 printFileAndLineForTestAndFailure(failure);
rgrover1 0:0b799af9d58e 176 else
rgrover1 0:0b799af9d58e 177 printFileAndLineForFailure(failure);
rgrover1 0:0b799af9d58e 178
rgrover1 0:0b799af9d58e 179 printFailureMessage(failure.getMessage());
rgrover1 0:0b799af9d58e 180 }
rgrover1 0:0b799af9d58e 181
rgrover1 0:0b799af9d58e 182 void TestOutput::printFileAndLineForTestAndFailure(const TestFailure& failure)
rgrover1 0:0b799af9d58e 183 {
rgrover1 0:0b799af9d58e 184 printErrorInFileOnLineFormattedForWorkingEnvironment(failure.getTestFileName(), failure.getTestLineNumber());
rgrover1 0:0b799af9d58e 185 printFailureInTest(failure.getTestName());
rgrover1 0:0b799af9d58e 186 printErrorInFileOnLineFormattedForWorkingEnvironment(failure.getFileName(), failure.getFailureLineNumber());
rgrover1 0:0b799af9d58e 187 }
rgrover1 0:0b799af9d58e 188
rgrover1 0:0b799af9d58e 189 void TestOutput::printFileAndLineForFailure(const TestFailure& failure)
rgrover1 0:0b799af9d58e 190 {
rgrover1 0:0b799af9d58e 191 printErrorInFileOnLineFormattedForWorkingEnvironment(failure.getFileName(), failure.getFailureLineNumber());
rgrover1 0:0b799af9d58e 192 printFailureInTest(failure.getTestName());
rgrover1 0:0b799af9d58e 193 }
rgrover1 0:0b799af9d58e 194
rgrover1 0:0b799af9d58e 195 void TestOutput::printFailureInTest(SimpleString testName)
rgrover1 0:0b799af9d58e 196 {
rgrover1 0:0b799af9d58e 197 print(" Failure in ");
rgrover1 0:0b799af9d58e 198 print(testName.asCharString());
rgrover1 0:0b799af9d58e 199 }
rgrover1 0:0b799af9d58e 200
rgrover1 0:0b799af9d58e 201 void TestOutput::printFailureMessage(SimpleString reason)
rgrover1 0:0b799af9d58e 202 {
rgrover1 0:0b799af9d58e 203 print("\n");
rgrover1 0:0b799af9d58e 204 print("\t");
rgrover1 0:0b799af9d58e 205 print(reason.asCharString());
rgrover1 0:0b799af9d58e 206 print("\n\n");
rgrover1 0:0b799af9d58e 207 }
rgrover1 0:0b799af9d58e 208
rgrover1 0:0b799af9d58e 209 void TestOutput::printErrorInFileOnLineFormattedForWorkingEnvironment(SimpleString file, int lineNumber)
rgrover1 0:0b799af9d58e 210 {
rgrover1 0:0b799af9d58e 211 if (TestOutput::getWorkingEnvironment() == TestOutput::vistualStudio)
rgrover1 0:0b799af9d58e 212 printVistualStudioErrorInFileOnLine(file, lineNumber);
rgrover1 0:0b799af9d58e 213 else
rgrover1 0:0b799af9d58e 214 printEclipseErrorInFileOnLine(file, lineNumber);
rgrover1 0:0b799af9d58e 215 }
rgrover1 0:0b799af9d58e 216
rgrover1 0:0b799af9d58e 217 void TestOutput::printEclipseErrorInFileOnLine(SimpleString file, int lineNumber)
rgrover1 0:0b799af9d58e 218 {
rgrover1 0:0b799af9d58e 219 print("\n");
rgrover1 0:0b799af9d58e 220 print(file.asCharString());
rgrover1 0:0b799af9d58e 221 print(":");
rgrover1 0:0b799af9d58e 222 print(lineNumber);
rgrover1 0:0b799af9d58e 223 print(":");
rgrover1 0:0b799af9d58e 224 print(" error:");
rgrover1 0:0b799af9d58e 225 }
rgrover1 0:0b799af9d58e 226
rgrover1 0:0b799af9d58e 227 void TestOutput::printVistualStudioErrorInFileOnLine(SimpleString file, int lineNumber)
rgrover1 0:0b799af9d58e 228 {
rgrover1 0:0b799af9d58e 229 print("\n");
rgrover1 0:0b799af9d58e 230 print(file.asCharString());
rgrover1 0:0b799af9d58e 231 print("(");
rgrover1 0:0b799af9d58e 232 print(lineNumber);
rgrover1 0:0b799af9d58e 233 print("):");
rgrover1 0:0b799af9d58e 234 print(" error:");
rgrover1 0:0b799af9d58e 235 }
rgrover1 0:0b799af9d58e 236
rgrover1 0:0b799af9d58e 237 void ConsoleTestOutput::printBuffer(const char* s)
rgrover1 0:0b799af9d58e 238 {
rgrover1 0:0b799af9d58e 239 while (*s) {
rgrover1 0:0b799af9d58e 240 PlatformSpecificPutchar(*s);
rgrover1 0:0b799af9d58e 241 s++;
rgrover1 0:0b799af9d58e 242 }
rgrover1 0:0b799af9d58e 243 flush();
rgrover1 0:0b799af9d58e 244 }
rgrover1 0:0b799af9d58e 245
rgrover1 0:0b799af9d58e 246 void ConsoleTestOutput::flush()
rgrover1 0:0b799af9d58e 247 {
rgrover1 0:0b799af9d58e 248 PlatformSpecificFlush();
rgrover1 0:0b799af9d58e 249 }
rgrover1 0:0b799af9d58e 250
rgrover1 0:0b799af9d58e 251 StringBufferTestOutput::~StringBufferTestOutput()
rgrover1 0:0b799af9d58e 252 {
rgrover1 0:0b799af9d58e 253 }