下面我们来看看两个主要函数。
1. abts_add_suite
/* Only end the suite if we actually ran it */ if (suite && suite->tail &&!suite->tail->not_run) { end_suite(suite); } |
怎么函数刚一开始就要结束掉suite?(end_suite其实是打印suite是否通过测试)仔细分析后才知道,这一句不是要结束自己,而是要结束上一个suite。再回过头来看看主函数中的代码就会明白了。
abts_suite* suite = NULL; for (i = 0; i < (sizeof(alltests) / sizeof(struct testlist *)); i++) { suite = alltests[i].func(suite); } |
让我们一步步的分析:
① 开始suite = NULL; 第一次当然就不会执行end_suite了,因为这时根本没有前一个suite可以结束掉。
② 第二次进入循环时,就会调用end_suite了,因为这是suite是第一次执行测试后的返回值,suite != NULL。
③ 依次类推可以得出end_suite实际上是打印前一个测试的结果。这种设计比较的精巧。
再往下看代码,创建一个subsuite,给这个suite一个名字,这个名字是suite所在的文件的文件名去掉后缀。然后再将其加入到链表中。
2. abts_run_test
这个函数就是调用具体的测试用例函数。测试用例函数是对一个基本功能的测试,它主要使用断言集。
首先取最后一个suite
ss = ts->tail;
即当前正在测试的suite。
然后初始化test_case。并将suite中的测试用例数递增。
tc.failed = 0; tc.suite = ss; ss->num_test++; |
最后调用实际的测试用例函数,将用例是否失败的信息放入到tc中。更新suite的测试用例失败数。
f(&tc, value); if (tc.failed) { ss->failed++; } |
很简单,我在这里分析好像是没必要的了。我感叹写abts作者的智慧。
推荐阅读: