您的位置:首页 > 其它

一次单元测试讨论引发的奇想

2016-03-31 09:59 309 查看
作者:Zhang Yang

近日,听了一段关于单元测试的讨论,在回家路上细细品味时产生了一些想法,这里记录下来,大家一起探讨。

单元测试的讨论

当时是这样一件事:项目上的一个子系统(subsystem)刚刚增加了单元测试的测试用例, 这些用例在开发人员那里编译是没有问题的,但是在CI中总是失败。

原因是单元测试的makefile文件中,使用了产品工程中的一个环境变量
${ENV_ROOT}
,该变量用于指示外部头文件所在的目录。而
${ENV_ROOT}
只有在设置了产品环境之后,才会有定义。目前的CI环境中并不会执行设置产品环境的脚本,而只是单独执行单元测试的 makefile 文件;这样 CI 编译测试用例的时候,被引用的外部头文件都无法被找到,导致编译器报错退出。

CI负责的同事就来找子系统的开发人员,要求他修改makefile取消对
${ENV_ROOT}
的使用,而采用将外部头文件直接复制到单元测试目录中的方法。而开发人员则表达了不同意见:

直接复制头文件,一方面是一件费时费力的事情,另一方面,当外部头文件发生变化的时候,子系统的单元测试无法立刻发现可能的问题。他甚至希望能够直接调用外部的函数,而不是将它们打桩或者mock掉。因为这样,可以更快捷的发现一些外部的错误。

单元测试的FIRST原则

学习过单元测试的同事,都知道它有个FIRST原则,其中 I 就代表着isolataion(隔离)。目的就之一就是为了使得

‘一个错误只会导致少量测试用例失败’,

为此,单元测试中有打桩,有mock;这样才能更快地定位和修复模块内部的错误。

权衡(trade-off)

在实践中,我们不可能只遵循于任何一种理论,而枉顾其他;一般来说我们不得不做一些妥协,使得各方面都基本满意。

子系统的开发人员,基于‘左移’原则,希望更快的能够发现错误,要求 CI 系统执行测试用例之前,要下载整个工程,然后设置产品的工程环境,最后执行测试用例。

而单元测试的理论要求测试用例有相当的隔离性,不要直接调用外部的服务,这样便于测试用例本身定位和修改错误。

不能绝对地说,这里一定是谁错了或者谁对了。让我们想一想这两种想法背后的故事:

1.开发人员,不满足单元测试只是测试子系统本身,还希望它能够提前发现别的子系统可能带来的风险;这个好处是显而易见的。

2.CI系统,希望能够单独执行某个子系统的单元测试用例,不依赖于产品工程。

一部分是因为之前产品代码都是保存在SVN上,而从SVN下载完整的产品代码需要数十分钟甚至一个小时的时间;当不需要下载完整工程的时候,CI可以在相对短的多的时间内给出执行结果。

另一部分,如果按照开发人员设想的实施,在糟糕的情况下,某个子系统的修改,会导致大量子系统单元测试用例失败,快速定位错误会比较困难。

权衡之下,是否可以这样:

1.子系统里的单元测试用例,尽量不要直接使用其他子系统的服务,而是使用打桩或者mock掉;

2.如果子系统依赖的外部服务至关重要,或者外部服务处于不稳定期,可以单独撰写测试外部服务的单元测试用例;这样外部的错误,既能够被提前发现,也只会导致少部分用例失败。

3.CI系统可以测试一下目前从Git上取工程需要多长时间,如果时间比较长,是否可以考虑在执行单元测试之前,只下载有依赖关系的多个子系统?

进一步的思考

单元测试问题可以到此告一段落,但是再仔细想一下,当初决定 CI 中单元测试有如此的要求,可能还有一个原因:

“减少‘我’失败/出错的机会,同时也不想管‘别人’是否失败/出错”。

这个想法和

“这个BUG不是我的问题,而是其他人的问题,所以请找别人”

是同一种思路。

防御性合作

这是一种典型的‘防御性合作’的思想,产生于画地为牢,按照代码划分权责范围的分工工作方式。这种方式,在历史上曾经成功的运用于我们的很多产品。但是如果要进一步提高研发效率,帮助部门成功转型,它肯定是做不到的。软件业,有这么一句俗话:

什么样的组织结构,一定会创造出类似结构的软件。

相信大家都还有记忆,以前当出现涉及多个开发组的 Bug 的时候,各组之间是如何合作的?都能听到哪些抱怨?

同样,开发新功能的时候,在集成测试、系统验证的时候还会发现缺少了一些功能? 交付给客户的时候,客户是否满意质量或者时间?

实际上的后果是:

开发组缺乏产品意识

各人自扫门前雪,休管他人瓦上霜

员工们很多的主观能动性被抑制住了,但是软件公司比其他类型的公司更加需要员工的主观能动性。可以怎么办呢?

自组织团队

要释放员工的主观能动性,端到端负责,自我驱动,自我管理,自我演进的自组织团队,在其他软件公司已经被证明了是好方法。

我们是否可以进行类似的尝试呢:让一个团队完全端到端地负责某个 服务的全部(包括产品,设计,实现,测试,集成,维护),直接面对客户交付产品。

让对产品负责的思想进入到每一位团队成员意识中,让团队能更直接的获得客户的反馈,更加直接的参与到竞争中,释放他们自己的主观能动性。

这样,当问题产生或者新的需求产生之时,很明确该团队的成员将成为唯一的 owner负责到底。

这样是否可以提高研发效率呢?让我们拭目以待吧
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: