1.1.3 当前软件测试工程化的困局与解法

可能你已经发现前述的测试左移是完全基于瀑布模型的,但是现在,敏捷开发和持续交付等研发模式被广泛采用,再加上软件架构的持续复杂化,前述的测试左移只能在局部范围内发挥作用,我们需要探索并实践适应新时代软件研发模式的测试左移。为此,我们有必要先系统地探讨一下当前软件测试工程化的困局,理解困局将有助于我们对测试进行优化。

总体来看,当前软件测试工程化的困局主要表现在以下3个维度:

技术实现上,软件架构的复杂度越来越高;

团队管理上,开发团队和测试团队的协作成本因为“筒仓效应”变得越来越高;

研发模式上,敏捷开发、持续交付、DevOps等的实践对测试活动提出了全新的要求。

接下来,我们依次展开讨论。

1. 技术实现维度上的困局与解法

从技术实现维度来看,软件架构的复杂度越来越高,软件本身的规模越来越大,传统的测试模式越来越“力有不逮”。

早期的软件基本采用单体架构,通过后期基于黑盒功能的系统测试基本能够保证软件质量。但是如今的软件架构普遍具有冰山模型(如图1-6所示)的特征,基于黑盒功能的系统测试往往只能对水面上的一少部分GUI(Graphical User Interface,图形用户界面)进行验证,大量的业务逻辑实现其实都在水面以下的微服务中,想通过水面上的GUI部分覆盖水面下的所有业务逻辑几乎是不可能完成的任务,因为你可能都不知道水面下有什么。试问,在传统黑盒测试模式下,又有多少测试工程师能够对被测软件的架构设计、调用链路、数据流状态等有清晰的理解呢?

图1-6 冰山模型

现在互联网产品的后端往往非常庞大和复杂,一般由几十到几千个微服务相互协作共同完成前端业务请求,这时候如果把测试寄希望于面向终端用户的系统测试,那么你能够发现的缺陷就会非常有限,而且发现缺陷之后,在调用链路中定位到出问题的微服务的成本也会很高。

在这种情况下,最优的测试策略就是先保证后端每个微服务的质量,这样集成场景下没有问题的概率就能大幅度提高。这就要求测试工作必须前置到微服务的接口开发层面,把大量的组合逻辑验证交由接口测试来覆盖,在GUI层只做基本的业务逻辑覆盖即可。

由上面的分析可以看出,软件架构后端的复杂化对测试的介入时机提出了新的要求,随着微服务架构的发展,测试重点必须从GUI端逐渐左移到API端,此时测试工程师的能力也必须随之扩展,其已经不能完全基于黑盒功能来设计测试用例,而必须知道更多架构和接口设计上的细节才能有效开展测试用例的设计,这些都要求测试介入的时机必须提前,即左移到架构设计。

2. 团队管理维度上的困局与解法

从团队管理维度来看,开发团队和测试团队的协作成本因为筒仓效应变得越来越高,继续采用独立测试团队和开发团队的做法越来越行不通,我们可以通过实际工作中常见的真实例子来感受一下这个困局。

在开发和测试采用独立团队的情况下,当测试工程师发现一个缺陷时,他要做的第一件事就是把缺陷的详细情况了解清楚并且完整记录在缺陷报告中。他需要找到最简单的可稳定重现缺陷的操作步骤,并且需要提供相关的测试数据,还需要对出现缺陷时的软件版本号、环境细节、配置细节等都做详尽的记录。更进一步地,为了便于开发工程师重现缺陷,他最好把出问题时的日志以及相关截图都保留好,一同记录至缺陷报告。这样一份高质量的缺陷报告往往需要花费测试工程师不少的时间。

但是当这份缺陷报告被提交后,如果缺陷不是来自生产环境,那么开发工程师往往并不会立马处理缺陷,因为开发工程师一般会选择确保能够连续完成当前负责的工作,尽量避免被打断。一般过了大半天或一两天,等开发工程师负责的工作告一段落后,他才会开始处理这个缺陷。此时他要做的第一件事就是重现缺陷,在重现缺陷之前,他必须按缺陷报告提供的详细信息重建测试环境,其中包括环境安装、测试数据构建等一系列步骤,所以往往也要花费不少时间。

