-
Notifications
You must be signed in to change notification settings - Fork 7
lcut用户指南
lcut 是Lightweight C Unit Test framework的缩写,它使用标准C语言实现,可以很容易的在不同额主流平台上使用,如Solaris、Linux等。
一个使用lcut进行的单元测试有三个层次:一个逻辑测试、测试套件和测试用例。每个逻辑测试可以包含多个测试套件,且每个测试套件又包含多个测试用例。在lcut这个测试框架中,测试用例是最基本和最小的单元。
实际上,lcut中的测试用例是原型为
void (*tc_func)(lcut_tc_t *tc, void *data)的函数。lcut使用 LCUT_TC_ADD 宏向一个测试套件中添加一个测试用例,测试套件使用 LCUT_TS_INIT 宏初始化。每个使用lcut进行的单元测试开始于 LCUT_TEST_BEGIN,结束于 LCUT_TEST_END 。另外 LCUT_TEST_RESULT宏可用于将执行结果反馈给本次测试的调用者(例如一些持续集成脚本等)。
#include "lcut.h" /* * A case that test nothing */ void tc_trivial_test(lcut_tc_t *tc, void *data) { } int main() { lcut_ts_t *suite = NULL; LCUT_TEST_BEGIN("A Trivial test", NULL, NULL); LCUT_TS_INIT(suite, "A Trivial test suite", NULL, NULL); LCUT_TC_ADD(suite, "A Trivial test case", tc_trivial_test, NULL, NULL, NULL); LCUT_TS_ADD(suite); LCUT_TEST_RUN(); LCUT_TEST_REPORT(); LCUT_TEST_END(); LCUT_TEST_RESULT(); }
上面测试输出结果如下:
********************************************************* LCUT -- Lightweight C Unit Testing framework By Tony Bai ********************************************************* Unit Test for 'A Trivial test': Suite <A Trivial test suite>: Case 'A Trivial test case': Passed Summary: Total Suites: 1 Failed Suites: 0 Total Cases: 1 Failed Cases: 0 ========================== GREEN BAR! ==========================
如果所有测试用例都通过,则你的控制台上会输出一个绿色的"GREEN BAR!",否则红色的"RED BAR!"将被呈现出来,并且伴随着失败用例的原因,例如:
Unit Test for 'A Trivial test': Suite <A Trivial test suite>: Case 'A Trivial test case': Failure occur in tc_null_test, 23 line in file runtests.c, expected<1> : actual<2> Summary: Total Suites: 1 Failed Suites: 0 Total Cases: 1 Failed Cases: 0 ========================== RED BAR! ==========================
lcut提供了许多断言宏:
* LCUT_INT_EQUAL(tc, expected, actual) * LCUT_INT_NEQUAL(tc, expected, actual) * LCUT_STR_EQUAL(tc, expected, actual) * LCUT_STR_NEQUAL(tc, expected, actual) * LCUT_ASSERT(tc, msg, condition) * LCUT_TRUE(tc, condition)
断言宏的使用方法显而易见,这里不赘述。
lcut支持mock,mock是一种重要的将你的单元测试与外部依赖隔离的方法。 LCUT_MOCK_RETV 和 LCUT_MOCK_ARG 分别用例mock函数的返回值和输出参数。
Mocked函数 'table_row_count' 实现如下:
int table_row_count(const database_conn *conn, const char *table_name, int *total_count) { (*total_count) = (int)LCUT_MOCK_ARG(); return (int)LCUT_MOCK_RETV(); } <pre> 依赖'table_row_count'的测试用例可以使用被mocked的'table_row_count'函数,并且可通过 LCUT_RETV_RETURN 和 LCUT_ARG_RETURN 宏来自由控制被mocked的'table_row_count'的返回值和输出参数的值。 <pre> LCUT_ARG_RETURN(table_row_count, 5); /* the total_count will be 5 after invoking the mocked table_row_count */ LCUT_RETV_RETURN(table_row_count, 0); /* the return value of mocked table_row_count will be 0 */
lcut还提供了两个宏 LCUT_ARG_RETURN_COUNT 和 LCUT_RETV_RETURN_COUNT ,用于被测试接口多次调用mocked接口的情况:
例如: int bar(int *outparameter) { ... foo(); ... foo(); ... foo(); }
如果要对bar进行测试,我们需要对foo进行mock,由于bar调用了三次foo,使用常规接口我们需要调用三次 LCUT_RETV_RETURN 和 LCUT_ARG_RETURN 对mocked foo进行相关设置,这里若使用 LCUT_ARG_RETURN_COUNT 和 LCUT_RETV_RETURN_COUNT 则只需调用一次,例如:
/* in some test case */ LCUT_RETV_RETURN_COUNT(foo, 13, 3); LCUT_ARG_RETURN_COUNT(foo, 17, 3);
如果希望某个被mocked的函数一直返回某个相同的值,可以将最后一个参数count设置为-1传入,例如:
LCUT_RETV_RETURN_COUNT(foo, 13, -1);/* make foo always return 13 */ LCUT_ARG_RETURN_COUNT(foo, 17, -1); /* make foo's outparameter always evaluated to 17 */
这样无论调用几次foo,其返回值都为13,其输出参数都为17。
跟过关于mock支持的细节可参考lcut包中example目录下的例子。
注意 : lcut不支持mock类型为double的函数返回值或参数。