關於CUnit, 本文主要從介紹三方面的內容:
1.CUnit的介紹。
1.1 介紹如何使用CUnit。
CUnit是一個對C語言編寫的程序進行單元測試的框架,在線文檔說它作為一個靜態鏈接庫被鏈接到用戶的測試代碼中。它提供了一種簡潔的框架來建立測試架構,並提供豐富的斷言(Assertion)來測試通用數據類型。除此之外,它還提供了許多不同的結構來運行測試用例和報告測試結果。
(1)CUnit的架構
Test Registry
|
------------------------------
| |
Suite '1' . . . . Suite 'N'
| |
--------------- ---------------
| | | |
Test '11' ... Test '1M' Test 'N1' ... Test 'NM'
提到這個框架,為後面如何使用CUnit提供了基礎。
先介紹這個框架,從底層往上介紹就兩句話:
(1)每個測試用例被包裝在一個測試包(suite)中,
(2)每個測試包(suite)是在有效的測試注冊單元(Test Registry)中注冊的。
對於CUnit來說,它是單線程運行,所以每次只能有一個有效的測試注冊單元(Test Registry),這個測試注冊單元下面可以包含多個測試包(suite),每個測試包可以擁有多個測試用例。劃分測試包(suite)的規則可以自由約定,比如按照模塊來劃分,一個模塊的測試用例集中到一個測試包中(suite)。至於測試用例,則用來測試模塊內部的函數。測試用例函數通過提供的各類輸入調用被測試的函數,返回執行結果,然後通過CUnit提供的斷言來判斷被測試的函數是否正確。
(2)測試模式
下面是四種測試模式:
1 Automated Output to xml file Non-interactive
2 Basic Flexible programming interface Non-interactive
3 Console Console interface (ansi C) Interactive
4 Curses Graphical interface (Unix) Interactive
第一種模式是將結果輸出到XML文檔中,便於生成報告。第二種模式是每一次運行結束之後在standard output中顯示測試結果,不能保留測試結果數據。第三種模式是console方式的,可以人機交互;前兩種模式是非交互式的。第四種只在Unix中使用。
(3)測試的基本流程
1)編寫單元測試函數(有必要的話要寫suite的init/cleanup函數)。Write functions for tests (and suite init/cleanup if necessary).
2)調用函數CU_initialize_registry()初始化測試注冊單元(Test Registry)。 Initialize the test registry - CU_initialize_registry()
3)調用函數CU_add_suite() 將測試包(suite)添加到測試注冊單元(Test Registry)中。Add suites to the test registry - CU_add_suite()
4)調用函數CU_add_test()將測試用例添加到測試包(suite)中。Add tests to the suites - CU_add_test()
5)使用合適的接口來運行測試用例。Run tests using an appropriate interface, e.g. CU_console_run_tests
6)調用函數CU_cleanup_registry清除測試注冊單元(Test Registry)。Cleanup the test registry - CU_cleanup_registry()
/*File:test.c *Auth:sjin *Date:2014-03-20 *Mail:[email protected] */ #include test.h #includeint sum(int a,int b) { return a + b; }
/*File:test.h *Auth:sjin *Date:2014-03-20 *Mail:[email protected] */ #ifndef __TEST_H_ #define __TEST_H_ int sum(int a,int b); #endif
/*File:testmain.c *Auth:sjin *Date:2014-03-20 *Mail:[email protected] */ #include test.h #include#include #include int InitSuite() { return 0; } int EndSuite() { return 0; } int Test_Is_Equal(int a,int b,int real) { int result; result = sum(a,b); if(result == real){ return 1; } return 0; } int Test_Is_Not_Equal(int a,int b,int real) { int result; result = sum(a,b); if(result != real){ return 1; } return 0; } void Test1() { CU_ASSERT(Test_Is_Equal(3,4,7)); } void Test2() { CU_ASSERT(Test_Is_Not_Equal(4,5,10)); } /*0:sucessful;1:failed */ int AddTestMain() { #if 1 CU_pSuite pSuite = NULL; /***************** * 1.CU_add_suite 增加一個Suite * 2.Suite名字:testSuite * 3.InitSuite EndSuite 分別是測試單元初始和釋放函數,如不需要傳NULL */ pSuite = CU_add_suite(testSuite,InitSuite,EndSuite); //if(NULL != pSuite){ if(NULL == CU_add_test(pSuite,Test1,Test1) || NULL == CU_add_test(pSuite,Test2,Test2)){ return 1; } // } /**********另一種測試方法**********/ #else CU_TestInfo testcases[] = { {Test1,Test1}, {Test2,Test2}, CU_TEST_INFO_NULL }; CU_SuiteIndo Suites[] = { {Test the functon sum:,InitSuite,EndSuite,testcases}, CU_TEST_INFO_NULL }; if(CUE_SUCCESS != CU_register_suites(Suites)){ return 1; } /******************************/ #endif return 0; }
/*File:CuintRunTest.c *Auth:sjin *Date:2014-03-20 *Mail:[email protected] */ #include#include #include extern int AddTestMain(); int main() { //初始化 if(CUE_SUCCESS != CU_initialize_registry()){ return CU_get_error(); } //返回注冊到用例指針 assert(NULL != CU_get_registry); //檢測是否在執行 assert(!CU_is_test_running()); //調用那個測試模塊完成測試用例 if(0 != AddTestMain()){ CU_cleanup_registry(); return CU_get_error(); } /*使用console控制交互界面的函數入口*/ CU_console_run_tests(); /*使用自動產生XML文件的模式*/ CU_set_output_filename(TestMax); CU_list_tests_to_file(); CU_automated_run_tests(); /*調用完畢清理注冊信息*/ CU_cleanup_registry(); }
INC=-I/usr/local/include LIB=-L/usr/local/lib all:test.c CUnitRunTest.c testMain.c gcc $^ -o test $(INC) $(LIB) -lcunit clean: rm -f test
export LD_LIBRARY_PATH=/usr/local/lib