(八)白盒测试实例--构建自己的单元测试框架1

在上一讲“单元测试的尝试”里我们遇到了几个问题:

1、代码重复的问题太多

2、测试结果需要人工去检查

3、对测试的总体信息也无从得知

本讲将构建一个简单的单元测试框架来解决以上的问题:

1、代码重复的问题太多。

这个问题很容易解决,只需要把判断预期结果和实际结果的逻辑提取到某个函数中即可。从整个代码来看,有两种类型的结果的函数:

(1)返回布尔型

(2)返回整数

因此,需要两个类型的判断预期结果和实际结果是否相符的函数:XUnit系列的框架的习惯使用assert*的命名来定义判断函数,对于通过的测试习惯打印一个“.”号,而对于失败的测试习惯打印一个“F”。 

  1. /*
  2.  * 判断是否取值为真
  3.  */
  4. void assertTrue(char *msg, bool actual)
  5. {
  6.     if(actual)
  7.     {
  8.         printf(".");
  9.     }
  10.     else
  11.     {
  12.         printf("F");
  13.     }
  14. }
  15. /*
  16.  * 判断预期结果和实际结果是否相符
  17.  */
  18. void assertEquals(char *msg, int expect, int actual)
  19. {
  20.     if(expect == actual)
  21.     {
  22.         printf(".");
  23.     }
  24.     else
  25.     {
  26.         printf("F");
  27.     }
  28. }

小知识:

2、测试结果需要人工去检查

    对于测试结果不要使用printf方式打印被测试函数的返回结果值就可以避免这个问题。

3、对测试的总体信息也无从得知

除了问题1的解决办法里使用“.”表示测试通过和“F”表示测试失败可以提高对测试结果的信息的直观性之外,做单元测试的人还希望能够得到以下的信息:

(1)执行的测试用例总数、通过的数量和失败的数量

(2)测试执行的时间

(3)如果测试用例执行失败了,希望知道是哪个测试用例失败,从而去分析失败的原因。

下面来实现以上三个目标:

1、  为了获取已执行的测试用例数量、通过的数量和失败的数量,以及测试执行的时间,需要定义一些变量来保存这些信息:

  1. int errorCount = 0;
  2. int testCount=0;
  3. time_t startTime, endTime;

2、为了获取失败的测试用例信息,需要先定义一个变量来保存错误信息,同时,上面的两个断言函数也需要增加一个参数,用来传递当失败的时候要显示的失败信息。为了方便记录错误的信息,可以添加两个处理错误信息的函数:

  1. /*
  2.  * 存放测试信息和错误信息的全局变量
  3.  */
  4. char *errors[100] = {""};
  5. int errorCount = 0;
  6. int testCount=0;
  7. time_t startTime, endTime;
  8. /*
  9.  * 判断是否取值为真
  10.  */
  11. void assertTrue(char *msg, bool actual)
  12. {
  13.     testCount++;
  14.     if(actual)
  15.     {
  16.         printf(".");
  17.     }
  18.     else
  19.     {
  20.         printf("F");
  21.         addError(msg);
  22.     }
  23. }
  24. /*
  25.  * 判断预期结果和实际结果是否相符
  26.  */
  27. void assertEquals(char *msg, int expect, int actual)
  28. {
  29.     testCount++;
  30.     if(expect == actual)
  31.     {
  32.         printf(".");
  33.     }
  34.     else
  35.     {
  36.         printf("F");
  37.         addError(msg, expect, actual);
  38.     }
  39. }

失败信息的处理函数:

  1. /*
  2.  * 添加错误信息
  3.  */
  4. void addError(char *msg)
  5. {
  6.     char error[100] = "Test '";
  7.     strcat(error, msg);
  8.     strcat(error, "' is failed!");
  9.     errors[errorCount] = new char[100];
  10.     strcpy(errors[errorCount], error);
  11.     errorCount ++;
  12. }
  13. /*
  14.  * 添加错误信息,带预期结果与实际结果参数
  15.  */
  16. void addError(char *msg, int expect, int actual)
  17. {
  18.     char error[100] = "Test '";
  19.     char num[10];
  20.     strcat(error, msg);
  21.     strcat(error, "' is failed!");
  22.     strcat(error, " Expected: ");
  23.     strcat(error, itoa(expect, num, 10));
  24.     strcat(error, " , actual: ");
  25.     strcat(error, itoa(actual, num, 10));
  26.     errors[errorCount] = new char[100];
  27.     strcpy(errors[errorCount], error);
  28.     errorCount ++;
  29. }

3、计算测试所花费的时间:

在测试开始之前开始计时,测试结束之后,停止计时。

  1. /*
  2.  * 初始化测试,开始计时
  3.  */
  4. void init()
  5. {
  6.     printf("\n****** Test start ******\n");
  7.     startTime = clock();
  8. }
  9. /*
  10.  * 结束测试,结束计时,打印报告
  11.  */
  12. void end()
  13. {
  14.     endTime = clock();
  15. }

4、测试结束之后,把收集到的信息打印出来:

  1. /*
  2.  * 测试报告
  3.  */
  4. void testReport()
  5. {
  6.     printf("\n\nTotal run Tests:");  //测试概要信息
  7.     printf("%d", testCount);
  8.     printf(", passed:%d", testCount-errorCount);
  9.     printf(", failed:%d\n", errorCount);
  10.     printf("Test escaped time: %6.3f seconds\n", (double)(endTime-startTime)/1000.0);
  11.     if(errorCount>0)   //测试失败的详细信息
  12.     {
  13.         printf("\n**************** Failed Test's Detail ****************\n\n");
  14.         
  15.         for(int i=0; i<errorCount; i++)
  16.         {
  17.             printf("  %d: ", i+1);
  18.             printf(errors[i]);
  19.             printf("\n");
  20.         }
  21.         printf("\n**************** End of Failed Detail ****************\n\n");
  22.     }
  23.     else   //所有测试都通过
  24.     {
  25.         printf("\n****** All Tests had Passed! ******\n\n");
  26.     }
  27. }

把这个函数放在end函数中调用:

  1. /*
  2.  * 结束测试,结束计时,打印报告
  3.  */
  4. void end()
  5. {
  6.     endTime = clock();
  7.     testReport();
  8. }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值