人人都能学会的编程入门课
胡光
原百度高级算法研发工程师
19410 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 38 讲
开篇词 (1讲)
人人都能学会的编程入门课
15
15
1.0x
00:00/00:00
登录|注册

27 | 牛刀小试(下):实现一个自己的测试框架

你好,我是胡光,欢迎回来,今天呢,我们继续学习测试框架的相关内容。
上节课中,我们讲到了软件开发一般分为前中后三个部分,提到作为技术人员的我们,一般主要负责在软件开发中期的编码与测试阶段。还有,我还讲到我们一般会综合运用白盒测试与黑盒测试这两种方法来进行程序测试。
更主要的是,我们还介绍了 Google 的单元测试框架 gtest,并对测试框架代码进行了一番解读。其中提到代码中的 TEST 是一个宏,那它展开后被替换的内容是什么呢?还有, RUN_ALL_TESTS 函数是如何依次执行程序中所有的测试用例函数的?
今天呢,我们就一个一个地来解决这些问题,并最终实现一个咱们自己的测试框架。

初步实现 TEST 宏

今天我们实现的所有代码呢,都会写在一个名字为 geek_test.h 的头文件中。当然我们也知道,将声明和定义写在一起,在大型工程中是会出现严重的编译错误,在实际的工程开发中,我们并不会这么做。
今天把声明和定义写在一起,只是为了课程内容的讲解需要,而你也完全没有必要担心,这不会影响你对主要内容的学习。
我们先回到上节课中的源代码:
#include <stdio.h>
#include "geek_test.h" // 替换掉原 gtest/gtest.h 头文件
// 判断一个数字 x 是否是素数
int is_prime(int x) {
for (int i = 2; i * i < x; i++) {
if (x % i == 0) return 0;
}
return 1;
}
// 第一个测试用例
TEST(test1, test_is_prime) {
EXPECT_EQ(is_prime(3), 1);
EXPECT_EQ(is_prime(5), 1);
EXPECT_EQ(is_prime(7), 1);
}
// 第二个测试用例
TEST(test2, test_is_prime) {
EXPECT_EQ(is_prime(4), 0);
EXPECT_EQ(is_prime(0), 0);
EXPECT_EQ(is_prime(1), 0);
}
int main() {
return RUN_ALL_TESTS();
}
我们的目的,是在不改变这份源代码的前提下,通过在 geek_test.h 中添加一些源码,使得这份代码的运行效果,能够类似于 gtest 的运行效果。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文介绍了如何实现一个自己的测试框架,通过讲解 TEST 宏的实现、`__attribute__`的使用和 RUN_ALL_TESTS 函数的设计,帮助读者了解了测试框架的基本原理和实现方法。作者首先讲解了如何初步实现 TEST 宏,通过预处理器展开,将 TEST 宏的两个参数内容连接在一起,形成一个函数名,从而将原来的 TEST 宏转换成合法的 C 语言代码。接着,作者介绍了`__attribute__`的使用,通过`__attribute__((constructor))`可以让函数在主函数执行之前就执行,这为后续的操作提供了便利。然后,文章讲解了 RUN_ALL_TESTS 函数的设计,通过注册函数将测试用例函数的函数地址存储到一个函数指针数组中,然后在 RUN_ALL_TESTS 函数中依次执行这些函数,实现了测试用例的执行。文章还提到了`__attribute__`((constructor)) 可以修饰函数,使修饰的函数先于主函数执行,以及通过测试框架这个项目,宏可以将原本看似不合理的代码变得合理。通过这两次课程,读者可以意识到,不是在阅读已有的测试框架的源码,而是在根据已有的测试框架,脑补其内部实现过程。这篇文章对于想要了解测试框架的基本原理和实现方法的读者来说是一篇很有价值的文章。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《人人都能学会的编程入门课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(4)

  • 最新
  • 精选
  • 🤪HappyJoo
    老师,自己乱写真的好多奇奇怪怪的问题呀,能不能给个每章节的源代码参考一下呢?我根据章节内容拼凑起来的代码,太多问题了,都不知道该从哪里开始问起了(ಥ_ಥ) ,总不能次次都把我的源码丢出来问你哈哈哈哈。有些问题真的搜了两三个小时才可能侥幸找到解决方法,如果老师能给分参考,可能可以减少一些不必要的时间呢~

    作者回复: 哈哈哈哈,完全理解你现在的处境。可这些时间不是没有必要的,是有必要的。如果我给出零碎的代码片段,你没办法完成组装,那肯定是有问题的。当然,直接给出代码参考是最直接的,可那样,你不还是不能发现自己的问题么。所以,要是实在找不到错误了,可以把你的问题发上来,我再帮你找。

    2020-03-24
    3
    2
  • 刘桢
    打卡打卡

    作者回复: 划水~~~

    2020-03-22
  • 罗耀龙@坐忘
    茶艺师学编程 思考题 关于EXPECT_EQ,我想至少 1、运行带入自变量的is_prime,得出对应的因变量; 2、得出的因变量与输入的值比较是否相等。如果相等,输出“ok”,不相等,输出“FAILED”、“函数名+结果”、“输入的数值” 以下是我的脑补: EXPECT_EQ(func, val1, val2){ int val3 = 0; val3 = func(val1); if(val3 == val2)printf(“OK”); else printf(“FAILED\nfunc(val1) = %d”, val3); } 如果写成宏的话 #define EXPECT_EQ(func(val),val2 )\ void EXPECT_EQ(func, val, val2){ \ int val3;\ val3 = func(val);\ if(val3 == val2)printf(“OK”);\ else printf(“FAILED\nfunc(val1) = %d”, val3);\ }\
    2020-10-30
  • 罗耀龙@坐忘
    茶艺师学编程 来到这里,老师双手一张: "诸位,我们一起放弃做人吧,哈哈哈哈哈哈" 一堆没见过的代码如暴雨般倾泻而来,瞬间淹没众人。 雷声,雨声、风声,如同老师的大笑。
    2020-10-22
收起评论
显示
设置
留言
4
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部