1. 程式人生 > >EmbedC_TDD__1 Keil中搭建自動化單元測試框架Unity

EmbedC_TDD__1 Keil中搭建自動化單元測試框架Unity

1 什麼是Unity

Unity是一個全部用C實現的自動化測試框架。它由很少的幾個檔案構成。

自動化測試框架就是一個軟體包,它能讓程式設計師表達產品程式碼應該有什麼樣的行為。自動化測試單元測試框架的工作需要提供以下能力:

  1. 用於表述測試用例的通用語言
  2. 用於表述期望結果的通用語言
  3. 能夠使用產品程式碼所用的程式語言的功能
  4. 能夠把所有的工程、系統或者子系統的單元測試用例收集到一起。
  5. 一個能執行全部或者部分測試用例的機制
  6. 對於測試套件的成功和失敗給出明確的報告
  7. 對於失敗的測試給出詳細的報告

需要指出的是測試框架只是給我們實現了一套測試機制,具體的測試用例還需要我們自己編寫。

2 為什麼要使用Unity

使用Unity的好處將在另一篇博文中詳細介紹。請點選這裡檢視。

3 獲取Unity的原始碼

4 Unity原始碼目錄結構分析

目錄 內容
src 這個資料夾中包含unity.c、unity.h、unity_internals.h,這是最基本的Unity組成,有了這三個檔案你就可以開始編寫測試用例了
docs Untiy的相關應用文件都在這裡,有條件同學建議都讀一下
auto 簡化測試用例搭建的Ruby指令碼,沒研究過Ruby,暫時不知道咋用
examples 參考測試例程
extras 附加實現夾具的功能
test Unity的所有的測試

5 在Keil中搭建Unity

5.1 將Unity原始碼新增到Kiel工程中

  1. 在工程檔案中新建Unity目錄,並拷貝從GitHub上下載下來的原始碼,如下圖: 在這裡插入圖片描述

  2. 在Keil已有的工程中新建Unity目錄,用於和Unity相關的原始碼實現,然後加入unity.c和unity_fixture.c。如下圖: 在這裡插入圖片描述

  3. 包含新新增的標頭檔案的路徑 在這裡插入圖片描述

  4. 在unity的原始碼examples中找到unity_config.h並放到我們工程的unity資料夾下。

  5. 編譯已有的keil工程,無錯誤無警告後繼續,有錯誤則檢測。

5.2 配置unity_config.h

開啟unity_config.h並配置,主要是為了配置一些資料型別和列印的重定向。我使用cm4核心定義的配置如下:

 #define UNITY_EXCLUDE_LIMITS_H /* 呼叫limits.h, UINT_MAX和ULONG_MAX預設是32位*/
  #define UNITY_EXCLUDE_STDINT_H  /* */
  #define UNITY_INT_WIDTH 32 /* int型變數是32位 */
  #define UNITY_POINTER_WIDTH 32 /* 設定指標為32位  因為我們是32位系統 */
   #define UNITY_INCLUDE_DOUBLE /**/
   #define UNITY_OUTPUT_CHAR(a)                       fputc(a, stdout) /* 重定向輸出列印函式 */
   #define UNITY_SUPPORT_WEAK __attribute__((weak)) /* 設定Unity中setup、teardown、suiteSetUp、suiteTearDown為弱函式如,果自己的工程中有setup函式Unity中自動無效而不會產生重定義問題。具體以原始碼中介紹為準。*/
   

其中比較重要的配置就是unity輸出的重定向了,這個函式會列印具體的unity的輸出資訊,如果我們現有的工程是使用串列埠輸出,則可以直接定向到串列埠輸出上,這裡我使用的是EventRecoder除錯工具,使用標準的printf輸出,所以直接重定向到了fputc上。

5.3 編寫測試用例

完成以上的步驟,我們就可以使用Unity了。仿照examples裡的例子,我們直接建立一個TestProductionCode_Runner.c檔案,該檔案包含了Unity的入口main函式。所以,對於我們工程的main函式來說,就不能這麼寫了,在完成相關的初始化後,必須退出,然後進入到Unity的main函式入口。改動如下:

#ifdef USING_UNITY_MAIN
int product_main(void)
#else
int main(void)
#endif
{ 
    EventRecorderInitialize(EventRecordAll, 1U);
    EventRecorderStart();
    
	delay_init(168);		  //初始化延時函式
	LED_Init();		        //初始化LED埠
	OLED_Init();			//初始化OLED  
	OLED_Clear();
	OLED_ShowString(0,0,"0.96' OLED TEST",16);
	printf("Hello EventRecord!\r\n");
#ifndef USING_UNITY_MAIN   
    while(1)
    {
        LED2 = 0;
        LED3 = 1;
        delay_ms(500);
        LED2 = 1;
        LED3 = 0;
        delay_ms(500);
     }
#endif
    return 0;
}

5.3 Unity測試結果解析

在這裡插入圖片描述

如上所示,沒有訊息就是最好的訊息,如果全部測試通過,最後會列印OK,如果測試失敗,則會反饋失敗的原因和具體的失敗位置。

最後,工程原始碼請點選這裡獲取。