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:
Rohit Grover
Date:
Thu Jun 19 08:24:31 2014 +0100
Revision:
2:82161d9e7b36
Parent:
1:4769360130ed
uncomment the code in CommandLineTestRunner::RunAllTests() having to do with MemoryLeakWarningPlugin

Bas Vodde, from the CppUTest development team has suggested an alternate way to run tests.

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 #ifndef D_UTestMacros_h
rgrover1 0:0b799af9d58e 29 #define D_UTestMacros_h
rgrover1 0:0b799af9d58e 30
rgrover1 0:0b799af9d58e 31 /*! \brief Define a group of tests
rgrover1 0:0b799af9d58e 32 *
rgrover1 0:0b799af9d58e 33 * All tests in a TEST_GROUP share the same setup()
rgrover1 0:0b799af9d58e 34 * and teardown(). setup() is run before the opening
rgrover1 0:0b799af9d58e 35 * curly brace of each TEST and teardown() is
rgrover1 0:0b799af9d58e 36 * called after the closing curly brace of TEST.
rgrover1 0:0b799af9d58e 37 *
rgrover1 0:0b799af9d58e 38 */
rgrover1 0:0b799af9d58e 39
rgrover1 0:0b799af9d58e 40
rgrover1 0:0b799af9d58e 41 #define TEST_GROUP_BASE(testGroup, baseclass) \
rgrover1 0:0b799af9d58e 42 extern int externTestGroup##testGroup; \
rgrover1 0:0b799af9d58e 43 int externTestGroup##testGroup = 0; \
rgrover1 0:0b799af9d58e 44 struct TEST_GROUP_##CppUTestGroup##testGroup : public baseclass
rgrover1 0:0b799af9d58e 45
rgrover1 0:0b799af9d58e 46 #define TEST_BASE(testBaseClass) \
rgrover1 0:0b799af9d58e 47 struct testBaseClass : public Utest
rgrover1 0:0b799af9d58e 48
rgrover1 0:0b799af9d58e 49 #define TEST_GROUP(testGroup) \
rgrover1 0:0b799af9d58e 50 TEST_GROUP_BASE(testGroup, Utest)
rgrover1 0:0b799af9d58e 51
rgrover1 0:0b799af9d58e 52 #define TEST_SETUP() \
rgrover1 0:0b799af9d58e 53 virtual void setup()
rgrover1 0:0b799af9d58e 54
rgrover1 0:0b799af9d58e 55 #define TEST_TEARDOWN() \
rgrover1 0:0b799af9d58e 56 virtual void teardown()
rgrover1 0:0b799af9d58e 57
rgrover1 0:0b799af9d58e 58 #define TEST(testGroup, testName) \
rgrover1 0:0b799af9d58e 59 /* External declarations for strict compilers */ \
rgrover1 0:0b799af9d58e 60 class TEST_##testGroup##_##testName##_TestShell; \
rgrover1 0:0b799af9d58e 61 extern TEST_##testGroup##_##testName##_TestShell TEST_##testGroup##_##testName##_TestShell_instance; \
rgrover1 0:0b799af9d58e 62 \
rgrover1 0:0b799af9d58e 63 class TEST_##testGroup##_##testName##_Test : public TEST_GROUP_##CppUTestGroup##testGroup \
rgrover1 0:0b799af9d58e 64 { public: TEST_##testGroup##_##testName##_Test () : TEST_GROUP_##CppUTestGroup##testGroup () {} \
rgrover1 0:0b799af9d58e 65 void testBody(); }; \
rgrover1 0:0b799af9d58e 66 class TEST_##testGroup##_##testName##_TestShell : public UtestShell { \
rgrover1 0:0b799af9d58e 67 virtual Utest* createTest() _override { return new TEST_##testGroup##_##testName##_Test; } \
rgrover1 0:0b799af9d58e 68 } TEST_##testGroup##_##testName##_TestShell_instance; \
rgrover1 0:0b799af9d58e 69 static TestInstaller TEST_##testGroup##_##testName##_Installer(TEST_##testGroup##_##testName##_TestShell_instance, #testGroup, #testName, __FILE__,__LINE__); \
rgrover1 0:0b799af9d58e 70 void TEST_##testGroup##_##testName##_Test::testBody()
rgrover1 0:0b799af9d58e 71
rgrover1 0:0b799af9d58e 72 #define IGNORE_TEST(testGroup, testName)\
rgrover1 0:0b799af9d58e 73 /* External declarations for strict compilers */ \
rgrover1 0:0b799af9d58e 74 class IGNORE##testGroup##_##testName##_TestShell; \
rgrover1 0:0b799af9d58e 75 extern IGNORE##testGroup##_##testName##_TestShell IGNORE##testGroup##_##testName##_TestShell_instance; \
rgrover1 0:0b799af9d58e 76 \
rgrover1 0:0b799af9d58e 77 class IGNORE##testGroup##_##testName##_Test : public TEST_GROUP_##CppUTestGroup##testGroup \
rgrover1 0:0b799af9d58e 78 { public: IGNORE##testGroup##_##testName##_Test () : TEST_GROUP_##CppUTestGroup##testGroup () {} \
rgrover1 0:0b799af9d58e 79 public: void testBodyThatNeverRuns (); }; \
rgrover1 0:0b799af9d58e 80 class IGNORE##testGroup##_##testName##_TestShell : public IgnoredUtestShell { \
rgrover1 0:0b799af9d58e 81 virtual Utest* createTest() _override { return new IGNORE##testGroup##_##testName##_Test; } \
rgrover1 0:0b799af9d58e 82 } IGNORE##testGroup##_##testName##_TestShell_instance; \
rgrover1 0:0b799af9d58e 83 static TestInstaller TEST_##testGroup##testName##_Installer(IGNORE##testGroup##_##testName##_TestShell_instance, #testGroup, #testName, __FILE__,__LINE__); \
rgrover1 0:0b799af9d58e 84 void IGNORE##testGroup##_##testName##_Test::testBodyThatNeverRuns ()
rgrover1 0:0b799af9d58e 85
rgrover1 0:0b799af9d58e 86 #define IMPORT_TEST_GROUP(testGroup) \
rgrover1 0:0b799af9d58e 87 extern int externTestGroup##testGroup;\
rgrover1 0:0b799af9d58e 88 extern int* p##testGroup; \
rgrover1 0:0b799af9d58e 89 int* p##testGroup = &externTestGroup##testGroup
rgrover1 0:0b799af9d58e 90
rgrover1 0:0b799af9d58e 91 // Different checking macros
rgrover1 0:0b799af9d58e 92
rgrover1 0:0b799af9d58e 93 #define CHECK(condition)\
rgrover1 0:0b799af9d58e 94 CHECK_LOCATION_TRUE(condition, "CHECK", #condition, __FILE__, __LINE__)
rgrover1 0:0b799af9d58e 95
rgrover1 0:0b799af9d58e 96 #define CHECK_TEXT(condition, text) \
rgrover1 0:0b799af9d58e 97 CHECK_LOCATION_TEXT(condition, "CHECK", #condition, text, __FILE__, __LINE__)
rgrover1 0:0b799af9d58e 98
rgrover1 0:0b799af9d58e 99 #define CHECK_TRUE(condition)\
rgrover1 0:0b799af9d58e 100 CHECK_LOCATION_TRUE(condition, "CHECK_TRUE", #condition, __FILE__, __LINE__)
rgrover1 0:0b799af9d58e 101
rgrover1 0:0b799af9d58e 102 #define CHECK_FALSE(condition)\
rgrover1 0:0b799af9d58e 103 CHECK_LOCATION_FALSE(condition, "CHECK_FALSE", #condition, __FILE__, __LINE__)
rgrover1 0:0b799af9d58e 104
rgrover1 0:0b799af9d58e 105 #define CHECK_LOCATION_TEXT(condition, checkString, conditionString, text, file, line) \
rgrover1 0:0b799af9d58e 106 { UtestShell::getCurrent()->assertTrueText((condition) != 0, checkString, conditionString, text, file, line); }
rgrover1 0:0b799af9d58e 107
rgrover1 0:0b799af9d58e 108 #define CHECK_LOCATION_TRUE(condition, checkString, conditionString, file, line)\
rgrover1 0:0b799af9d58e 109 { UtestShell::getCurrent()->assertTrue((condition) != 0, checkString, conditionString, file, line); }
rgrover1 0:0b799af9d58e 110
rgrover1 0:0b799af9d58e 111 #define CHECK_LOCATION_FALSE(condition, checkString, conditionString, file, line)\
rgrover1 0:0b799af9d58e 112 { UtestShell::getCurrent()->assertTrue((condition) == 0, checkString, conditionString, file, line); }
rgrover1 0:0b799af9d58e 113
rgrover1 0:0b799af9d58e 114 //This check needs the operator!=(), and a StringFrom(YourType) function
rgrover1 0:0b799af9d58e 115 #define CHECK_EQUAL(expected,actual)\
rgrover1 0:0b799af9d58e 116 CHECK_EQUAL_LOCATION(expected, actual, __FILE__, __LINE__)
rgrover1 0:0b799af9d58e 117
rgrover1 0:0b799af9d58e 118 #define CHECK_EQUAL_LOCATION(expected,actual, file, line)\
rgrover1 0:0b799af9d58e 119 { if ((expected) != (actual)) { \
rgrover1 0:0b799af9d58e 120 if ((actual) != (actual)) \
rgrover1 0:0b799af9d58e 121 UtestShell::getCurrent()->print("WARNING:\n\tThe \"Actual Parameter\" parameter is evaluated multiple times resulting in different values.\n\tThus the value in the error message is probably incorrect.", file, line); \
rgrover1 0:0b799af9d58e 122 if ((expected) != (expected)) \
rgrover1 0:0b799af9d58e 123 UtestShell::getCurrent()->print("WARNING:\n\tThe \"Expected Parameter\" parameter is evaluated multiple times resulting in different values.\n\tThus the value in the error message is probably incorrect.", file, line); \
rgrover1 0:0b799af9d58e 124 UtestShell::getCurrent()->assertEquals(true, StringFrom(expected).asCharString(), StringFrom(actual).asCharString(), file, line); \
Rohit Grover 1:4769360130ed 125 } \
Rohit Grover 1:4769360130ed 126 else \
Rohit Grover 1:4769360130ed 127 { \
Rohit Grover 1:4769360130ed 128 UtestShell::getCurrent()->assertLongsEqual((long)0, (long)0, file, line); \
rgrover1 0:0b799af9d58e 129 } }
rgrover1 0:0b799af9d58e 130
rgrover1 0:0b799af9d58e 131 //This check checks for char* string equality using strcmp.
rgrover1 0:0b799af9d58e 132 //This makes up for the fact that CHECK_EQUAL only compares the pointers to char*'s
rgrover1 0:0b799af9d58e 133 #define STRCMP_EQUAL(expected,actual)\
rgrover1 0:0b799af9d58e 134 STRCMP_EQUAL_LOCATION(expected, actual, __FILE__, __LINE__)
rgrover1 0:0b799af9d58e 135
rgrover1 0:0b799af9d58e 136 #define STRCMP_EQUAL_LOCATION(expected,actual, file, line)\
rgrover1 0:0b799af9d58e 137 { UtestShell::getCurrent()->assertCstrEqual(expected, actual, file, line); }
rgrover1 0:0b799af9d58e 138
rgrover1 0:0b799af9d58e 139 #define STRCMP_NOCASE_EQUAL(expected,actual)\
rgrover1 0:0b799af9d58e 140 STRCMP_NOCASE_EQUAL_LOCATION(expected, actual, __FILE__, __LINE__)
rgrover1 0:0b799af9d58e 141
rgrover1 0:0b799af9d58e 142 #define STRCMP_NOCASE_EQUAL_LOCATION(expected,actual, file, line)\
rgrover1 0:0b799af9d58e 143 { UtestShell::getCurrent()->assertCstrNoCaseEqual(expected, actual, file, line); }
rgrover1 0:0b799af9d58e 144
rgrover1 0:0b799af9d58e 145 #define STRCMP_CONTAINS(expected,actual)\
rgrover1 0:0b799af9d58e 146 STRCMP_CONTAINS_LOCATION(expected, actual, __FILE__, __LINE__)
rgrover1 0:0b799af9d58e 147
rgrover1 0:0b799af9d58e 148 #define STRCMP_CONTAINS_LOCATION(expected,actual, file, line)\
rgrover1 0:0b799af9d58e 149 { UtestShell::getCurrent()->assertCstrContains(expected, actual, file, line); }
rgrover1 0:0b799af9d58e 150
rgrover1 0:0b799af9d58e 151 #define STRCMP_NOCASE_CONTAINS(expected,actual)\
rgrover1 0:0b799af9d58e 152 STRCMP_NOCASE_CONTAINS_LOCATION(expected, actual, __FILE__, __LINE__)
rgrover1 0:0b799af9d58e 153
rgrover1 0:0b799af9d58e 154 #define STRCMP_NOCASE_CONTAINS_LOCATION(expected,actual, file, line)\
rgrover1 0:0b799af9d58e 155 { UtestShell::getCurrent()->assertCstrNoCaseContains(expected, actual, file, line); }
rgrover1 0:0b799af9d58e 156
rgrover1 0:0b799af9d58e 157 //Check two long integers for equality
rgrover1 0:0b799af9d58e 158 #define LONGS_EQUAL(expected,actual)\
rgrover1 0:0b799af9d58e 159 LONGS_EQUAL_LOCATION(expected,actual,__FILE__, __LINE__)
rgrover1 0:0b799af9d58e 160
Rohit Grover 1:4769360130ed 161 #define UNSIGNED_LONGS_EQUAL(expected,actual)\
Rohit Grover 1:4769360130ed 162 UNSIGNED_LONGS_EQUAL_LOCATION(expected,actual,__FILE__, __LINE__)
Rohit Grover 1:4769360130ed 163
rgrover1 0:0b799af9d58e 164 #define LONGS_EQUAL_LOCATION(expected,actual,file,line)\
rgrover1 0:0b799af9d58e 165 { UtestShell::getCurrent()->assertLongsEqual((long)expected, (long)actual, file, line); }
rgrover1 0:0b799af9d58e 166
Rohit Grover 1:4769360130ed 167 #define UNSIGNED_LONGS_EQUAL_LOCATION(expected,actual,file,line)\
Rohit Grover 1:4769360130ed 168 { UtestShell::getCurrent()->assertUnsignedLongsEqual((unsigned long)expected, (unsigned long)actual, file, line); }
Rohit Grover 1:4769360130ed 169
rgrover1 0:0b799af9d58e 170 #define BYTES_EQUAL(expected, actual)\
rgrover1 0:0b799af9d58e 171 LONGS_EQUAL((expected) & 0xff,(actual) & 0xff)
rgrover1 0:0b799af9d58e 172
rgrover1 0:0b799af9d58e 173 #define POINTERS_EQUAL(expected, actual)\
rgrover1 0:0b799af9d58e 174 POINTERS_EQUAL_LOCATION((expected),(actual), __FILE__, __LINE__)
rgrover1 0:0b799af9d58e 175
rgrover1 0:0b799af9d58e 176 #define POINTERS_EQUAL_LOCATION(expected,actual,file,line)\
rgrover1 0:0b799af9d58e 177 { UtestShell::getCurrent()->assertPointersEqual((void *)expected, (void *)actual, file, line); }
rgrover1 0:0b799af9d58e 178
rgrover1 0:0b799af9d58e 179 //Check two doubles for equality within a tolerance threshold
rgrover1 0:0b799af9d58e 180 #define DOUBLES_EQUAL(expected,actual,threshold)\
rgrover1 0:0b799af9d58e 181 DOUBLES_EQUAL_LOCATION(expected,actual,threshold,__FILE__,__LINE__)
rgrover1 0:0b799af9d58e 182
rgrover1 0:0b799af9d58e 183 #define DOUBLES_EQUAL_LOCATION(expected,actual,threshold,file,line)\
rgrover1 0:0b799af9d58e 184 { UtestShell::getCurrent()->assertDoublesEqual(expected, actual, threshold, file, line); }
rgrover1 0:0b799af9d58e 185
rgrover1 0:0b799af9d58e 186 //Fail if you get to this macro
rgrover1 0:0b799af9d58e 187 //The macro FAIL may already be taken, so allow FAIL_TEST too
rgrover1 0:0b799af9d58e 188 #ifndef FAIL
rgrover1 0:0b799af9d58e 189 #define FAIL(text)\
rgrover1 0:0b799af9d58e 190 FAIL_LOCATION(text, __FILE__,__LINE__)
rgrover1 0:0b799af9d58e 191
rgrover1 0:0b799af9d58e 192 #define FAIL_LOCATION(text, file, line)\
rgrover1 0:0b799af9d58e 193 { UtestShell::getCurrent()->fail(text, file, line); }
rgrover1 0:0b799af9d58e 194 #endif
rgrover1 0:0b799af9d58e 195
rgrover1 0:0b799af9d58e 196 #define FAIL_TEST(text)\
rgrover1 0:0b799af9d58e 197 FAIL_TEST_LOCATION(text, __FILE__,__LINE__)
rgrover1 0:0b799af9d58e 198
rgrover1 0:0b799af9d58e 199 #define FAIL_TEST_LOCATION(text, file,line)\
rgrover1 0:0b799af9d58e 200 { UtestShell::getCurrent()->fail(text, file, line); }
rgrover1 0:0b799af9d58e 201
rgrover1 0:0b799af9d58e 202 #define UT_PRINT_LOCATION(text, file, line) \
rgrover1 0:0b799af9d58e 203 { UtestShell::getCurrent()->print(text, file, line); }
rgrover1 0:0b799af9d58e 204
rgrover1 0:0b799af9d58e 205 #define UT_PRINT(text) \
rgrover1 0:0b799af9d58e 206 UT_PRINT_LOCATION(text, __FILE__, __LINE__)
rgrover1 0:0b799af9d58e 207
rgrover1 0:0b799af9d58e 208 #if CPPUTEST_USE_STD_CPP_LIB
rgrover1 0:0b799af9d58e 209 #define CHECK_THROWS(expected, expression) \
rgrover1 0:0b799af9d58e 210 { \
rgrover1 0:0b799af9d58e 211 SimpleString msg("expected to throw "#expected "\nbut threw nothing"); \
rgrover1 0:0b799af9d58e 212 bool caught_expected = false; \
rgrover1 0:0b799af9d58e 213 try { \
rgrover1 0:0b799af9d58e 214 (expression); \
rgrover1 0:0b799af9d58e 215 } catch(const expected &) { \
rgrover1 0:0b799af9d58e 216 caught_expected = true; \
rgrover1 0:0b799af9d58e 217 } catch(...) { \
rgrover1 0:0b799af9d58e 218 msg = "expected to throw " #expected "\nbut threw a different type"; \
rgrover1 0:0b799af9d58e 219 } \
rgrover1 0:0b799af9d58e 220 if (!caught_expected) { \
rgrover1 0:0b799af9d58e 221 UtestShell::getCurrent()->fail(msg.asCharString(), __FILE__, __LINE__); \
rgrover1 0:0b799af9d58e 222 } \
rgrover1 0:0b799af9d58e 223 }
rgrover1 0:0b799af9d58e 224 #endif /* CPPUTEST_USE_STD_CPP_LIB */
rgrover1 0:0b799af9d58e 225
rgrover1 0:0b799af9d58e 226 #define UT_CRASH() { UtestShell::crash(); }
rgrover1 0:0b799af9d58e 227 #define RUN_ALL_TESTS(ac, av) CommandLineTestRunner::RunAllTests(ac, av)
rgrover1 0:0b799af9d58e 228
rgrover1 0:0b799af9d58e 229 #endif /*D_UTestMacros_h*/