“测试金字塔”(一):为单元测试“正名”

一. 单元测试的“理由”

我曾经认为单元测试是针对功能的。任何超出功能的测试都不是单元测试。

实际上,“单位”的定义取决于您。如果您使用的是函数式编程,那么一个单元很可能是指一个函数。您的单元测试将使用不同的参数调用此函数并断言它返回预期的结果;在面向对象的语言中,下至方法,上至类都可以是一个单元(从单个方法到一个整个类都可以是一个单元)。意图很重要(本文第一次提到“意图”这个词,很重要)

我们有单元测试、增量测试、集成测试、回归测试、冒烟测试等等,名字不胜枚举。谷歌看到了这种“百家争鸣”的现象,创造了自己的命名方式,只分为小试、中试和大试。

· 小测试,针对单个功能的测试,关注其内部逻辑,模拟所有需要的服务。

小测试带来良好的代码质量、良好的异常处理和优雅的错误报告

验证两个或多个指定模块化应用程序之间的交互的中型测试

大规模测试,也称为“系统测试”或“端到端测试”。大型测试在更高级别上运行,验证系统作为一个整体是如何工作的。

结论:我们的单元测试可以为一个函数写一个case,或者根据函数的调用关系写一个case。

二. 金字塔模型

在金字塔模型之前,冰淇淋模型很流行。包含大量手动测试、端到端自动化测试和少量单元测试。后果是随着产品的增长,人工回归测试的时间越来越长,质量难以控制;自动化案例经常失败,每次失败都对应一个长函数调用。什么地方出了错?单元测试很差,基本上没用。

Mike Cohn 在他的《敏捷成功》一书中创造了“测试金字塔”一词。这个比喻很形象,让你一眼就知道测试需要分层。它还告诉您需要为每一层编写多少测试。

测试金字塔本身是一个很好的经验法则,我们最好记住科恩在金字塔模型中提到的两件事:

编写不同粒度的测试

级别越高,您应该编写的测试越少

同时,我们对金字塔的理解绝不能止步于此,还要进一步了解:

我将金字塔模型理解为 – 冰淇淋融化了。就是说顶层所有的“手工测试”理论上都应该自动化,熔断,优先全部熔成单元测试。单元测试不能覆盖的会放在中间层(分层测试)冗余测试是什么意思,不能覆盖的会放在中间层。到 UI 层。所以,UI层的情况,可以的就不要,运行慢,不稳定。按照乔刚柱的说法,我不区分单元测试还是分层测试,都叫自动化测试。那么所有的自动化案例都应该被视为一个整体。案例不应该是多余的,单元测试可以覆盖它们。从分层或 ui 中删除。

低级测试越多,涉及的内容越少,而高级测试涉及的内容越多。就像单元测试一样,它只关注一个单元而不是其他单元。所以,只要写一个单元,就可以通过测试;而集成测试则需要将多个单元组装在一起进行测试。测试通过的前提是这些单元都写好了,这个周期明显短于单元测试需要长;系统测试需要将整个系统的所有模块连接在一起,各种数据准备通过。

另外,由于涉及的模块太多,任何模块的任何调整都可能破坏高层测试。因此,高级测试通常相对脆弱。在实际工作中,一些高级别的测试会涉及到外部系统。结果,复杂性继续增加。

三. 为什么要做单测

我们无法避免这个问题。新闻是这次研发模式改革的支柱之一,所以自上而下的推动让这个问题变得不那么棘手:做,做。不,但是有很多原因:

(收集到的吐槽真实声音)

单元测试浪费太多时间

单元测试只是证明代码做了什么

· 我是一个很棒的程序员,我可以不进行单元测试吗?

· 稍后的集成测试将捕获所有错误

单元测试不具有成本效益。我写了所有的测试,那么测试人员是做什么的呢?

公司雇我写代码,而不是测试

· 测试代码的正确性不是我的工作

单元测试的意义

·单元测试对我们的产品质量非常重要。

单元测试是所有测试中最低的测试类型。这是第一个也是最重要的部分。它是唯一保证实现 100% 代码覆盖率的测试。它是整个软件测试过程的基础。前提是单元测试可以防止后期开发因为bug太多而失控,单元测试的性价比是最好的。

· 据统计,大约80%的错误是在软件设计阶段引入的,修复软件错误的成本会随着软件生命周期的推进而上升。越晚发现错误,修复它的成本就越高,而且成倍增加。作为一名编码员,也是单元测试的主要执行者,是唯一可以生成无错误程序的人,没有其他人可以做到这一点

·代码规范、优化、可测试代码

·自信地重构

·自动执行三千次

下图来自微软统计:单元测试阶段发现bug,平均耗时3.25小时。如果泄露到系统测试阶段,需要11.5小时。

下图旨在说明两个问题:85%的缺陷是在代码设计阶段产生的,而bug发现阶段越晚,成本越高,呈指数级增长。所以,在单元测试早期就可以发现bug,省时省力,一劳永逸,何乐而不为。

单元测试特别耗时?

它不能一刀切,也不能只关注单个测试阶段的耗时。

我采访了新闻客户端的发展和背景。首先,可以肯定的是,单次测试会增加开发量,增加开发时间;

在《单元测试的艺术》一书中,提到了一个案例:发现两个开发能力相近的团队同时开发相似的需求。做单项测试的团队将编码阶段的时间延长了一倍,从7天增加到14天,但是这个团队在集成测试阶段表现得非常顺利,bug很少,并且可以快速定位bug等。最终效果,整体交付时间和缺陷数量对于单个测试团队来说是最少的。

单一的测试,存在是合理的。一方面,需要将单个测试放在整个迭代周期中,观察其效果;另一方面,写单项测试也是一项技术任务冗余测试是什么意思,写得好的同学需要的时间少,代码质量高(也就是说,不代表写单项测试,是可以写单项测试)

谁来编写单项测试?

·发展学生写单项测试

·测试学生写单题的能力。专注于开发脚手架、分层测试/端到端测试

增量或库存

· 增量代码的单个测试用例

·当对现有代码进行大规模重构,而后者的质量暴露出很大风险时,正是推动完成单测的好时机

四. 单元测试阶段

一. 广义的单元测试,我们指的是这三部分的有机结合:

·代码审查

·静态扫码

编写单元测试用例

二. 结合新闻的实践,我将单测增长的过程分为4个目标,即:

·会写,全员会写

· 写得很好,同时专注于可测试性问题和试点解决方案

·识别可测试性问题,熟练使用重构方法进行重构;识别代码架构设计问题;同步编写案例和业务代码

·TDD。但这个目标是一个期望,而不是一个必须实现的目标。

截至发稿当天,消息处于第三阶段,即每次迭代都能产出优质案例,覆盖率高,需求覆盖率高;重在可测性,时刻关注重构。

五. 单元测试指标

挺尴尬的,而且没有一个直接的指标来衡量单次测试的效果。我们也经常被问到,“如何证明你的新闻单测试的作用?”

错误指标(间接指标):连续迭代中错误总数的趋势、迭代中新错误的趋势、每千行错误率

·单项测试需求覆盖率(50%以上),参与者覆盖率(80%以上)

·单个测试用例总数的趋势和代码行数的增量趋势

增量代码行覆盖率(接入层80%,客户端30%)

单个函数的圈复杂度(小于40),单个函数的代码行数(小于80),扫描报警数)

在迭代需求持续高吞吐的前提下,以新闻iOS的数据为例:

六. Go 单元测试框架选择

基础选择:testify + gomonkey

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论