Skip to content

Commit d27db51

Browse files
committed
重新设计测试框架实现的方式,将每个测试检查/断言改为分组测试;将内部需要的函数由依赖链接调用函数使用改为通过函数指针转递回调函数的方式;增加指定换行符的流程
1 parent 6fb99b7 commit d27db51

File tree

6 files changed

+231
-307
lines changed

6 files changed

+231
-307
lines changed

.idea/editor.xml

Lines changed: 0 additions & 243 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

inc/rmdev_test_framework.h

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,53 +17,68 @@ typedef unsigned char rmdev_test_bool_t;
1717
#define RMDEV_TEST_TRUE 1U
1818
#define RMDEV_TEST_FALSE 0U
1919

20-
/**
21-
* rmdev 测试框架 主函数
22-
* @attention 需要将其放在真正的 main 函数中调用
23-
*/
24-
void rmdev_test_framework_main(void);
20+
#define RMDEV_TEST_NULL ((void*)0)
2521

2622
/**
27-
* rmdev 测试框架 格式化输出函数
28-
* @attention 这是接口函数,具体实现需要根据平台来编写,即需要在平台的相关文件中实现这个函数的定义。
23+
* rmdev 测试框架 格式化输出回调函数类型
2924
* @param format 格式化字符串
3025
* @param ... 可变参数列表
3126
*/
32-
void rmdev_test_printf(const char* format, ...);
27+
typedef void (*rmdev_test_printfCallback)(const char* format, ...);
28+
29+
/**
30+
* rmdev 测试框架 延时回调函数类型
31+
* @param ms 毫秒数
32+
*/
33+
typedef void (*rmdev_test_delayCallback)(unsigned int ms);
34+
35+
/**
36+
* rmdev 测试框架 测试项回调函数类型
37+
*/
38+
typedef void (*rmdev_test_testItemCallback)(void);
39+
40+
/**
41+
* rmdev 测试框架 主函数
42+
* @attention 需要将其放在真正的 main 函数中调用
43+
*/
44+
void rmdev_test_framework_main(const char* break_char,
45+
rmdev_test_printfCallback printfCallback,
46+
rmdev_test_delayCallback delayCallback,
47+
rmdev_test_testItemCallback testItemCallback);
48+
49+
void rmdev_test_item(const char* name, const char* file, int line);
50+
51+
#define RMDEV_TEST_ITEM(name) rmdev_test_item(name, __FILE__, __LINE__)
3352

3453
/**
3554
* rmdev 测试框架 检查布尔表达式是否正确(测试失败后会继续运行)
3655
* @attention 不建议直接调用这个函数,而是使用宏 RMDEV_TEST_CHECK,因为这个宏可以自动填写文件名与行号
37-
* @param name 测试名称
3856
* @param file 调用函数所在的文件名
3957
* @param line 调用函数所在的行号
4058
* @param result 待检查的布尔表达式
4159
*/
42-
void rmdev_test_check(const char* name, const char* file, int line, rmdev_test_bool_t result);
60+
void rmdev_test_check(const char* file, int line, rmdev_test_bool_t result);
4361

4462
/**
4563
* rmdev 测试框架 检查布尔表达式是否正确(测试失败后会继续运行)
46-
* @param name 测试名称
4764
* @param result 待检查的布尔表达式
4865
*/
49-
#define RMDEV_TEST_CHECK(name, result) rmdev_test_check(name, __FILE__, __LINE__, result)
66+
#define RMDEV_TEST_CHECK(result) rmdev_test_check(__FILE__, __LINE__, result)
5067

5168
/**
5269
* rmdev 测试框架 断言布尔表达式是否正确(测试失败后会停止测试)
5370
* @attention 不建议直接调用这个函数,而是使用宏 RMDEV_TEST_CHECK,因为这个宏可以自动填写文件名与行号
54-
* @param name 测试名称
5571
* @param file 调用函数所在的文件名
5672
* @param line 调用函数所在的行号
5773
* @param result 待检查的布尔表达式
5874
*/
59-
void rmdev_test_assert(const char* name, const char* file, int line, rmdev_test_bool_t result);
75+
void rmdev_test_assert(const char* file, int line, rmdev_test_bool_t result);
6076

6177
/**
6278
* rmdev 测试框架 断言布尔表达式是否正确(测试失败后会停止测试)
63-
* @param name 测试名称
6479
* @param result 待检查的布尔表达式
6580
*/
66-
#define RMDEV_TEST_ASSERT(name, result) rmdev_test_assert(name, __FILE__, __LINE__, result)
81+
#define RMDEV_TEST_ASSERT(result) rmdev_test_assert(__FILE__, __LINE__, result)
6782

