单元测试究竟是该开发来做还是测试?

2018 年 8 月 17 日 InfoQ

不少公司有单元测试的需求,但单元测试到底谁来做,每个公司都不一样。

1 开发写单测

优:开发对代码最熟悉,而且开发技能也强,开发自己写单元测试效率上和覆盖率上都比较高。而且单元测试有时候需要开发对代码进行部分重构才方便进行,开发自己做这些重构也比较顺手。

缺:开发平时写业务代码就忙不过来了,哪有时间写单元测试?而且大部分开发没有太好的测试思想,单元测试可能只是写个最简单的用例就完了,最终可能单元测试通过,但基本的功能还是有问题,这样的单测没有太大作用。

2 测试写单测

优:测试有比较好的测试思想,可以更好地保证用例的覆盖。而且通过写单测测试能更好地了解具体代码结构、流程,对于后续的业务测试也有利。

缺:有比较好代码能力的测试人员不多,而且测试对代码没有开发熟悉,遇上为了可测性需要重构的时候还是得开发花时间配合。效率上不如开发自己写。

3 无论谁来做,那到底怎样才能做好单元测试?

如果你没有开发背景,感觉这篇文章理解起来有难度,那你可以在学完后续的“代码级测试”系列的文章后,再回过头来看一遍这篇文章,相信你会有醍醐灌顶的感觉。

什么是单元测试?

如果把电视机的生产、测试和软件的开发、测试进行类比,你可以发现:

  • 电子元器件就像是软件中的单元,通常是函数或者类,对单个元器件的测试就像是软件测试中的单元测试;

  • 组装完成的功能电路板就像是软件中的模块,对电路板的测试就像是软件中的集成测试;

  • 电视机全部组装完成就像是软件完成了预发布版本,电视机全部组装完成后的开机测试就像是软件中的系统测试。

通过这个类比,相信你已经体会到了单元测试对于软件整体质量的重要性,那么单元测试到底是什么呢?

单元测试是指,对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作,这里的最小可测试单元通常是指函数或者类。

单元测试通常由开发工程师完成,一般会伴随开发代码一起递交至代码库。单元测试属于最严格的软件测试手段,是最接近代码底层实现的验证手段,可以在软件开发的早期以最小的成本保证局部代码的质量。

另外,单元测试都是以自动化的方式执行,所以在大量回归测试的场景下更能带来高收益。

同时,你还会发现,单元测试的实施过程还可以帮助开发工程师改善代码的设计与实现,并能在单元测试代码里提供函数的使用示例,因为单元测试的具体表现形式就是对函数以各种不同输入参数组合进行调用,这些调用方法构成了函数的使用说明。

如何做好单元测试?

要做好单元测试,你首先必须弄清楚单元测试的对象是代码,以及代码的基本特征和产生错误的原因,然后你必须掌握单元测试的基本方法和主要技术手段,比如什么是驱动代码、桩代码和 Mock 代码等。

代码的基本特征与产生错误的原因

开发语言多种多样,程序实现的功能更是千变万化,我可以提炼出代码的基本特征,并总结出代码缺陷的主要原因么?答案是肯定,你静下心来思考时,会发现其中是有规律可寻的。

因为无论是开发语言还是脚本语言,都会有条件分支、循环处理和函数调用等最基本的逻辑控制,如果抛开代码需要实现的具体业务逻辑,仅看代码结构的话,你会发现所有的代码都是在对数据进行分类处理,每一次条件判定都是一次分类处理,嵌套的条件判定或者循环执行,也是在做分类处理。

如果有任何一个分类遗漏,都会产生缺陷;如果有任何一个分类错误,也会产生缺陷;如果分类正确也没有遗漏,但是分类时的处理逻辑错误,也同样会产生缺陷。

可见,要做到代码功能逻辑正确,必须做到分类正确并且完备无遗漏,同时每个分类的处理逻辑必须正确。

在具体的工程实践中,开发工程师为了设计并实现逻辑功能正确的代码,通常会有如下的考虑过程:

  1. 如果要实现正确的功能逻辑,会有哪几种正常的输入;

  2. 是否有需要特殊处理的多种边界输入;

  3. 各种潜在非法输入的可能性以及如何处理。

讲到这里,你有没有回想起我跟你分享的“等价类”。没错,这些开发工程师眼中的代码“功能点”,就是单元测试的“等价类”。

单元测试用例详解

在实际工作中,你想做好单元测试,就必须对单元测试的用例设计有深入的理解。

通常来讲,单元测试的用例是一个“输入数据”和“预计输出”的集合。你需要针对确定的输入,根据逻辑功能推算出预期正确的输出,并且以执行被测试代码的方式进行验证,用一句话概括就是“在明确了代码需要实现的逻辑功能的基础上,什么输入,应该产生什么输出”。

但是,对于单元测试来讲,测试用例的“输入数据”和“预计输出”可能远比你想得要复杂得多。

首先,让我来解释一下单元测试用例“输入数据”都有哪些种类,如果你想当然的认为只有被测试函数的输入参数是“输入数据”的话,那就大错特错了。这里我总结了几种“输入数据”,希望可以帮助你理解什么才是完整的单元测试“输入数据”:

  • 被测试函数的输入参数;

  • 被测试函数内部需要读取的全局静态变量;

  • 被测试函数内部需要读取的成员变量;

  • 函数内部调用子函数获得的数据;

  • 函数内部调用子函数改写的数据;

  • 嵌入式系统中,在中断调用时改写的数据;

后续,这篇文章的作者茹炳晟老师也深入分析了“预计输出”的几大分类,驱动代码,桩代码和 Mock 代码三者之间的异同点及不同功能,真的值得一读。但由于篇幅的限制,我就不分享太多了,大家可以扫描下方的二维码进入专栏,可试读《软件测试 52 讲》的前三篇文章。即使不购买,前三篇文章也值得你去看一看。

驱动代码,桩代码和 Mock 代码三者的逻辑关系

4 今日福利
  1. 即日起至 8 月 18 日 24 点:《软件测试 52 讲》限时团购优惠价 79 元 / 人(原价 99 元),扫描下图二维码或点击阅读原文

  2. 订阅专栏后,每邀请一位好友订阅专栏,立享 24 元返现,上不封顶, 极客时间 App/ 服务号立即提现。

79 元,52 篇好文,点击“阅读原文”,支持原创,支持极客时间上值得一看的专栏。

赶紧了,这福利只有 2 天了

登录查看更多
0

相关内容

【实用书】学习用Python编写代码进行数据分析,103页pdf
专知会员服务
194+阅读 · 2020年6月29日
【2020新书】使用高级C# 提升你的编程技能,412页pdf
专知会员服务
57+阅读 · 2020年6月26日
Python导论,476页pdf,现代Python计算
专知会员服务
260+阅读 · 2020年5月17日
【2020新书】如何认真写好的代码和软件,318页pdf
专知会员服务
63+阅读 · 2020年3月26日
《代码整洁之道》:5大基本要点
专知会员服务
49+阅读 · 2020年3月3日
【书籍推荐】简洁的Python编程(Clean Python),附274页pdf
专知会员服务
180+阅读 · 2020年1月1日
无人驾驶仿真软件
智能交通技术
21+阅读 · 2019年5月9日
每个架构师都应该培养业务思维
InfoQ
3+阅读 · 2019年4月21日
企业数据AI化战略:从数据中台到AI中台
36大数据
11+阅读 · 2019年2月18日
年薪48万的程序员,他究竟做对了什么?
机器学习算法与Python学习
7+阅读 · 2018年12月28日
重磅 | 带学斯坦福CS231n计算机视觉课+带打全球顶级kaggle大赛
Arxiv
102+阅读 · 2020年3月4日
Arxiv
92+阅读 · 2020年2月28日
Arxiv
17+阅读 · 2018年4月2日
Arxiv
7+阅读 · 2018年3月19日
VIP会员
相关VIP内容
【实用书】学习用Python编写代码进行数据分析,103页pdf
专知会员服务
194+阅读 · 2020年6月29日
【2020新书】使用高级C# 提升你的编程技能,412页pdf
专知会员服务
57+阅读 · 2020年6月26日
Python导论,476页pdf,现代Python计算
专知会员服务
260+阅读 · 2020年5月17日
【2020新书】如何认真写好的代码和软件,318页pdf
专知会员服务
63+阅读 · 2020年3月26日
《代码整洁之道》:5大基本要点
专知会员服务
49+阅读 · 2020年3月3日
【书籍推荐】简洁的Python编程(Clean Python),附274页pdf
专知会员服务
180+阅读 · 2020年1月1日
相关资讯
无人驾驶仿真软件
智能交通技术
21+阅读 · 2019年5月9日
每个架构师都应该培养业务思维
InfoQ
3+阅读 · 2019年4月21日
企业数据AI化战略:从数据中台到AI中台
36大数据
11+阅读 · 2019年2月18日
年薪48万的程序员,他究竟做对了什么?
机器学习算法与Python学习
7+阅读 · 2018年12月28日
重磅 | 带学斯坦福CS231n计算机视觉课+带打全球顶级kaggle大赛
Top
微信扫码咨询专知VIP会员