摘錄官方說明如下:
- Unity - Curiously Powerful Unit Testing in C for C.
- CMock - Automagical generation of stubs and mocks for Unity Tests.
- CException - Lightweight exception handling for C.
- Ceedling - Test build management.
Unity
此模組是一個純 C 語言的單元測試架構,提供了許多測試函數,由函數名稱可以清楚的知道其用途,例如:
TEST_ASSERT_TRUE(condition) // 預期 condition = true, 否則 assert此模組好處是簡單易用,下面是一個使用範例
TEST_ASSERT_FALSE(condition) // 預期 condition = false, 否則 assert
TEST_ASSERT(condition) // 與 TEST_ASSERT_TRUE() 相同
TEST_ASSERT_EQUAL_INT(expected, actual) // 若 actual != expected 就 assert
TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) // 比較兩塊記憶體內容是否相同,若不同就 assert
假設程式碼實作如下:
int a = 1;則輸出如下:
TEST_ASSERT_EQUAL_INT(2, a);
TEST_ASSERT_EQUAL_HEX8(5, a);
TEST_ASSERT_EQUAL_UINT16(0x8000, a);
TestMyModule.c:15:test_One:FAIL:Expected 2 was 1詳細用法可參考 https://github.com/ThrowTheSwitch/Unity
TestMyModule.c:23:test_Two:FAIL:Expected 0x05 was 0x01
TestMyModule.c:31:test_Three:FAIL:Expected 32768 was 1
CMock
如果有個工具能自動產生測試案例,直接幫忙使用各種 TEST_ASSERT_xxx協助檢查輸入輸出就好了。
幸運的是 CMock 就是一個這樣的工具。CMock會分析 header file,自動幫忙生成一些檢查值的測試函數,而內部的檢查機制仍是使用 unity 定義的函數。
摘錄官方說明如下
- CMock generates pure C code from regular C headers. No special markup required.
- CMock automatically generates your mock modules from simple headers, saving you from tediously creating your own stubs.
Jordan Schaenzle 所發表的文章 The mock object approach to test-driven development,詳細地說明了Mock function,摘錄如下:
A mock is a stand-in for a real module. It doesn’t contain any real functionality but rather imitates a module’s interface. When used in a test, a mock intercepts calls between the module under test and the mocked module.
假設 Parse.h 宣告函數如下:
int ParseStuff(char* Cmd);CMock 會協助生成 MockParse.c 與 MockParse.h ,並產生下列函數:
void ParseStuff_ExpectAndReturn(char* Cmd, int toReturn);接著撰寫測試程式時,先預告預期會處理的參數與返回值,再呼叫測試程式,如下:
void ParseStuff_IgnoreAndReturn(int toReturn);
void ParseStuff_StubAndCallback(CMOCK_ParseStuff_CALLBACK Callback);
#include "MockParse.h" // 原本是 #include "Parse.h"原本呼叫 ParseStuff() 的地方,現在會變成先呼叫 ParseStuff_ExpectAndReturn()然後再呼叫 ParseStuff(),這樣的改變並不需要改變原本的程式碼,CMock 所產生的函數會協助我們作這個改變。
ParseStuff_ExpectAndReturn("NeatStuff", 1);
MyFunctionInvokeParseStuffSomeWhere(); // 內部會呼叫 ParseStuff()
參考資料:http://www.throwtheswitch.org/cmock
CException
此模組透過兩個檔案提供 expection hander,CException.h and CException.c,只要平台上能夠支援 setjmp/longjmp,就可以使用此模組。
使用方式為 Try Catch Throw。
實際使用範例可參考:http://www.throwtheswitch.org/cexception
Ceedling
此模組會使用 Unity,CMock 與 CExpection,可以與 Eclipse 或 sublime 等編輯器結合,並且可以針對不同的開發環境產生不同的執行程式(release binaries in target or test binaries in PC)。
Matt Chernosky 提供了非常詳細的使用步驟
http://www.electronvector.com/blog/add-unit-tests-to-your-current-project-with-ceedling
至於是否需要使用 Ceedling,或是只使用 Unity即可?可以根據此篇作個選擇。
http://www.throwtheswitch.org/decide-o-tron
參考資料:
https://www.ibm.com/developerworks/cn/linux/l-tdd/
https://www.ibm.com/developerworks/cn/linux/l-cppunit/index.html
https://www.slideshare.net/hugolu/ss-31191146
http://m.sanmin.com.tw/product/index/99o155l8n108m88k101b69z108k121memgqoe1881rnk