如果问题能够重现,则可以进一步定位问题;如果问题不能重现,则可能这个缺陷在流程上就要被打回去加以复现。假定现在问题能够重现了,你会发现修复缺陷的过程往往是很快的,因为这个坑就是开发工程师自己挖的。

修复缺陷以后,开发工程师提交代码,集成流水线会生成对应的待测版本并通知之前的测试工程师进行验证。但是此时测试工程师大概率在处理其他测试工作,测试工程师同样不希望被打断,所以不会为了验证这个缺陷立马搭建环境。从效率角度出发,测试工程师一般会选择将多个缺陷集中在一个版本上一起验证,这样就能省掉很多环境搭建的时间。所以从缺陷修复完成到测试工程师验证这个缺陷,往往需要等好几天。

从上面的过程描述中我们可以发现,从缺陷被发现到缺陷最终被验证的整个过程中,真正有效的工作时间占比很小,大量的时间都被流程上的等待和环境安装等耗费掉了。整个过程中,开发工程师没有偷懒,测试工程师也没有偷懒,他们各自都选择了效率最高的方式开展工作,但是从全局视角来看,效率仍十分低下。据一些企业内部的不完全统计,每个缺陷全生命周期中一般会有超过80%的时间被跨团队的过程流转浪费掉。

除了上述时间上的浪费,还有以下原因使得测试团队与开发团队各自独立的组织设置越来越寸步难行。

(1)独立的测试团队往往在开发后期才介入,很难有效保证测试的覆盖率和质量。

(2)开发测试比持续增长,测试人力投入越来越大,实际收益却很低,测试团队进行的测试活动并不能显著降低现网问题数。

(3)需求本身会不断变化,需求的实现也会随之变化,开发团队和测试团队之间的需求传递效率往往十分低下,这在增加漏测隐患的同时,也增加了交接成本。

(4)如果开发团队要快速迭代软件版本,这就要求测试团队具有很高的效率和很短的反馈周期,独立的测试团队很难跟上快速迭代的版本需要。

(5)独立的测试团队有点像“保姆”,这直接导致开发团队的自测意识不够,心理上依赖测试团队,使得质量内建形同虚设。

(6)由于开发团队不负责测试活动,可能未积极考虑如何降低测试的难度,可测试性设计甚至不会被纳入开发工程师的考虑范围。

所以,试想一下,如果测试工程师和开发工程师是同一批人,过程流转造成的大量时间浪费是不是就不会发生?测试活动是不是就能提前介入?需求变化的传递是不是就会更加顺畅?测试的反馈周期是不是也会进一步缩短?开发团队的质量意识是不是也会增强?可测试性问题是不是自然会被纳入开发工程师的考虑范围?这也就是现在先进的软件组织广泛推崇开发者自测的原因,而开发者自测可以说是测试左移的一种有效落地途径,能够最大程度满足质量内建的各种要求。

3. 研发模式维度上的困局与解法

从研发模式维度来看,敏捷开发、持续交付和DevOps等研发模式愈发流行,产品的研发节奏越来越快,传统的“开发提测之后进行测试,然后上线发布”的测试模式面临很大的挑战。在当前新的研发模式下,研发生命周期中的各个阶段(比如设计、开发和测试阶段)都被弱化,或者说边界变得非常模糊,一个迭代通常就包含设计、开发、测试和发布的全流程,已经很难有大把的时间专门用来集中开展测试活动,工程师的能力边界正在变得模糊,普遍需要全栈工程师。

在这种背景下,必须把测试实践全程融入研发的各个阶段,把控各个阶段的质量,而不能依赖于最后的系统测试。我们需要转变观念,传统研发模式下的系统测试以发现问题为主要目标,而现在的系统测试应该以“成果展示”和“获取信心”为主要目标。