#ifndef LEMON_HPP_ #define LEMON_HPP_ #include #include /** * Class: Lemon * * Provides simple unit testing with TAP compliant output */ class Lemon { public: /** * Function: Lemon */ Lemon(int numPlannedTests) : num_tests(0), test_number(0), num_skips(0), num_failures(0) { std::cout << "1.." << numPlannedTests << std::endl; } /** * Function: end * * Ends unit testing and displays the results */ void end() { if(num_skips > 0) { std::cout << "# Looks like you planned " << num_tests; std::cout << " but only ran " << (num_tests - num_skips) << ".\n"; } if(num_failures > 0) { std::cout << "# Looks like you failed " << num_failures; std::cout << " tests of " << num_tests << "." << std::endl; } else { std::cout << "# Looks like you passed all " << num_tests << " tests." << std::endl; } } /** * Function: diag * * Parameters: * str - The value to be written out to the console * * Displays the given string as extra information not part of the * unit test. */ void diag(std::string str) { std::cout << "# " << str << std::endl; } /** * Function: ok * * Parameters: * pass - A boolean expression that should evalute true * testName - The name of this particular test * * Checks whether the given boolean condition is true, if so the * test passes, otherwise it fails */ bool ok(bool pass, std::string testName) { num_tests++; if(testName[0] != '#') { testName = "- " + testName; } if(pass) { std::cout << "ok " << num_tests << " " << testName << std::endl; } else { num_failures++; std::cout << "not ok " << num_tests << " " << testName << std::endl; diag(" Failed test"); } return pass; } /** * Function: is * * Parameters: * thisOne - An object to be compared * thatOne - Another object to be compared * * Checks whether the two values are equal, comparison operator * as well as stream output operator must be defined for type. */ template bool is(const T& thisOne, const T& thatOne, std::string testName) { bool pass = (thisOne == thatOne); ok(pass, testName); if(!pass) { std::cout << "# got: '" << thisOne << "'" << std::endl; std::cout << "# expected: '" << thatOne << "'" << std::endl; } return pass; } /** * Function: isnt * * Checks that two values are not equal, results in a failure if they are */ template bool isnt(const T& thisOne, const T& thatOne, std::string testName) { bool pass = (thisOne != thatOne); ok(pass, testName); if(!pass) { std::cout << "# '" << thisOne << "'" << std::endl; std::cout << "# !=" << std::endl; std::cout << "# '" << thatOne << "'" << std::endl; } return pass; } /** * Function: pass * * Adds a passing test with the given name */ bool pass(std::string testName) { return ok(true, testName); } /** * Function: fail * * Adds a failing test with the given name */ bool fail(std::string testName) { return ok(false, testName); } /** * Function: skip * * Parameters: * message - A message indicating reason for skip * num - The num of sequential tests to skip (1 by default) * * Skips a test with the given name */ void skip(std::string message, int num = 0) { num_skips += num; for(int i = 0; i < num; i++) { pass("# SKIP " + message); } } /** * Function: todo * * Parameters: * message - A message indicating what the test is * * Creates a todo message for the given test so it will be completed * at a later time. */ void todo(std::string message) { num_skips++; pass("# TODO " + message); } private: /** * Variable: num_tests * The number of unit tests to be run */ int num_tests; /** * Variable: test_number * The number of the test currently running */ int test_number; /** * Variable: num_skips * The number of skipped tests */ int num_skips; /** * Variable: num_failures * The number of failed tests */ int num_failures; }; #endif /*LEMON_HPP_*/