C++單元測試如何實施?
library: Gac Library -- C++ Utilities for GPU Accelerated GUI and Script
cases: https://gac.codeplex.com/SourceControl/latest#Common/UnitTest/UnitTest/TestList.cpp
學長給的手寫的框架
可以當作參考PS: 我注釋掉了顏色信息 貌似windows失敗了//*****test.h******
#ifndef TEST_HPP_INCLUDED
#define TEST_HPP_INCLUDED#include &
#include &
#define TEST_DEBUG
#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1#define LOVERFLOW -2typedef int Status;//#define RESET " 33[0m"
//#define BLACK " 33[30m" /* Black *///#define RED " 33[31m" /* Red *///#define GREEN " 33[32m" /* Green *///#define YELLOW " 33[33m" /* Yellow *///#define MAGENTA " 33[35m" /* Magenta *///#define CYAN " 33[36m" /* Cyan *///#define WHITE " 33[37m" /* White *///#define BOLDBLACK " 33[1m 33[30m" /* Bold Black *///#define BOLDRED " 33[1m 33[31m" /* Bold Red *///#define BOLDGREEN " 33[1m 33[32m" /* Bold Green */
//#define BOLDYELLOW " 33[1m 33[33m" /* Bold Yellow *///#define BOLDBLUE " 33[1m 33[34m" /* Bold Blue *///#define BOLDMAGENTA " 33[1m 33[35m" /* Bold Magenta *///#define BOLDCYAN " 33[1m 33[36m" /* Bold Cyan *///#define BOLDWHITE " 33[1m 33[37m" /* Bold White */#define TESTCASE_NAME(testcase_name)
testcase_name##_TEST#define TEST(testcase_name)
class TESTCASE_NAME(testcase_name) : public TestCase
{ public: TESTCASE_NAME(testcase_name)(const char* case_name) : TestCase(case_name){}; virtual void Run(); private: static TestCase* const testcase_; }; TestCase* const TESTCASE_NAME(testcase_name)::testcase_ = UnitTest::GetInstance()-&>RegisterTestCase(
new TESTCASE_NAME(testcase_name)(#testcase_name)); void TESTCASE_NAME(testcase_name)::Run()#define RUN_ALL_TESTS()
UnitTest::GetInstance()-&>Run();//單元測試的主體
class TestCase{public:TestCase(const char *case_name) : testcase_name(case_name) {};
virtual void Run() = 0; bool test_resu< const char *testcase_name;};class UnitTest
{public: static UnitTest* GetInstance(); TestCase* RegisterTestCase(TestCase *testcase);bool Run();
TestCase *current_test_case;
bool test_resu< int passed_num; int failed_num; std::vector&UnitTest* UnitTest::GetInstance()
{ static UnitTest instance;return instance;
}TestCase* UnitTest::RegisterTestCase(TestCase *testcase)
{ testcases_.push_back(testcase); return testcase;}bool UnitTest::Run()
{ test_result = true;std::cout /*&<&< YELLOW*/ &<&< "[ Start Run ]" &<&< /*RESET &<&<*/ "Have " &<&< testcases_.size() &<&< " Unit Testing" &<&< std::endl;
std::cout &<&< std::endl; for (std::vector&
std::cout &<&< /*GREEN &<&<*/ "[ Run ]" &<&< /*RESET &<&<*/ test_case-&>testcase_name &<&< std::endl;
test_case-&>Run();if (test_case-&>test_result)
std::cout &<&< /*GREEN &<&<*/ "[ Pass ]" &<&< /*RESET &<&<*/ test_case-&>testcase_name &<&< std::endl; else std::cout &<&< /*RED &<&<*/ "[ Failed ]" &<&< /*RESET &<&<*/ test_case-&>testcase_name &<&< std::endl;if (test_case-&>test_result)
{ passed_num++; } else { failed_num++; test_result = false; } std::cout &<&< std::endl; }std::cout &<&< std::endl;
std::cout &<&< /*YELLOW &<&<*/ "[ RUN OVER ]" &<&< /*RESET &<&<*/ "Total " &<&< testcases_.size() &<&< " Unit Testing" &<&< std::endl; std::cout &<&< /*GREEN &<&<*/ "[ PASS ]" &<&< /*RESET &<&<*/ passed_num &<&< " Units" &<&< std::endl; std::cout &<&< /*RED &<&<*/ "[ FAIL ]" &<&< /*RESET &<&<*/ failed_num &<&< " Units" &<&< std::endl; return test_resu<}enum OperatorType
{ OPERATOR_TYPE_EQ, OPERATOR_TYPE_NE, OPERATOR_TYPE_GT, OPERATOR_TYPE_LT, OPERATOR_TYPE_GE, OPERATOR_TYPE_LE};template &
switch (operator_type)
{ case OPERATOR_TYPE_EQ: if (typeid(ElemType) == typeid(double)) condition = !(fabs(left_value - right_value) &< 1e-8); else if (typeid(ElemType) == typeid(float)) condition = !(fabs(left_value - right_value) &< 1e-6); else condition = !(left_value == right_value); strcpy(str_operator, " == "); break;case OPERATOR_TYPE_NE:
if (typeid(ElemType) == typeid(double)) condition = !(fabs(left_value - right_value) &> 1e-8); else if (typeid(ElemType) == typeid(float)) condition = !(fabs(left_value - right_value) &> 1e-6); else condition = !(left_value != right_value); strcpy(str_operator, " != "); break;case OPERATOR_TYPE_GT:
condition = !(left_value &> right_value); strcpy(str_operator, " &> "); break;case OPERATOR_TYPE_LT:
condition = !(left_value &< right_value); strcpy(str_operator, " &< "); break;case OPERATOR_TYPE_LE:
condition = !(left_value &<= right_value); strcpy(str_operator, " &<= "); break;case OPERATOR_TYPE_GE:
condition = !(left_value &>= right_value); strcpy(str_operator, " &>= "); break; }if (condition)
{ UnitTest::GetInstance()-&>current_test_case-&>test_result = 0; std::cout &<&< file_name &<&< "(" &<&< line_num &<&< "): "; std::cout &<&< "Error: Expect: " &<&< str_left_value &<&< str_operator &<&< str_right_value; std::cout &<&< ", Fact: " &<&< left_value &<&< " vs " &<&< right_value &<&< std::endl; } return (!condition);}bool CheckStrData(const char *left_value,
const char *right_value, const char *str_left_value, const char *str_right_value, const char *file_name, const unsigned long line_num, OperatorType operator_type){ bool condition; char str_operator[5];if (operator_type == OPERATOR_TYPE_EQ)
{ condition = !((strcmp(left_value, right_value) == 0)); strcpy(str_operator, " == "); } else if (operator_type == OPERATOR_TYPE_NE) { condition = !((strcmp(left_value, right_value) != 0)); strcpy(str_operator, " != "); }if (condition)
{ UnitTest::GetInstance()-&>current_test_case-&>test_result = 0; std::cout &<&< file_name &<&< "(" &<&< line_num &<&< "): "; std::cout &<&< "Error: Expect: " &<&< str_left_value &<&< str_operator &<&< str_right_value; std::cout &<&< ", Fact: " &<&< left_value &<&< " vs " &<&< right_value &<&< std::endl; } return (!condition);}#define CHECK_NUMERICAL_DATA(left_value, right_value, operator_type)
CheckNumericalData(left_value, right_value, #left_value, #right_value, __FILE__, __LINE__, operator_type)#define CHECK_STR_DATA(left_value, right_value, operator_type) CheckStrData(left_value, right_value, #left_value, #right_value, __FILE__, __LINE__, operator_type)#define EXPECT_EQ(left_value, right_value) CHECK_NUMERICAL_DATA(left_value, right_value, OPERATOR_TYPE_EQ)
#define EXPECT_NE(left_value, right_value) CHECK_NUMERICAL_DATA(left_value, right_value, OPERATOR_TYPE_NE)#define EXPECT_GT(left_value, right_value) CHECK_NUMERICAL_DATA(left_value, right_value, OPERATOR_TYPE_GT)#define EXPECT_LT(left_value, right_value) CHECK_NUMERICAL_DATA(left_value, right_value, OPERATOR_TYPE_LT)#define EXPECT_GE(left_value, right_value) CHECK_NUMERICAL_DATA(left_value, right_value, OPERATOR_TYPE_GE)#define EXPECT_LE(left_value, right_value) CHECK_NUMERICAL_DATA(left_value, right_value, OPERATOR_TYPE_LE)#define ASSERT_EQ(left_value, right_value) if (!CHECK_NUMERICAL_DATA(left_value, right_value, OPERATOR_TYPE_EQ)) return;
#define ASSERT_NE(left_value, right_value) if (!CHECK_NUMERICAL_DATA(left_value, right_value, OPERATOR_TYPE_NE)) return;#define ASSERT_GT(left_value, right_value) if (!CHECK_NUMERICAL_DATA(left_value, right_value, OPERATOR_TYPE_GT)) return;#define ASSERT_LT(left_value, right_value) if (!CHECK_NUMERICAL_DATA(left_value, right_value, OPERATOR_TYPE_LT)) return;#define ASSERT_GE(left_value, right_value) if (!CHECK_NUMERICAL_DATA(left_value, right_value, OPERATOR_TYPE_GE)) return;#define ASSERT_LE(left_value, right_value) if (!CHECK_NUMERICAL_DATA(left_value, right_value, OPERATOR_TYPE_LE)) return;#define EXPECT_TRUE(condition) CHECK_NUMERICAL_DATA(static_cast&
#endif
//*******source.cpp
#include "test.h"
int Add(int a, int b)
{ return a + b;}int Minus(int a, int b)
{ return a - b;}TEST(Test_PassDemo)
{ EXPECT_EQ(3, Add(1, 2)); EXPECT_EQ(0, Minus(1, 1));}TEST(Test_FailDemo)
{ int condition = 0; char a[] = "acc"; char b[] = "abc"; EXPECT_STREQ(a, b); EXPECT_TRUE(condition); EXPECT_EQ(2, Minus(2, 2)); ASSERT_EQ(4, Add(1, 2)); EXPECT_EQ(2, Add(1, 2));}int main(){ return RUN_ALL_TESTS();}MinUnit -- a minimal unit testing framework for C
JTN002 - MinUnit -- a minimal unit testing framework for C
所有代碼如下:
#define mu_assert(message, test) do { if (!(test)) return message; } while (0)
#define mu_run_test(test) do { char *message = test(); tests_run++;
if (message) return message; } while (0)
extern int tests_run;
cppunit,不過我只用過cunit, 因為部門不讓用c++單元測試很給力,不過log也不能少
好像有個CPPUnit是專門作單元測試的,你可以了解參考一下阿
gmock
推薦一本書 《morden c++ with test driven development》1.google test。好處是很好的「圖形」顯示。2. boost test:boost的1.54以後新增了test庫,好處是如果已經用了boost,就不用新引入庫啦。3. python test:用來測試一些介面挺方便。
gtest也不錯
log4c++
一般需要自己動手編寫測試程序,本文是我的一篇總結,大家可以參考:http://www.zhouzhaoxiong.com/455.html
寫個程序代碼,造自動樁函數,測試待測功能函數或者膜塊。可用gtest測試待測函數,推薦這個因為它高端大氣上檔次,代碼少,又使用簡單,輸出很好看!再么用log,跑程療看log。這個就沒gtest那麼好了!
推薦閱讀:
※各位都是怎麼進行單元測試的?
※MFC 過時了嗎?
※如何用c++寫一個簡單的計算器程序?
※C++在acm里的優勢相比其他語言有多大?
※如何入門CDQ分治?
TAG:C |