【嵌入式】在嵌入式工程中搭建Unity单元测试框架

Unity测试框架的使用

一 测试框架说明

Unity是一个单元测试框架。我们的目标是保持它的规模和功能。核心的Unity测试框架有三个文件:一个C文件和两个头文件。它们共同提供函数和宏,使测试更容易。

二 测试框架使用

测试文件是C文件。通常情况下,将为要测试的每个C模块创建一个测试文件。测试文件应该包括unity.h和要测试的C模块的头文件。接下来,测试文件将包括setUp()和tearDown()函数。
setUp函数可以包含希望在每次测试之前运行的任何内容。
tearDown函数可以包含希望在每次测试之后运行的任何内容。
这两个函数都不接受参数,也不返回任何东西。如果你不需要它们,你可以把它们中的一个或两个都留空。
文件的大部分将是一系列测试函数。测试函数遵循以 test_ 或 spec_ 开头的惯例。您不必这样命名它们,但是它清楚地说明了哪些函数是针对其他开发人员的测试。此外,与Unity或Ceedling一起提供的自动化脚本将默认寻找以这种方式添加前缀的测试函数。测试函数不接受任何参数,也不返回任何结果。所有的测试会计都在Unity内部处理。
最后,在测试文件的底部,将编写一个main()函数。这个函数将调用UNITY_BEGIN(),然后为每个测试调用RUN_TEST,最后调用UNITY_END()。这实际上会触发每个测试函数运行,因此每个函数都有自己的RUN_TEST调用是很重要的。
完成后,测试文件将如下所示:

1.	#include "unity.h"  
2.	#include "file_to_test.h"  
3.	  
4.	void setUp(void) {  
5.	    // set stuff up here  
6.	}  
7.	  
8.	void tearDown(void) {  
9.	    // clean stuff up here  
10.	}  
11.	  
12.	void test_function_should_doBlahAndBlah(void) {  
13.	    //test stuff  
14.	}  
15.	  
16.	void test_function_should_doAlsoDoBlah(void) {  
17.	    //more test stuff  
18.	}  
19.	  
20.	// not needed when using generate_test_runner.rb  
21.	int main(void) {  
22.	    UNITY_BEGIN();  
23.	    RUN_TEST(test_function_should_doBlahAndBlah);  
24.	    RUN_TEST(test_function_should_doAlsoDoBlah);  
25.	    return UNITY_END();  
26.	}  

三 实际使用例程(结合代码重构)

(1)先写一个简单的接口powerCode16To8,作用是指定偏移量,将一串16位的通信码转换成8位的通信码:

1.	/************************************************************************** 
2.	* 函数名称:powerCode16To8 
3.	* 功能描述:电源板16位通信码转8位通信码 
4.	* 输入参数: 
5.	* 输出参数: 
6.	* 返 回 值: 
7.	* 其它说明: 
8.	**************************************************************************/  
9.	int powerCode16To8(IN int offset, IN uint8_t p_power_code_16[COMM_CODE_TOTAL_LEN], OUT uint8_t p_power_code_8[COMM_CODE_LEN])  
10.	{  
11.	    int i;  
12.	    memset(p_power_code_8,0x00,sizeof(COMM_CODE_LEN));  
13.	    for(i = 0;i < COMM_CODE_LEN;i ++)  
14.	    {  
15.	        p_power_code_8[i] = p_power_code_16[offset + i];  
16.	    }  
17.	      
18.	    return 1;  
19.	}  

(2)编写测试用例如下,该用例将一个16位的通信码,向右偏移一位,取其前八位作为结果power_code_8,与预期结果t_power_code_8进行比较,如果比较结果一致,则视为用例通过:

1.	void Test_Motor_Given_power_code_16_When_powerCode16To8_Then_OK(void)   
2.	{  
3.	    uint8_t power_code_16[COMM_CODE_TOTAL_LEN] = 
4.	{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
5.	 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};  
6.	    uint8_t power_code_8[COMM_CODE_LEN] = {0};  
7.	    uint8_t t_power_code_8[COMM_CODE_LEN] = 
8.	{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};                           
9.	                                                    
10.	    powerCode16To8(1, power_code_16, power_code_8);  
11.	    TEST_ASSERT_EQUAL_HEX8_ARRAY(t_power_code_8, power_code_8, COMM_CODE_LEN);  
12.	}  

(3)编写RUN_TEST,并在main函数中加入测试用例(可以用宏控制测试版本和非测试版本,以控制片上资源的消耗)

1.	void Test_Motor_Entry()  
2.	{  
3.	    SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);  
4.	    printf("\r\n%s\t\t%s\r\n", __DATE__, __TIME__);  
5.	      
6.	    UNITY_BEGIN();  
7.	    RUN_TEST(Test_Motor_Given_power_code_16_When_powerCode16To8_Then_OK);  
8.	    UNITY_END();  
9.	}  
10.	  
11.	int main(void)  
12.	{  
13.	    /****************单元测试模块****************/  
14.	    #ifdef  UNITY_TEST_ASSERT  
15.	      
16.	    Test_Motor_Entry();  
17.	      
18.	    #endif  
19.	    /********************END********************/  
20.	}  

(4)编译运行并通过SEGGER_RTT(先在Project.map里面找到_SEGGER_RTT的地址(内部flash的地址),再在打开的RTT_Viewer中输入对应的地址,就可以输出Unity输出的打印信息),可以打印测试结果如下(也可以通过Telnet本机127.0.0.1的方式,将打印的内容输出到SecureCRT等工具中,拷贝出来分析):
【嵌入式】在嵌入式工程中搭建Unity单元测试框架_第1张图片
【嵌入式】在嵌入式工程中搭建Unity单元测试框架_第2张图片

四 相关资料索引

【1】《C语言单元测试Unity使用(一) 入门指南》

【2】《Keil中搭建自动化单元测试框架Unity》

【3】GitHub中Unity开源库文件

你可能感兴趣的:(嵌入式,嵌入式,单元测试)