本文轉(zhuǎn)自公眾號(hào),歡迎關(guān)注
嵌入式C單元測(cè)試框架unity-初體驗(yàn) (qq.com)
前言
在嵌入式領(lǐng)域,尤其是MCU領(lǐng)域,一般很少有使用單元測(cè)試框架,一般就是開發(fā)階段開發(fā)人員按照自己的習(xí)慣和經(jīng)驗(yàn)進(jìn)行自測(cè),然后就是系統(tǒng)集成測(cè)試,所以一般在單元測(cè)試這一環(huán)做的不是很規(guī)范。實(shí)際上我們?cè)陂_發(fā)中應(yīng)該要改善這種現(xiàn)狀,加強(qiáng)單元測(cè)試的管理,避免單元測(cè)試純憑開發(fā)人員是否有時(shí)間做,做到什么程度也是隨緣。應(yīng)該由測(cè)試來保證開發(fā)質(zhì)量,避免依賴于個(gè)人,并且積累測(cè)試用例庫(kù),這樣有助于產(chǎn)品迭代穩(wěn)定,尤其是在BSP等領(lǐng)域,有一個(gè)好的測(cè)試框架和測(cè)試用例集能很好的完成芯片的驗(yàn)證,和生產(chǎn)測(cè)試等工作。
恰好有這樣一個(gè)框架,專為嵌入式領(lǐng)域純粹的C測(cè)試而生-unity,使用ANSI C編寫,移植性好,資源占用少,就一個(gè)C文件和h文件,可以通過h進(jìn)行一些配置,特別適合MCU開發(fā)等領(lǐng)域。
官網(wǎng)
http://www.throwtheswitch.org/
http://www.throwtheswitch.org/unity
下載源碼
https://github.com/ThrowTheSwitch/Unity/
或者
https://github.com/ThrowTheSwitch/Unity/archive/master.zip
使用
http://www.throwtheswitch.org/unity
這個(gè)頁面可以看到基本的介紹,瀏覽一下就知道個(gè)大概了,
https://github.com/ThrowTheSwitch/Unity/
下的README.md也可以先看一下。
先不管細(xì)節(jié),不需要了解很多,不管三七二十一先用了再說。
這里使用某個(gè)MCU的開發(fā)板,MDK環(huán)境進(jìn)行測(cè)試。
我們這里使用源碼中的example_1進(jìn)行測(cè)試。
添加代碼
將下載的源碼Unity\\src下的unity.c,unity.h,unity_internals.h
Unity\\examples下的unity_config.h
放到自己工程的unity目錄下,這一部分是unity源碼
Unity\\examples\\example_1\\src下的所有文件放置到自己工程的src目錄下,這一部分是用戶代碼需要測(cè)試的
Unity\\examples\\example_1\\test下的所有文件放置到自己工程的test目錄下,這一部分是測(cè)試代碼
配置頭文件包含路徑
添加上述幾個(gè)文件夾到頭文件包含路徑
依賴
默認(rèn)依賴打印輸出函數(shù)putchar
見unity_internals.h中
#ifndef UNITY_OUTPUT_CHAR
/* Default to using putchar, which is defined in stdio.h */
#include < stdio.h >
#define UNITY_OUTPUT_CHAR(a) (void)putchar(a)
#else
/* If defined as something else, make sure we declare it here so it's ready for use */
#ifdef UNITY_OUTPUT_CHAR_HEADER_DECLARATION
extern void UNITY_OUTPUT_CHAR_HEADER_DECLARATION;
#endif
#endif
我們要根據(jù)自己的情況進(jìn)行移植,
unity_config.h中配置以下宏,其中RS232_putc在我們自己的代碼中實(shí)現(xiàn)
注意:需要在unity_internals.h中#define UNITY_INCLUDE_CONFIG_H 1
或者在工程配置中定義宏UNITY_INCLUDE_CONFIG_H,才會(huì)使用unity_config.h
比如MDK工程中設(shè)置
如果已經(jīng)實(shí)現(xiàn)了標(biāo)準(zhǔn)輸入輸出重定向,有putchar則不需要使能這些宏,直接使用putchar。
測(cè)試1
example_1中有兩個(gè)測(cè)試,一個(gè)是源碼帶2的一個(gè)是不帶2的。
代碼中
先將帶2的相關(guān)代碼不進(jìn)行編譯
將TestProductionCode_Runner.c中的main函數(shù)名改為testrunner_main
在自己工程的main函數(shù)中調(diào)用該函數(shù)(先 extern int testrunner_main(void);申明下函數(shù))
運(yùn)行程序打印如下
test/TestProductionCode.c:20:test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode:PASS
test/TestProductionCode.c:33:test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken:FAIL: Expected 1 Was 0
test/TestProductionCode.c:41:test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue:PASS
test/TestProductionCode.c:51:test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain:PASS
test/TestProductionCode.c:61:test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed:FAIL: Expected 0x00001234 Was 0x00005A5A
-----------------------
5 Tests 2 Failures 0 Ignored
FAIL
測(cè)試2
使用帶2的代碼
TestProductionCode2_Runner.c中main函數(shù)名改為testrunner2_main
在自己的代碼中調(diào)用
testrunner2_main
先 extern int testrunner2_main(void);申明該函數(shù)
運(yùn)行看到輸出如下
test/TestProductionCode2.c:20:test_IgnoredTest:IGNORE: This Test Was Ignored On Purpose
test/TestProductionCode2.c:25:test_AnotherIgnoredTest:IGNORE: These Can Be Useful For Leaving Yourself Notes On What You Need To Do Yet
test/TestProductionCode2.c:30:test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented:IGNORE
-----------------------
3 Tests 0 Failures 3 Ignored
OK
總結(jié)
以上可以看到,unnity進(jìn)行單元測(cè)試十分方便,移植也很簡(jiǎn)單,先進(jìn)行一個(gè)初體驗(yàn),后面再詳細(xì)介紹其使用和設(shè)計(jì)原理。
審核編輯:湯梓紅
-
mcu
+關(guān)注
關(guān)注
146文章
17123瀏覽量
350975 -
嵌入式
+關(guān)注
關(guān)注
5082文章
19104瀏覽量
304791 -
源碼
+關(guān)注
關(guān)注
8文章
639瀏覽量
29185 -
Unity
+關(guān)注
關(guān)注
1文章
127瀏覽量
21806
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論