6883
#ifdef __cplusplus
6984
}

src/rmdev_test_framework.c

Lines changed: 159 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,46 +7,139 @@
77

88
#include "rmdev_test_framework.h"
99

10-
static int success_count = 0U; ///< 成功计数
11-
static int fail_count = 0U; ///< 失败计数
10+
enum {
11+
RMDEV_TEST_NO_ERROR = 0, ///< 无错误
12+
RMDEV_TEST_NO_BREAK_CHARACTER, ///< 没有设置换行符
13+
RMDEV_TEST_NO_PRINTF_CALLBACK, ///< 没有设置 printf 回调函数
14+
RMDEV_TEST_NO_DELAY_CALLBACK, ///< 没有设置 delay 回调函数
15+
RMDEV_TEST_NO_TEST_ITEM_CALLBACK, ///< 没有设置 test_item 回调函数
16+
RMDEV_TEST_TEST_ITEM_COUNT_ERROR, ///< 测试项计数与成功、错误的项目计数不匹配
17+
RMDEV_TEST_OTHER_ERROR ///< 其他错误
18+
};
1219

13-
/**
14-
* rmdev 测试框架 延时函数
15-
* @attention 这是接口函数,具体实现需要根据平台来编写,即需要在平台的相关文件中实现这个函数的定义。
16-
* @param ms 毫秒数
17-
*/
18-
void rmdev_test_delay(unsigned int ms);
20+
unsigned char rmdev_test_error_code = RMDEV_TEST_NO_ERROR; ///< 测试框架错误码
1921

20-
/**
21-
* rmdev 测试框架 测试项
22-
* @attention 这是接口函数,需要在平台的相关文件中实现这个函数的定义。
23-
*/
24-
void rmdev_test_testItem(void);
22+
static const char* break_character; ///< 换行符
23+
24+
static rmdev_test_printfCallback printfCallback_ = RMDEV_TEST_NULL;
25+
static rmdev_test_delayCallback delayCallback_ = RMDEV_TEST_NULL;
26+
static rmdev_test_testItemCallback testItemCallback_ = RMDEV_TEST_NULL;
27+
28+
static int test_item_total_count = 0U; ///< 测试项计数
29+
static int success_count = 0U; ///< 成功计数
30+
static int fail_count = 0U; ///< 失败计数
31+
32+
static rmdev_test_bool_t in_test_item = RMDEV_TEST_FALSE; ///< 是否在测试项中
33+
34+
static const char* current_test_item_name = ""; ///< 当前测试项名称
35+
static int test_item_index = 0U; ///< 测试项编号
36+
static int test_item_success_count = 0U; ///< 单个测试项成功计数
37+
static int test_item_fail_count = 0U; ///< 单个测试项失败计数
2538

2639
static void rmdev_test_finish(void);
40+
static void rmdev_test_item_finish(const char* name);
41+
42+
/// 打印行分割线
43+
#define PRINTF_LINE(void) printfCallback_("==================================================%s", break_character)
44+
45+
/// 打印单行分割线
46+
#define PRINTF_SINGLE_LINE(void) \
47+
printfCallback_("--------------------------------------------------%s", break_character)
48+
49+
/// 结束的死循环
50+
#define END_LOOP(void) \
51+
do { \
52+
} while (RMDEV_TEST_TRUE)
53+
54+
static void rmdev_test_item_finish(const char* name)
55+
{
56+
in_test_item = RMDEV_TEST_FALSE;
57+
58+
if (test_item_index != test_item_success_count + test_item_fail_count) {
59+
printfCallback_(
60+
"rmdev_test_framework Fatal error: Test item count (%d) does not match success (%d) and fail (%d) "
61+
"counts!%s",
62+
test_item_index,
63+
test_item_success_count,
64+
test_item_fail_count,
65+
break_character);
66+
67+
rmdev_test_error_code = RMDEV_TEST_TEST_ITEM_COUNT_ERROR;
68+
END_LOOP();
69+
}
70+
71+
PRINTF_SINGLE_LINE();
72+
printfCallback_(" Test item \"%s\" finished.%s", name, break_character);
73+
printfCallback_(" %d test(s) succeeded, %d test(s) failed.%s",
74+
test_item_success_count,
75+
test_item_fail_count,
76+
break_character);
77+
PRINTF_SINGLE_LINE();
78+
}
79+
80+
void rmdev_test_item(const char* name, const char* file, const int line)
81+
{
82+
if (!in_test_item) {
83+
in_test_item = RMDEV_TEST_TRUE;
84+
test_item_index = 0U;
85+
test_item_success_count = 0U;
86+
test_item_fail_count = 0U;
87+
current_test_item_name = name;
88+
89+
PRINTF_LINE();
90+
printfCallback_(" Test item \"%s\" started.%s", name, break_character);
91+
printfCallback_(" (In file %s:%d)%s", file, line, break_character);
92+
PRINTF_LINE();
93+
}
94+
else {
95+
rmdev_test_item_finish(current_test_item_name);
96+
rmdev_test_item(name, file, line);
97+
}
98+
}
2799

