軟件開發(fā)中,每次需求的變更基本都需要改寫代碼,而代碼變更后就需要進行功能測試。當然,在功能測試之前需要代碼的單元測試,避免代碼改動后部分場景沒有驗證,最后出現(xiàn)各種問題。
常用的C語言測試框架有:
(相關(guān)資料圖)
1、Unity示例
這里介紹Unity,其他的大家感興趣可以自行查閱,不同的單元測試框架適用于不同的開發(fā)需求和場景。開發(fā)人員可以按照自己的項目要求選擇最適合的框架。
Unity最小可以只用到幾個文件即可完成,把Unity源碼目錄下的unity.c
、unity.h
、unity_internals.h
三個文件復制至我們的工程目錄下進行編譯即可,然后在測試文件代碼中包含unity.h
簡單的示例
完成功能函數(shù)的驗證:
#include #include"unity.h"voidsetUp(){//這里可以放置每個測試用例運行前的初始化代碼}voidtearDown(){//這里可以放置每個測試用例運行后的清理代碼}intAdd(inta,intb){returna+b;}voidtest_AddFun(void){TEST_ASSERT_EQUAL_UINT(6,Add(1,5));TEST_ASSERT_EQUAL_UINT(4,Add(-1,5));TEST_ASSERT_EQUAL_UINT(-6,Add(-1,-5));}intmain(){UNITY_BEGIN();//啟動測試RUN_TEST(test_AddFun);UNITY_END();//結(jié)束測試return0;}
通過串口或終端打印內(nèi)容為:
C:\test/test.c:47:test_AddFun:PASS-----------------------1Tests0Failures0IgnoredOK
其中,unity_internals.h
文件中可以修改輸出終端,即UNITY_OUTPUT_CHAR
宏的定義。
/*-------------------------------------------------------*OutputMethod:stdout(DEFAULT)*-------------------------------------------------------*/#ifndefUNITY_OUTPUT_CHAR/*Defaulttousingputchar,whichisdefinedinstdio.h*/#include #defineUNITY_OUTPUT_CHAR(a)(void)putchar(a)#else/*Ifdefinedassomethingelse,makesurewedeclareitheresoit"sreadyforuse*/#ifdefUNITY_OUTPUT_CHAR_HEADER_DECLARATIONexternvoidUNITY_OUTPUT_CHAR_HEADER_DECLARATION;#endif#endif
其中,自定義實現(xiàn)的C語言擴展庫(cot)的容器功能函數(shù)都已通過Unity添加了對應的單元測試用例,鏈接:
2、輕量級通用擴展庫
旨在打造一個C語言的通用擴展庫。
1、介紹
支持多種容器實現(xiàn),包括通用隊列(包括不定長隊列)、棧、雙向鏈表和動態(tài)數(shù)組功能
支持定義序列化/反序列化的結(jié)構(gòu)體功能
移植了部分 C++ Boost庫中的PP庫功能
2、軟件架構(gòu)
目錄說明:
├─cot│ ├─include│ │ ├─container // 容器實現(xiàn)頭文件│ │ ├─preprocessor // 移植Boost庫中的PP庫頭文件│ │ └─serialize // 序列化/反序列化實現(xiàn)頭文件│ └─src│ ├─container // 容器實現(xiàn)源文件│ └─serialize // 序列化/反序列化實現(xiàn)源文件├─test│ ├─container // 容器實現(xiàn)測試代碼│ └─serialize // 序列化/反序列化測試代碼└─unity // 單元測試框架代碼
3、使用說明
(1)容器類功能使用說明
雙向鏈表使用方式demo:
int main(){ cotList_t list; cotListItem_t nodeBuf[10]; cotList_Init(&list, nodeBuf, 10); int data1 = 10; int data2 = 20; int data3 = 30; // 頭部增加元素 cotList_PushFront(&list, &data1); // 尾部增加元素 cotList_PushBack(&list, &data2); // 插入元素 cotList_Insert(&list, cotList_End(&list), &data3); // 使用迭代器遍歷所有元素 for_list_each(item, list) { printf(" = %d\n", *item_ptr(int, item)); } // 移除指定元素 cotList_Remove(&list, &data3); // 根據(jù)添加移除元素 cotList_RemoveIf(&list, OnRemoveCondition); cotList_t list2; cotListItem_t nodeBuf2[3]; cotList_Init(&list2, nodeBuf2, 3); // 鏈表內(nèi)存交換 cotList_Swap(&list1, &list2); return 0;}
動態(tài)數(shù)組使用方式demo:
int main(){ uint8_t buf[20]; cotVector_t vector; cotVector_Init(&vector, buf, sizeof(buf), sizeof(uint32_t)); // 在尾部追加元素 uint32_t data = 42; cotVector_Push(&vector, &data); data = 56; cotVector_Push(&vector, &data); data = 984; cotVector_Push(&vector, &data); // 插入元素 uint32_t arrdata[2] = {125, 656}; cotVector_InsertN(&vector, 2, &arrdata, 2); // 刪除兩個元素 cotVector_RemoveN(&vector, 1, 2); // 根據(jù)添加刪除元素 cotVector_RemoveIf(&vector, OnVectorRemoveCondition); // 打印數(shù)組中的數(shù)據(jù)內(nèi)容 for (int i = 0; i < cotVector_Size(&vector); i++) { printf("%02x ", cotVector_Data(&vector)[i]); } return 0;}
int main(){ uint8_t buf[10]; cotQueue_t queue; cotQueue_Init(&queue, buf, sizeof(buf), sizeof(int)); // 在尾部追加元素 int data = 42; cotQueue_Push(&queue, &data, sizeof(data)); data = 895; cotQueue_Push(&queue, &data, sizeof(data)); // 訪問元素 int *pData = (int *)cotQueue_Front(&queue); printf("val = %d \n", *pData); // 彈出首個元素 cotQueue_Pop(&queue); return 0;}
隊列(不定長FIFO)使用方式demo:
int main(){ uint8_t buf[10]; cotIndQueue_t queue; cotIndQueue_Init(&queue, buf, sizeof(buf)); // 在尾部追加元素 char data = 42; cotIndQueue_Push(&queue, &data, sizeof(data)); int data1 = 80; cotIndQueue_Push(&queue, &data, sizeof(data1)); long data2 = -400; cotIndQueue_Push(&queue, &data, sizeof(data2)); // 訪問元素 size_t length; int *pData = (int *)cotIndQueue_Front(&queue, &length); printf("val = %d \n", *pData, length); // 彈出首個元素 cotIndQueue_Pop(&queue); return 0;}
int main(){ uint8_t buf[10]; cotStack_t stack; cotStack_Init(&stack, buf, sizeof(buf), sizeof(int)); // 在頂部追加元素 int data = 42; cotStack_Push(&stack, &data, sizeof(data)); data = 895; cotQueue_Push(&stack, &data, sizeof(data)); // 訪問元素 int *pData = (int *)cotStack_Top(&stack); printf("val = %d \n", *pData); // 彈出頂部元素 cotStack_Pop(&stack); return 0;}
(2)序列化/反序列化功能使用說明
可以定義一個公共頭文件:
#ifndef STRUCT_H#define STRUCT_H#include "serialize/serialize.h"COT_DEFINE_STRUCT_TYPE(test_t, ((UINT16_T) (val1) (2)) ((INT32_T) (val2) (1)) ((UINT8_T) (val3) (1)) ((INT16_T) (val4) (1)) ((DOUBLE_T) (val5) (1)) ((INT16_T) (val6) (1)) ((STRING_T) (szName) (100)) ((DOUBLE_T) (val7) (1)) ((FLOAT_T) (val8) (1)) ((STRING_T) (szName1) (100)))#endif // STRUCT_H
#include "struct.h"int main(){ uint8_t buf[100]; // 序列化使用demo COT_DEFINE_STRUCT_VARIABLE(test_t, test); test.val1[0] = 5; test.val1[1] = 89; test.val2 = -9; test.val3 = 60; test.val4 = -999; test.val5 = 5.6; test.val6 = 200; test.val7 = -990.35145; test.val8 = -80.699; sprintf(test.szName, "test56sgdgdfgdfgdf"); sprintf(test.szName1, "sdfsdf"); int length = test.Serialize(buf, &test); printf("Serialize: \n"); for (int i = 0; i < length; i++) { printf("%02x %s", buf[i], (i + 1) % 16 == 0 ? "\n" : ""); } printf("\n"); // 反序列化使用demo test_t test2; // COT_DEFINE_STRUCT_VARIABLE(test_t, test2); COT_INIT_STRUCT_VARIABLE(test_t, test2); test2.Parse(&test2, buf); printf("val = %d\n", test2.val1[0]); printf("val = %d\n", test2.val1[1]); printf("val = %d\n", test2.val2); printf("val = %d\n", test2.val3); printf("val = %d\n", test2.val4); printf("val = %lf\n", test2.val5); printf("val = %d\n", test2.val6); printf("name = %s\n", test2.szName); printf("val = %lf\n", test2.val7); printf("val = %f\n", test2.val8); printf("name = %s\n", test2.szName1); return 0;}
標簽:
精彩推薦
- 環(huán)球熱文:出任黨委書記!招商仁和人壽迎新領(lǐng)... 2023-06-05 19:10:21
- 今日熱聞!北新涇街道的“日間照料中心”,安排... 2023-06-05 18:54:09
- 孔孟顏曾不能通婚_孔孟顏曾不能亂稱 焦點觀察 2023-06-05 16:49:07
- 聚焦:黃金9999價格今天多少一克(2023年6月5日) 2023-06-05 16:38:39
- 嵌入式代碼單元測試如何完成? 2023-06-05 19:20:51
- 天天觀察:動人心弦的豪華之作,攬勝極光L釋放... 2023-06-05 19:09:09
- 焦點快看:公安數(shù)據(jù)應用鯤鵬實驗室和警務(wù)大數(shù)... 2023-06-05 19:12:03
- 觀熱點:信用卡如何掛賬停息?停息掛賬為什么... 2023-06-05 19:08:30
- 環(huán)球熱文:出任黨委書記!招商仁和人壽迎新領(lǐng)... 2023-06-05 19:10:21
- 暫停營業(yè)!淄博張店區(qū)燒烤協(xié)會發(fā)布倡議書 今日視點 2023-06-05 19:04:28
- 今日熱聞!北新涇街道的“日間照料中心”,安排... 2023-06-05 18:54:09
- 全球焦點!呼和浩特市和林格爾縣老師赴煙臺市... 2023-06-05 18:25:50
- 2023端午天津周邊好去處推薦 2023-06-05 18:05:22
- 2023天津端午看海好去處有哪些|環(huán)球滾動 2023-06-05 18:04:11
- 東莞高溫補貼領(lǐng)取條件及標準 2023-06-05 18:08:30
- 東莞高溫補貼哪些人可以領(lǐng)?|今日播報 2023-06-05 18:10:42
- 2023年6月10日起嘉定20路站點臨時調(diào)整 2023-06-05 18:04:10
- 2023松江區(qū)高考考點有哪些 2023-06-05 18:18:24
- 2023廣州增城區(qū)可搭帳篷嗎? 2023-06-05 18:20:19
- 2023廣州寶墨園第三屆漢風荷韻旅游文化節(jié)|世界熱訊 2023-06-05 18:09:26
- 從化區(qū)關(guān)于做好2023年高考期間公交保障工作的告示 2023-06-05 18:11:53
- 2023端午節(jié)廣州景點在哪里預約?|世界通訊 2023-06-05 18:10:56
- 世界速遞!治學經(jīng)驗 2023-06-05 18:14:15
- 武昌積玉橋街道:多舉措強化普法宣傳,為建設(shè)... 2023-06-05 17:58:30
- 巴南:175家企業(yè)為“萬企興萬村”行動注入新動... 2023-06-05 17:45:58
- 天天快消息!蕪湖安徽碼是什么碼? 2023-06-05 17:09:21
- 世界速讀:2023端午節(jié)天津博物館門票預約時間+入口 2023-06-05 17:26:17
- 2023端午節(jié)天津博物館門票預約指南_世界球精選 2023-06-05 17:11:40
- 2023端午天津極地海洋公園怎么去?(附交通指南) 2023-06-05 17:11:52
- 環(huán)球新動態(tài):2023端午天津極地海洋公園營業(yè)時間 2023-06-05 17:09:31
- 2023端午天津極地海洋公園門票價格 今日聚焦 2023-06-05 17:03:07
- 2023東莞基層崗位補貼標準|世界即時 2023-06-05 17:22:56
- 環(huán)球觀點:東莞基層崗位補貼政策2023 2023-06-05 17:26:19
- 東莞基層崗位補貼和就業(yè)補貼的區(qū)別-每日時訊 2023-06-05 17:14:06