2023年11月30日发(作者:)

什么样才算单元测试?谁该负责写?微软和⾕歌这么说……

原创 持续交付20 持续交付2.0

随着“DevOps”这个词在IT⾏业开始流⾏起来,就越来越多地听到有⼈讨论下⾯两个问题:

1. 什么样的测试才算单元测试?

2. 谁应该负责写单元测试?

事情就是这么巧,这两个问题都已经被万亿市值的⽜X公司讨论过了……

难道你还不知道么?

⼀、 ⾕歌,⾃动化测试⽤例的 S / M / L

内容总结⾃《⾕歌软件⼯程(版)》的第⼗⼀章,⾃动化测试概述

2020

对于来⾃没有强⼤测试⽂化的组织的开发⼈员来说,将编写测试作为提⾼⽣产率和速度的⼀种⼿段的想法似乎是对⽴的。毕竟,编写测试可能需要同样长

的时间(如果不是更长的话!)⽽不是实现功能会放在⾸位。相反,在Google,我们发现投资于软件⾃动化测试可以为开发⼈员的⼯作效率带来⼏个关键的

好处:

调试更少

增强了对变⾰的信⼼

改进的⽂档

更简单的review

构思周到的设计

快速、⾼质量的发布

1、⿊暗年代(2005年以前)

在⾕歌早期,⼯程师驱动的测试通常被认为是⽆关紧要的。⼤家认为,我们依靠聪明⼈把软件做好。

有⼏个⼤型系统,编写并执⾏了⼀些⼤型集成测试,但⼤多数产品都是敏捷裸奔

2005年,⾕歌⽹络服务( Google Web Server ,简称GWS )的服务质量糟糕到了极点,⼯程师们从早到忙到晚,为了应付⽣产环境上出现的问题和故障,

已经疲惫不堪。⽣产效能下降,发布质量变得越来越差,团队成员对发布越来越没有信⼼,发布得越来越慢。甚⾄在⼀段时间⾥,80 % 的发布都包含对⽤

户有影响且必须回退的缺陷。

因此,当时负责 GWS Tech Lead 要求必须写⾃动化测试,并执⾏持续集成实践。他们甚⾄专门安排了⼀名⼯程师做构建警察(Build Cop),负责确

保每次构建失败,都能被快速修复。要么⾃⼰修复,要么找到那个破坏构建之⼈,要么回退代码。

⼀年之后,紧急修复的发布数量减少了⼀半。现在,GWS 有数万个⾃动化测试⽤例来保障代码质量。⽬前可以保持每天发布⼀次,并且⽤户可感知的缺

陷相对很少。

这⼀事件可以被看做⾕歌软件⼯程意识觉醒的标志性事件。它意味着,不可能⼀直依靠⼯程师的个体能⼒来避免产品缺陷。即使每个⼯程师都只是偶尔写

出⼀个缺陷,那么当你有⾜够多的⼈在同⼀个项⽬上时,你仍旧会被越来越多的缺陷所包围。

22008 年以后

⾕歌很早就学到的教训之⼀是,虽然⼯程师更愿意编写更⼤的系统级别的⾃动化测试⽤例。然⽽,与⼩型测试⽤例相⽐,这些系统级别的测试⽤例运⾏更

慢、更不可靠、并且更难调试。

当忍受不了系统级别测试的问题定位和调试的痛苦时,他们就会问⾃⼰,为什么我们不能⼀次只测试⼀台服务器呢?或者,为什么我们需要⼀次测试

整个服务?我们是可以单独测试较⼩的模块的啊……”

最终,为了减轻痛苦,⼯程师开始编写越来越⼩型的测试⽤例。结果证明,这样的⼩型测试⽤例更快、更稳定,通常不那么痛苦

这在公司周围引发了很多关于什么是的意思?⼩测试意味着单元测试吗?那么集成测试呢?它们的测试规模是⼤,还是⼩?

我们得出的结论是

每个⾃动测试⽤例有两个不同的维度:资源占⽤和验证范围

