Sample:
#include "UnitTest.h" void Test1() { Assert(1 > 2); } int main() { using namespace UnitTest; ConsoleReport consoleReport; RunTest(&Test1, consoleReport, L"Test1"); }
Source Code: UnitTest.h
#pragma once #include <string> #include <chrono> #include <iostream> namespace UnitTest { enum class TestResult { Passed, Failed, Canceled, }; inline const wchar_t* GetTestResultMsg(TestResult r) { switch (r) { case TestResult::Passed: return L"Passed"; case TestResult::Failed: return L"Failed"; case TestResult::Canceled: return L"Canceled"; default: break; } return 0; } class TestResultException { public: int m_SourceLine; std::wstring m_FileName; std::wstring m_Message; TestResult m_TestResult; TestResultException(TestResult r, const wchar_t* message, const wchar_t* f, int l) { m_Message = message; m_FileName = f; m_SourceLine = l; m_TestResult = r; } }; // //Assertions to be used inside the test functions // inline void Cancel(const wchar_t* message = L"", const wchar_t* file = L"", int line = 0) { throw TestResultException(TestResult::Canceled, message, file, line); } inline void Assert(bool condition, const wchar_t* message = L"assertion failed", const wchar_t* file = L"", int line = 0) { if (!condition) throw TestResultException(TestResult::Failed, message, file, line); } inline void IsTrue(bool condition, const wchar_t* message = L"assertion IsTrue failed", const wchar_t* file = L"", int line = 0) { Assert(condition, message, file, line); } inline void Fail(const wchar_t* message = L"Test failed", const wchar_t* file = L"", int line = 0) { Assert(false, message, file, line); } inline void IsFalse(bool condition, const wchar_t* message = L"assertion IsFalse failed", const wchar_t* file = L"", int line = 0) { Assert(!condition, message, file, line); } template<class T1, class T2> inline void AreEqual(const T1& v1, const T2& v2, const wchar_t* message = L"assertion AreEqual failed", const wchar_t* file = L"", int line = 0) { Assert(v1 == v2, message, file, line); } template<class T1, class T2> inline void AreNotEqual(const T1& v1, const T2& v2, const wchar_t* message = L"assertion AreNotEqual failed", const wchar_t* file = L"", int line = 0) { Assert(v1 != v2, message, file, line); } struct Report { // I will count this for you int m_PassedCount; int m_FailedCount; int m_CanceledCount; Report() { m_PassedCount = 0; m_FailedCount = 0; m_CanceledCount = 0; } virtual void ReportResultCore(const wchar_t* testName, std::chrono::high_resolution_clock::duration&, UnitTest::TestResult result, const wchar_t* pszMessage) = 0; void ReportResult(const wchar_t* testName, std::chrono::high_resolution_clock::duration& duration, UnitTest::TestResult result, const wchar_t* pszMessage) { switch (result) { case TestResult::Passed: m_PassedCount++; break; case TestResult::Failed: m_FailedCount++; break; case TestResult::Canceled: m_CanceledCount++; break; } ReportResultCore(testName, duration, result, pszMessage); } }; struct ConsoleReport : public Report { virtual void ReportResultCore(const wchar_t* testName, std::chrono::high_resolution_clock::duration& duration, TestResult result, const wchar_t* pszMessage) override { std::wcout << testName << L" "; std::wcout << pszMessage; typedef std::chrono::duration<int, std::ratio<1, 1000>> MS; int ms = std::chrono::duration_cast<MS>(duration).count(); std::wcout << ms << L" ms"; } }; void RunTest(void (*PF)(void), Report& report, const wchar_t* psz) { auto startTime = std::chrono::high_resolution_clock::now(); try { (*PF)(); auto duration = std::chrono::high_resolution_clock::now() - startTime; report.ReportResult(psz, duration, TestResult::Passed, L"succeeded"); } catch (const std::exception&) { auto duration = std::chrono::high_resolution_clock::now() - startTime; report.ReportResult(psz, duration, TestResult::Failed, L"failed"); } catch (const TestResultException& e) { auto duration = std::chrono::high_resolution_clock::now() - startTime; report.ReportResult(psz, duration, TestResult::Failed, e.m_Message.c_str()); } catch (...) { auto duration = std::chrono::high_resolution_clock::now() - startTime; report.ReportResult(psz, duration, TestResult::Failed, L"failed"); } } } //namespace UnitTest #define WIDEN2(x) L ## x #define WIDEN(x) WIDEN2(x) #define __WFILE__ WIDEN(__FILE__) // Auto generate comments, file and line numbers #define Assert(x) UnitTest::Assert((x), L#x, __WFILE__, __LINE__) #define IsTrue(x) UnitTest::IsTrue((x), L#x, __WFILE__, __LINE__) #define IsFalse(x) UnitTest::IsFalse((x), L#x, __WFILE__, __LINE__) #define AreEqual(x, y) UnitTest::AreEqual((x), (y), L"AreEqual " L#x L", " L#y, __WFILE__, __LINE__) #define AreNotEqual(x, y) UnitTest::AreNotEqual((x), (y), L"AreNotEqual " L#x L", " L#y, __WFILE__, __LINE__) #define Fail() UnitTest::Fail(L"Test Failed", __WFILE__, __LINE__)