2020/7/14
學習內容:
-
單元測試框架的編寫與實現,單元測試框架屬於測試的一部分,驗證程序的某一部分邏輯是否正確。
-
模仿google test模塊的方式,在文件中加入多個TEST函數,然后調用RUN_ALL_TESTS函數就可以執行所有的TEST函數,並且返回結果;
-
TEST函數其實並不是真正意義上的一個函數,而是通過宏定義實現的一個文件頭。因為多個TEST函數存在於同一個文件中肯定是不符合c語言的語法的。
通過以下代碼定義TEST
#define TEST(a, b) void a_##_b() //定義了一個函數頭 #define EXPECT(a, comp ,b) {\ if (!((a) comp (b))) { \ test_func_flag = 1; \ //用於標記測試是否出錯,全局變量 expect_printf(__FILE__, __LINE__, "(" #a ") " #comp " (" #b ")"); \ } \ } #define EXPECT_EQ(a, b) EXPECT(a, ==, b); //這里使用了一個技巧 #define EXPECT_NE(a, b) EXPECT(a, !=, b); //但是這樣我們不知道有幾個測試用例,如何執行測試用例 //使用attribute注冊函數使函數先於main函數執行 //將TEST(a, b)改為如下 #define TEST(a, b) \ void a##_##b();\ //這一句是聲明這個測試函數,不然在注冊函數時會出現未聲明 __attribute__((constructor)) \ //先於main函數執行 void add_##a##_##b() { \ add_func(a##_##b, #a "." #b); \ }\ void a##_##b() //原來的函數頭放在了這里 //接下來實現一些接口函數和結構 struct Func_Data { void (*func)(); const char *func_name; } func_arr[100]; //真正的工程中是不可以用一個固定大小的數組的 int func_cnt; void add_func(void (*func)(), const char *func_name) { func_arr[func_cnt].func = func; func_arr[func_cnt].func_name = func_name; func_cnt++; return; //禮貌性的返回 } int test_func_flag; void expect_printf(const char *file, int line_on, const char *msg) { printf(YELLOW" %s:%d : Failure\n", file, line_on); printf(YELLOW" Expected: %s\n"NONE, msg); return; } int RUN_ALL_TEST() { printf(GREEN"[==========]"NONE" Running %d tests\n", func_cnt); for (int i = 0; i < func_cnt; i++) { printf(GREEN"[ RUN ] %s\n", func_arr[i].func_name); test_func_flag = 0; int b = clock(); func_arr[i].func(); int e = clock(); if (test_func_flag) { printf(RED"[ FAILED ]\n"NONE); } else { printf(GREEN"[ OK ]\n"NONE); } printf(" %s (%s ms)\n", func[i].func_name, 1000 * (e - b) / CLOCK_PER_SEC); } return 0; } //將測試函數封裝在testcasen.h中 #ifdef DEBUG #include "testcase.h" #endif //... #ifdef DEBUG return RUN_ALL_TESTS(); #else return 0; #endif //makefile 的編寫 release: debug: -DDEBUG