不应该是家,窝更适合一点

运用系统思考,走上改善之路

上一篇 / 下一篇  2011-08-29 10:06:23 / 个人分类:转载

为什么敏捷实施,或是任何一点的过程改进都步履维艰?即使是十几人的团队中,也会出现“写自动化测试”──“不写自动化测试”──“写自动化测试”──“不写自动化测试”这种循环往复的过程?

除了人们常常总结的“敏捷实施模式”,或是“敏捷失败经验分享”这样的具体话题之外,是不是还有一些存在于思维模式中的更加根本性的因素,阻碍了我们对系统全景的认知,从而导致改革先行者的黯然退场?

本文将通过两个案例来讲述如何使用系统思考,从全局掌握我们所处的复杂环境,做到既见树木,又见森林。

案例1:舍本逐末

有一个测试团队的负责人找到我们说,我觉得现在的自动化测试问题很大,执行时间长,也不稳定,有的时候是测试写错了,也要花很长时间修。我打算组织一批人,重新设计一下测试代码的架构,把常用的底层功能封装成设计良好的API

我的同事说,好啊,你们打算怎么做呢?

他说,我也还没想好,所以想过来商量一下。我希望这个东西做成以后,能够让不会写程序的QA们都能用它来写自动化测试脚本了,他们现在就是这样,又要做测试,又要学着写程序,我觉得太辛苦了。能让他们不用学编程就能写测试脚本就好了。

……要不我们先看一下现在的代码,了解一下都有什么问题,然后再讨论?我们内心有点小小的纠结。

好吧,我来给你们开通访问权限,找人给你们讲代码。他很爽快的答应了。

打开代码之后我们就忍不住风中凌乱了,满屏都是重复的代码片段,让人一阵阵的眩晕。两天之内,我们仅仅用了提取方法这一个重构手法,就删掉了 1200行代码。期间还发现,不知道谁在调试的时候把一处代码从等待3秒改成了等待10秒忘了改回来,于是其他人再复制粘贴的时候,就全变成了等待10 秒。

于是事情就明朗化了。

依赖于一小拨人重新设计代码结构,提炼API,确实会在短期内使问题得到缓解。但使用这些API的人依然是那些不懂得如何编程的QA,他们依然会使 用复制粘贴来解决问题。再好的架构、再优秀的设计,最终还是会淹没在大量重复的代码中,犹如黄金深埋浮沙之下。而且如果问题表象得到暂时解决,人们就会缺 少动力从根本上提升QA的编码能力,随着设计一点一点腐化,就又需要精兵强将充当救火队员。如此不断反复,直到有一天又回到重新设计乃至重写的老路上来。

这是个典型的舍本逐末的模型。

分析

在上面的场景中,对于测试代码质量低劣这个问题有两种解决方案,一种是精兵强将解决,另一种是测试人员自己解决,每一种方案都会削弱代码质量不断下滑的趋势,从而让系统处于一种平衡状态。如下图所示:

图中的“S”表示同向连接,即箭头起点所示变量的增长会导致另一方变量的增长;“O”表示反向连接,即箭头起点变量的增长会导致另一方的减少。天平表示调节环路,该回路会趋于平衡稳定。

但是,由精兵强将出马可以让问题症状迅速得到缓解,提升测试人员的编码能力则需要长期的辅导训练,不可能一蹴而就,所以图中下方的调节环路实际上是有时间滞延存在的:

与此同时,由精兵强将解决问题会减少测试人员锻炼的机会,从而削弱测试人员的编码能力,进一步使人们不倾向于让测试人员自己解决问题,又转过头来增强了对于精兵强将的依赖。所以还要在图中增加另外一条回路:

滚雪球表示增强环路,该回路会使得回路上的所有节点持续增强

这幅图的全貌便构成了舍本逐末的模型。彼得·圣吉在《第五项修炼》中对此解释到:

上面的环路代表快速见效的症状解,它迅速解决问题症状,但只是暂时的。下面的环路包含了时间延滞,它代表较根本的解决方案,但其效果要较长的时间才 会显现出来。然而它可能是惟一持久见效的方式。有时候舍本逐末的结构中,会多出一个由症状解所带来的副作用所形成的增强环路。发生这样的情形时,副作用常 使问题更难以解决。

人们或者是因为没有找到问题的根源,或者是因为时间延滞的存在,倾向于采取一种简单易行又可以立竿见影的方案,这便是症状解了。但是症状消除以后, 问题就不再令人重视,从而丧失了从根本上解决问题的能力。而问题依然深藏,等到它有一天再度浮上水面时,症状就会更重,更难解决。

这是一条不断衰减的增强环路。在回路上每走一步,情况就会更恶劣一分。

面对舍本逐末,通常的解决方案有两条:

必须要认识到症状解只是短期止痛的手段,切不能形成依赖;