28-
void rmdev_test_check(const char* name, const char* file, const int line, const rmdev_test_bool_t result)
100+
void rmdev_test_check(const char* file, const int line, const rmdev_test_bool_t result)
29101
{
102+
if (!in_test_item) {
103+
printfCallback_("Error: Test check called without a test item started!%s", break_character);
104+
END_LOOP();
105+
}
106+
107+
++test_item_total_count;
108+
++test_item_index;
109+
30110
if (result) {
31-
rmdev_test_printf("Test %s passed.\r\n", name);
111+
printfCallback_("No.%d passed.%s", test_item_index, break_character);
32112
++success_count;
113+
++test_item_success_count;
33114
}
34115
else {
35-
rmdev_test_printf("Test %s failed at %s:%d.\r\n", name, file, line);
116+
printfCallback_("No.%d check failed at %s:%d.%s", test_item_index, file, line, break_character);
36117
++fail_count;
118+
++test_item_fail_count;
37119
}
38120
}
39121

40-
void rmdev_test_assert(const char* name, const char* file, const int line, const rmdev_test_bool_t result)
122+
void rmdev_test_assert(const char* file, const int line, const rmdev_test_bool_t result)
41123
{
124+
if (!in_test_item) {
125+
printfCallback_("Error: Test assert called without a test item started!%s", break_character);
126+
END_LOOP();
127+
}
128+
129+
++test_item_total_count;
130+
++test_item_index;
131+
42132
if (result) {
43-
rmdev_test_printf("Assert %s passed.\r\n", name);
133+
printfCallback_("No.%d passed.%s", test_item_index, break_character);
44134
++success_count;
135+
++test_item_success_count;
45136
}
46137
else {
47-
rmdev_test_printf("Assert %s failed at %s:%d.\r\nTest failed!\r\n", name, file, line);
138+
printfCallback_("No.%d assert failed at %s:%d.%s", test_item_index, file, line, break_character);
48139
++fail_count;
140+
++test_item_fail_count;
49141

142+
rmdev_test_item_finish(current_test_item_name);
50143
rmdev_test_finish();
51144
}
52145
}
@@ -56,16 +149,57 @@ void rmdev_test_assert(const char* name, const char* file, const int line, const
56149
*/
57150
static void rmdev_test_finish(void)
58151
{
59-
rmdev_test_printf("\r\nTest Finished.\r\n\r\n %d Test(s) Succeeded, %d Test(s) Failed.\r\n",
60-
success_count,
61-
fail_count);
62-
while (RMDEV_TEST_TRUE) {
152+
if (success_count + fail_count == test_item_total_count) {
153+
printfCallback_("\r\nTest Finished.\r\n\r\n %d Test(s) Succeeded, %d Test(s) Failed.\r\n",
154+
success_count,
155+
fail_count);
63156
}
157+
else {
158+
rmdev_test_error_code = RMDEV_TEST_TEST_ITEM_COUNT_ERROR;
159+
160+
printfCallback_(
161+
"rmdev_test_framework Fatal error: Test item count (%d) does not match success (%d) and fail (%d) "
162+
"counts!%s",
163+
test_item_total_count,
164+
success_count,
165+
fail_count,
166+
break_character);
167+
}
168+
169+
END_LOOP();
64170
}
65171

66-
void rmdev_test_framework_main(void)
172+
void rmdev_test_framework_main(const char* break_char,
173+
const rmdev_test_printfCallback printfCallback,
174+
const rmdev_test_delayCallback delayCallback,
175+
const rmdev_test_testItemCallback testItemCallback)
67176
{
68-
rmdev_test_testItem();
177+
break_character = break_char;
178+
179+
printfCallback_ = printfCallback;
180+
delayCallback_ = delayCallback;
181+
testItemCallback_ = testItemCallback;
182+
183+
if (break_character == RMDEV_TEST_NULL) {
184+
rmdev_test_error_code = RMDEV_TEST_NO_BREAK_CHARACTER;
185+
END_LOOP();
186+
}
187+
if (printfCallback_ == RMDEV_TEST_NULL) {
188+
rmdev_test_error_code = RMDEV_TEST_NO_PRINTF_CALLBACK;
189+
END_LOOP();
190+
}
191+
if (delayCallback_ == RMDEV_TEST_NULL) {
192+
rmdev_test_error_code = RMDEV_TEST_NO_DELAY_CALLBACK;
193+
printfCallback_("rmdev_test_framework Fatal error: No delay callback function set!%s", break_character);
194+
END_LOOP();
195+
}
196+
if (testItemCallback_ == RMDEV_TEST_NULL) {
197+
rmdev_test_error_code = RMDEV_TEST_NO_TEST_ITEM_CALLBACK;
198+
printfCallback_("rmdev_test_framework Fatal error: No test item callback function set!%s", break_character);
199+
END_LOOP();
200+
}
201+
202+
testItemCallback_();
69203

70204
rmdev_test_finish();
71205
}

test/main.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,36 @@
77

88
#include "rmdev_test_framework.h"
99

10+
#include <stdbool.h>
11+
12+
#include "test_function_impl.h"
13+
14+
void my_testItem(void)
15+
{
16+
RMDEV_TEST_ITEM("Constant Test");
17+
RMDEV_TEST_CHECK(true);
18+
RMDEV_TEST_CHECK(false);
19+
20+
RMDEV_TEST_ITEM("Calculate Test");
21+
RMDEV_TEST_CHECK((1 + 1) == 2);
22+
RMDEV_TEST_CHECK((2 * 2) == 4);
23+
RMDEV_TEST_CHECK((3 - 1) == 2);
24+
25+
RMDEV_TEST_CHECK((1 + 1) == 3); // false
26+
27+
RMDEV_TEST_CHECK((114514 + 1919810) == 2034324);
28+
RMDEV_TEST_ASSERT(-1 - 2 == -3);
29+
30+
RMDEV_TEST_ITEM("Assert Test");
31+
RMDEV_TEST_ASSERT(true);
32+
RMDEV_TEST_ASSERT(false);
33+
34+
RMDEV_TEST_CHECK(true);
35+
}
36+
1037
int main(void)
1138
{
12-
rmdev_test_framework_main();
39+
rmdev_test_framework_main("\n", my_printf, my_delay, my_testItem);
1340

1441
return 0;
1542
}

test/test_function_impl.c

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,13 @@
88
#include <stdio.h>
99
#include <stdarg.h>
1010
#include <unistd.h> // For sleep function
11-
#include <stdbool.h>
1211

13-
#include "rmdev_test_framework.h"
14-
15-
void rmdev_test_testItem(void)
16-
{
17-
RMDEV_TEST_CHECK("true", true);
18-
RMDEV_TEST_CHECK("false", false);
19-
20-
RMDEV_TEST_CHECK("1 + 1", (1 + 1) == 2);
21-
RMDEV_TEST_CHECK("2 * 2", (2 * 2) == 4);
22-
RMDEV_TEST_CHECK("3 - 1", (3 - 1) == 2);
23-
24-
RMDEV_TEST_CHECK("1 + 1 == 3", (1 + 1) == 3);
25-
26-
RMDEV_TEST_ASSERT("true 1", true);
27-
//RMDEV_TEST_ASSERT("false", false);
28-
29-
RMDEV_TEST_CHECK("true 2", true);
30-
}
31-
32-
void rmdev_test_delay(const unsigned int ms)
12+
void my_delay(const unsigned int ms)
3313
{
3414
sleep(ms);
3515
}
3616

37-
void rmdev_test_printf(const char* format, ...)
17+
void my_printf(const char* format, ...)
3818
{
3919
va_list args;
4020
va_start(args, format);

test/test_function_impl.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* @file test_function_impl.c
3+
* @author 杜以成
4+
* @date 2025-06-03
5+
* @brief 测试框架所需要的函数的实现
6+
*/
7+
8+
#pragma once
9+
10+
void my_delay(unsigned int ms);
11+
void my_printf(const char* format, ...);

0 commit comments

Comments
 (0)