资源⼤⼩:运⾏测试⽤例所需的资源:内存、进程和时间。

验证范围:正在被验证的特定代码路径的⼤⼩。

⼤⼩和范围相互关联,但他们⼜是截然不同的概念。

我们对⼩型、中型和⼤型的定义实际上是以测试基础设施对所执⾏的测试⽤例的资源约束来限定的

但简⽽⾔之,⼩型测试是在单个进程中运⾏,中型测试可以在单台计算机上运⾏,⽽⼤型测试在他们想要的任何地⽅运⾏。

不使⽤传统意义上的单元测试集成测试,是因为我们认为:测试集最重要的品质是速度和确定性,⽽不管测试的范围是什么

⾕歌主要是对全系统端到端验证⽽保留那些较⼤的测试,这些测试更多的是验证配置⽽不是某个代码⽚段,以及那些⽆法使⽤测试替⾝对象的遗留系统测

试。

他们经常会将⼤型测试与⼩型或中型测试隔离开来,只在创建发布分⽀进⾏构建和发布过程中运⾏⼤型测试,以免影响开发⼈员的⼯作流程。

⼆、 微软的⾃动化测试⽤例分级:从 L0 L3

1. ⿊暗时代 2010 年以前)

众所周知,微软是最重视⾃动化测试的软件公司。⾃上个世纪九⼗年代开始,微软的测试部门就有专门的两个职位,它们是:

1Software Design Engineer Test (SDETs) 负责开发⾃动化和测试基础设施。

2Software Test Engineer (STEs) :运⾏⾃动化测试,和执⾏⼿⼯测试。

那时,他们的开发⼈员与测试⼈员的⽐例达甚⾄达到了 1 : 1 。然⽽,这种做法在现今根本⽆法正常运作。

但它真的有⽤吗?⼀句话没有。我们开始看到⼀些问题,但被产品的商业成功掩盖了⼀些。到了年代末,这些问题就⽔落⽯出了。开发⼈员把代码

——90

扔到了⾯前。把测试⾃动化扔给了。我们的对策是不断壮⼤,尤其是供应商。在测试领域的晋升机会有限。维护这种配置

SDETsSDETsSTEsSTEsSTEs

是⾮常昂贵的。测试成为了⼀个瓶颈,导致了产品的延迟,但我们还是⽆法看穿它。

—— Evolving Test Practices at Microsoft - Azure DevOps

参见《

2. 开启DevOps时代

在微软开始DevOps之旅后,开始寻求⽅法,改变这种状态。在2015年,团队制定了新的质量愿景。其中核⼼的部分就是把整个测试组合向源头移动。

以前,我们的⾃动化测试分类是基于测试执⾏的时间,例如 nightly run (NAR) full automation run (FAR), 等。现在,我们基于对外部的依赖,重新划分

了⾃动化测试的类别。如下所⽰。

L0/L1 – Unit tests

L0 – 这个级别的测试是数量最多,在内存中快速执⾏的单元测试。⼀个 L0 测试⽤例对⼤多数⼈来说,就是那个最经典的单元测试定义,它只依赖于被测

试的代码,没有其它依赖。

L1 – 这个级别的测试可能需要⼆进制集成包 加上(数据SQL 或者file system)。

L2/L3 – Functional tests

L2 – 这个功能测试类是针对可测试的服务部署执⾏。它算是⼀个功能测试类,需要进⾏服务的部署,但可能会以某种⽅式将关键的服务依赖关系断开。

L3 – 这是在⽣产环境中执⾏的受限集成测试类别。它们需要完整的产品部署。

微软的 VSTS 团队花了两年半的时间,才将它以⼤型系统测试(上图中的橙⾊部分)为主转变成以 L0 测试⽤例(蓝⾊部分)为主的状态。

当然,微软 VSTS 不再有写⾃动化测试的 SDTE ,也没有维护⾃动化测试的 STE 了,这些⼯作全部由开发⼯程师代劳。