在症状得到缓解之后,要继续加强对根本解的重视。

但见招拆招总是相对容易一些的,更关键的地方是,如何才能识别出舍本逐末这样的模型?当我们采取某些理所当然的对策却得到了不合理的结果,有什么办法可以帮助我们分析问题根源,找到解决方案?

要认清问题的本质,就必须要认识到,我们所处的是各个因素之间紧密连接相互影响的复杂系统,当前采取的行动,会从多方面对这个系统产生影响,而这些影响之间或推波助澜,或相互牵制,从而导致相同的行动在长期和短期来看具有不同的结果。

比如,当代码中发现bug的时候,很多人的常见反应都是调试──定位──解决这样的思路。从眼前来看,发现bug立即修复是可以最快见效的手 段,但却丧失了将测试进行完善的机会,相当于是安全网上明明出现了漏洞却听之任之。等到以后因为需求变更等原因影响了这块代码的时候,就再也无法通过执行 测试来得到快速而完整的反馈了。

丹尼斯·舍伍德在《系统思考》中说,

如果你希望了解一个系统,并进而能够预测它的行为,那么,就非常有必要将系统作为一个整体来研究。将系统各部分割裂开来研究,很可能破坏系统内部的连接,从而破坏系统本身。

如果你希望影响或控制系统的行为,你必须将系统作为一个整体来采取行动。在某些地方采取行动并希望其他地方不受影响的想法注定要失败──这也就是连接的意义所在。

为了帮助人们更好的从整体上研究复杂系统的行为,丹尼斯在书中提供了一套完整的工具──系统循环图。

系统循环图中共有三个基本要素:

增强环路。在增强环路中共有偶数个O型连接,增强环路上的各个节点会呈现指数增长或指数衰退。

调节环路。在调节环路上共有奇数个O型连接,调节环路上的各个节点会趋于平衡状态。它会消化掉外界的影响力,使改变难以发生。

时间滞延。时间滞延是一个不容忽视的影响力,由于滞延的存在,人们常常会发现某个行为在短期内没有产生预想的结果,从而加大投入力度,当行为的后果出现在眼前时,却已经矫枉过正。

下面我将通过另一个真实的案例来讲述系统循环图的应用。

案例2:历史不断重演

一天中午,我忽然听到有人说,我们又开始讨论要不要放弃自动化功能测试了。

咦?你为什么要说又呢?我忍不住问道。

因为我们半年前已经讨论过一次,当时得出的结论是不再写自动化测试了。后来不记得是什么原因了,又用Cucumber来写,最近发现每次上线还是要做大量的手工测试,这些自动化测试又要浪费很多时间来修,所以我们准备讨论一下到底还要不要继续写。

当天下午,我参加了这个团队的讨论,终于弄清楚了事情的来龙去脉:

大概是一年前,为了减少手工测试的成本,团队决定一步步把上线时需要手工回归的测试用例转换成自动化,同时决定每个story做完以后都要加入自动化测试。研究了几天webdriver以后,就开始了自动化测试的尝试。

但麻烦很快就出现了。第一,开发人员用Java代码写的测试,QA不好理解,也不是很清楚哪些场景被测试覆盖到,哪些没有,所以无法信赖测试结果; 第二,测试跟开发共用一套数据库,数据总是受到污染,因此造成测试失败,浪费大量定位和修复的时间。而数据库是由国外的客户控制的,催促了很长时间也没能 给测试分离出一套专用的数据库来。

测试红啊红,修啊修,后来一算时间,在自动化测试上投入了120多人天,却依然得不到一套稳定执行的测试用例,不但没办法保证交付质量,还让每个人心力交瘁。于是毅然决然的停掉了。

过了两三个月,客户终于准备好了一套专门用来跑功能测试的数据库,开发团队也对行为驱动开发有了一定的认识。于是又开始写自动化测试,这次用了CucumberQA写场景,Dev写实现。

写了大概有100多个场景的测试,又有人开始质疑这一切:第一,整套系统实在是太庞大复杂了,写到现在为止,连1/4都没覆盖到,所以上线还是手工 回归。我们到底要花多大的精力才能把所有的场景都自动化起来,这些投入是不是值得?第二,测试环境还是不稳定,比如本地数据跟CI用的数据不一致,比如 Tomcat里面部署的应用常常启动不起来,等等。每个问题都要消耗大量的人力。这些浪费能不能平衡自动化测试到最后能够带来的收益?

但团队中还有其他人对自动化测试持有乐观态度,认为问题总是可以解决的,只要坚持不懈就能够看到长期的回报。于是就有了这次讨论。

分析

绘制系统循环图的第二条法则是:从有趣的地方开始。在这个案例的场景下,开发团队最关心的是该不该写自动化测试,它对交付能力会带来什么影响,于是我们选择自动化测试的数量作为起始点。

接下来是第三条法则──“询问它将驱动什么,以及它的驱动力是什么’”

我们首先可以想到的是,自动化测试的数量增加,会缩短发现Bug的周期,但是这个作用是需要测试数量积累到一定程度才会发挥出来的。它同时还会增加测试的开发和维护成本,增加测试执行时间,缩短手工测试周期。见下图:

手工测试周期的缩短会带来交付周期的缩短,提升产品收益,从而使人们更倾向于编写自动化测试。于是在图中就出现了一个增强环路:

而测试的开发维护成本增加,会导致开发进度放缓,从而削弱收益,于是在图的下方出现了调节环路,这条调节环路的存在,会阻碍人们在自动化测试上的投入。

与此类推,我们同样在图中可以发现其他的增强环路与调节环路:

而在这四条回路之外,还会有其他因素对这个结构造成影响:

画出系统循环图以后,就可以结合团队的状况进行整体分析:

首先回到质疑的声音上来,有人说,整套系统实在是太庞大复杂了,写到现在为止,连1/4都没覆盖到,所以上线还是手工回归,这里反映出的正是从 自动化测试数量手工测试时间这条线上的时间滞延的效果。在前文中提到过,时间滞延在反馈环路中会造成矫枉过正,这里是它的第二个作用──给人带 来挫败感。它会导致某个行为在短期内看不到任何效果,当滞延的时间过长时,会令人失望乃至放弃努力。消除时间滞延可以对系统起到卓有成效的改善。在这个案 例中,我们可以通过推动手动测试用例向自动化测试的转化来缩短滞延。

然而,当时间滞延的作用被削弱以后,还有另外的问题等着去解决。下面再来看看这支团队从写自动化测试不写自动化测试的变化过程中发生了什么。

在刚开始写自动化测试的时候,团队主要的感受是QA少了手工测试的时间,质量多了保障,所以增强环路发挥了作用,每个story完成以后,开发人员 都会为所对应的场景写几个测试。但当测试数量增加到一定程度,调节环路的反馈力量开始占据主导地位──测试时间变长、维护成本增加。而且测试数量越多,带 来的问题就越大,最后便有了第一次的选择:放弃自动化测试。

这正是《第五项修炼》中描述的成长上限模型:

增强环路导致成长。成长总会碰到各种限制与瓶颈,然而大多数的成长之所以停止,却不是因为达到了真正的极限。这是由于,增强环路固然产生快速的成长。却常在不知不觉中,触动一个抑制成长的调节环路开始运作,而使成长减缓、停顿,甚或下滑。

……

当改善的速度慢下来,你会更加努力地去改善。但渐渐的,你愈是用力推动你所熟悉的做法,调节环路的反作用愈是强烈,使你的努力愈是徒劳无功。到了最后,最常有的反应是放弃他们原来的目标。

所以,当我们观察到有增强环路与调节环路遭遇的情况出现时,更为有效的解决方案应该到调节环路上寻找。在上面的系统循环图中,测试环境稳定性、 开发人员技能可以限制测试的开发维护成本硬件数量与质量可以限制测试运行时间,我们可以通过控制这些在调节环路之外起作用的因素,削弱 调节环路的影响,让增强环路的成长继续开始。

小结

结构决定行为。增强环路总是产生指数级的上升或衰减;调节环路总是倾向于使整个环路趋于平衡状态;各种环路的相互影响,就会产生舍本逐末成长上限或是饮鸩止渴等基本模型。

然而不幸的是,参与系统的各个部分,常常见树不见林,只能针对眼中见到的局部信息,做出局部的最佳决策。但每个人的局部最佳决策,并不能构成整个系统的全局最佳决策。因为系统中有反馈、有延迟,因和果在时空上并不紧紧相连,显而易见的解往往无效。

在纷乱芜杂的因果关系中,使用系统思考可以帮助我们理清问题的脉络,认识系统全貌,从而进一步寻找有效的杠杆解──比如案例2中的限制调节环路;而不是固囿于局部优化,把环状的因果关系割裂成线段,看不到当前采取的行动会在未来反作用于自身,因此导致各种系统问题的出现。

系统循环图是一个很强大的工具,但一个人的视野总是有限的,用头脑风暴的方式往往可以得到更全面的认知。案例2的图形就是小组讨论的结果。只是这种方式需要引导者时时注意控制讨论的边界,不要偏离重心。

本文通过两个实际案例对系统思考的基本概念进行了描述,并讲解了如何使用系统循环图对一个复杂系统进行分析,对这方面知识感兴趣的读者可以通过《系统思考》和《第五项修炼》这两本书进行深入研究,学会用这套工具来指导持续改进的步伐。



TAG: 测试 自动化 系统思考 改善

 

评分:0

我来说两句

Open Toolbar