测试驱动开发——助你创造更有效的软件工程项目
测试
DAVE_JOSEPHSEN
5人收藏 1556次学习

测试驱动开发——助你创造更有效的软件工程项目

我工作于一家名叫Librato的小型却多产的程序工厂。在这里我们每天要部署40到60遍代码。而每次的部署我都会及时反馈到我们团队的聊天室当中,因为聊天机器人会自动帮我们上传要部署的新代码。我们可以从机器人那里得到诸如新用户的加入、产品检测问题等通知,我们甚至还可以将Github或者Travis-CI嵌入其中。

 

序言

我工作于一家名叫Librato的小型却多产的程序工厂。在这里我们每天要部署40到60遍代码。而也许在我写这篇文章的同时,我们的团队已经将代码重新部署了40多遍了,这其中有12次是代码的开发部分,而剩下的二十多次是环境的搭建与调试。而每次的部署我都会及时反馈到我们团队的聊天室当中,因为聊天机器人会自动帮我们上传要部署的新代码。

 

事实上,我们在制作自己的产品(遥测程序)的过程中,大多数与服务器的交流都来自这台聊天机器人。我们可以从机器人那里得到诸如新用户的加入、产品检测问题等通知,我们甚至还可以将Github或者Travis-CI嵌入其中。

 

因此每当有组内成员将新的代码加入到开发测试中时,我就能在组内聊天内看到这样的画面:

除了测试结果之外,机器人还会推送一个Travis链接,指向Travis的输出。所以我可以清楚地看到Travis上的一切。聊天机器人会自动重启计算机,自动运行测试脚本,并对上传的代码进行审核,并最终把其部署到云端。对于很多人来说这是个非常有趣的程序。

总共多少个测试脚本?

我们先锁定我们的预警系统,因为他的开发代码和检测代码都是用Go语言来编写的,这对于我这样粗心的彪形大汉来说再好不过。

find .  | grep _test.go | wc -l

上面的这条指令会为我们找出44个在指定文件夹中以.go后缀结尾的测试文件,每个测试文件都对应着他们的开发文件。例如我们会为foo.go文件找到属于它自己的测试文件foo_test.go 。而那些没有匹配的测试文件的开发文件一般都是一些变量声明、数据结构声明等简单的定义文件。这些文件本身也是没有测试价值的。

grep -ri 'func Test.*(*testing.T' . | wc -l

 

上面的另一条指令产生了172个测试进程,大概测试了总体函数中的1/4.

find .  | grep _test.go | while read i; do egrep -v '({|})' ${i} | grep '[a-z][A-Z]'; done  | wc -l 

经过粗略的统计,在这个目标文件夹中我们一中有2400行测试代码,这几乎占据了总代码的一半行数。那么,我们写了这么多的测试代码,多到几乎与真正的开发代码齐平,我们的工程进展就会更加有效率吗?

其实对我来说,答案是肯定的。也许对很多持怀疑态度的人来说上面的数字毫无疑义。接下来我会简单解释为什么我会觉得这些测试代码能够有效地为持续集成系统形成一层强而有效的催化剂。测试程序虽然在表面上看是组织开发进程的工具,但是从整体来看却是在为项目最终的正确开发发布提供台阶。如果没有它们,整个持续集成系统会漏洞百出。

好的测试可以帮助我们快速上道

当然,有些测试无法适应于所有开发环境。在编写他们的时候,我们既需要保持程序化,又要精心挑选。持续集成系统比传统的变量控制系统更加依赖良好的测试脚本。只有制作精细的测试脚本才会使人快速上到。

好的测试脚本能够促进组内合作

如果我们把测试做的过于复杂或无意义,或者把代码风格这种无标准答案因人而异的元素也加到限制当中,一般人都甚至不会加以理睬。如果我们把编写测试脚本的任务分配给一个特定的小组的话。这种弄巧成拙的现象很容易发生。成功的测试脚本应该以传输重要参数为主,并让所有人都参与到编写当中,因为它们能帮助每个人更好地认识到我们需要从自己搭建的程序中得到什么。脚本代码应该能够让我们对这个项目的编程合作有更深入的认识,而不是产生工程师之间的矛盾。

好的测试脚本能形成优质的代码库

创建并维护好的测试代码不仅是一门科学,也是一门艺术。它使我们特别注重程序的正确性因此使我们能更好地认知自己的期望和假设。选取合适的测试参数不仅意味着需要彻底了解自己的项目,而且明白现阶段所产生的偏差。可用于测试的脚本一般都是经过精心编写的,而那些质量差的脚本很难投入到运行当中。

度量驱动开发?

在上述例子中,还有一部分代码既不是实用性的开发代码,也不是检测代码。这些代码如下面一行所示:

metrics.Measure("outlet.poll.alerts.count", len(alerts)) 

这段代码的意义在于检测应用程序内部的一些重要属性,比如队列大小,线程数目,内部设备延迟等等。当测量结束之后这些度量将会集中反馈到中央系统中并以可视化的图形向用户展示出来。下面这些图便

好的度量帮助我们快速上手

在Librato,内部度量是必不可少的。它们可以帮助我们更加了解程序行为。我们一般会谨慎选择度量值并进行跟踪测量,并根据度量反映的结果进行汇总。

就像测试脚本一样,度量检测也不能保证环境的干扰。Librato里的持续集成系统严重依赖品质优良的度量,仅有这样的测试才能反馈有用的结果。他们让我们看到了开发代码对产品内部属性的影响。

好的度量能建立优质的代码库

好的度量测试的是系统体系。它们可以用来检测我们搭建的系统在使用中表现如何。像测试脚本规定了程序的主要参数值一样,度量测试规范了我们产品的内部属性。度量测试也教会了我们许多之前不曾熟悉的代码。虽然没有任何的文档说明,但是我还是能够在上面的度量测试中推断出很多。比如这个预警系统功能是发送警报,客户使用数量,警报拉响总概率和单独拉响概率。

因此同样的,创建并维护好的度量代码也不仅是一门科学,也是一门艺术。它同样使我们特别注重程序的正确性因此使我们能更好地认知自己的期望和假设。当我们能够正确地设计度量测试的时候,我们对系统的内部运行也有了深入理解。这无论对于设计系统还是框架结构都很有帮助。在Librato我们相信如果今天你能够创建测试代码,你就已经知道了如何在产品中融入度量测试并将产品进行优化,是你的客户达到最大的满意程度。

加入1KE学习俱乐部

1KE学习俱乐部是只针对1KE学员开放的私人俱乐部