你是一家大公司里不得志的程序员。和你同年进公司的那些人在核心业务上拼命工作,被客户骂,加班,交付,开庆功会,拿奖金。而你,不知道怎么的被放到一个叫做“测试工具开发”的边角部门里,干着一些不疼不痒不影响公司业绩的工作。你恨。你要报复。你要拿回本该属于自己的一切。

现在我教你怎么做。

首先,你要启动一个自主开发自动化测试工具的项目。让老板们相信自动化测试的重要性并不困难,世界上有无数的文章和书籍在讲这件事,你们公司请的咨询顾问一定也会说到这件事,这些都是你的帮手。真正难的部分是“自主开发”。你用得上一个百试百灵的招数。告诉老板们,一个自主开发的工具可以由自己来维护和支持,只有这样才能把核心技术的命脉掌握在自己手里,而不用向别人支付维护支持的费用──小心,千万不要提到那些开源的工具,因为老板们万一真的弄懂了“开源”这两个字的含义,你的整个大计划就泡汤了。拿IBM的RFT当靶子。除了后面我会说到的各种好处之外,IBM的咨询价格足以帮你吓到老板从而启动这个项目。

然后,你要精心选择一个自动化测试执行引擎。你需要这么一个引擎,因为你不能自己去做一个──工作量还在其次,要是连这都能做,你也就不在这个边角部门里郁闷了。同时这个引擎又不能太稳定,更不能太开放,这都是你大计划中不可或缺的要素。所以,你看,我说过了,RFT就是最好的靶子:它的开放程度确保了你要花好几个月时间才能把它嵌在自己的工具里而且以后再也不会有别人尝试干这件事。而且,想想吧,当你跟老板们报告说你hack了IBM的软件从而省下了licence费用时,他们该有多开心。

接下来,你要发明一套自己的测试脚本语法。沿用RFT的语法当然轻松,但这样使用它的人就会发现自己使用的其实是RFT,然后在该死的互联网上找到相关的资料。不能让这样的事发生。始终记住,你的目标是让自己变得重要。你发明的语法应该基于XML。不仅因为实现简单,而且因为它能确保测试脚本无法被阅读和重构,从而让使用这工具的人跪在你脚边求你支持。关于使用XML的好处,稍后我还会说到。

当然你不希望向领导演示时用记事本编辑XML。所以你得同时实现一个支持拖拽的测试用例编辑界面。把一个测试步骤表示为一个图标,把几个图标往测试用例里一拖,一个测试用例就好了。别忘了,执行用例的功能也得在这个界面里实现。千万别为了偷懒而实现一个命令行来执行用例,这很重要。好了,现在你可以去演示了,领导一定会喜欢的。“鼠标拖拽其实比键盘输入慢多了!”旁边一个傻逼顾问叫喊着。领导们不会听懂他的话。不用理会他,更不要尝试跟他争论,那只会给你自己带来麻烦。

现在这个工具可以小范围试用了。那些麻烦的用户会抱怨:“我每次都要重复这几个同样的操作!我想把它们合并成一个步骤!”镇静。不要骂他们(尽管你一直就想骂他们)。记得吗?让测试用例不可被重构是你大计划中的一部分。现在你要笑容可掬说。我们早就考虑到了这个问题,我们的工具可以把几个步骤封装成一个更大的、具有业务含义的东西……嗯,姑且把它叫做“操作词汇”吧。现在我就来帮助你们做这个抽象和封装。当然了,操作也要用XML来承载,并且在提供给用户时要先做一次编译或者打包或者加密,总之是不能让他们看到源文件。这样他们才能永远依赖你。

小范围试用很重要。你必须努力工作,帮用户写测试用例,帮他们封装操作,找你能找到的一切资源来帮他们,然后把投入二十个人月干出来的成果全都描述成你的工具带来的神奇变化。放心,你只需要这么干一次(或者两次)。为了把这些愚蠢的家伙踩在脚下,有时你就得先纡尊降贵。这是策略。

试用结束,你回到自己的办公室,这些愚蠢的用户还会不停地找你帮忙更新被封装的操作。这是设计中的一环。现在你应该做一个中央服务器,把他们的测试用例和操作全都保存在上面,让他们每次执行测试都从服务器上取用例脚本。然后告诉他们,这叫云计算,这叫测试工厂。当然这些傻瓜不会懂得云计算是什么玩意,但他们会发现你帮他们更新操作的速度变快了,然后他们就会认为这就是云计算带来的效果。把他们感谢你的话搜集起来,很快你就会用得上。

现在万事俱备,可以向老板汇报了。这次汇报的重点是两个关键词。这也是今后宣传这个工具时的常用语。一定要背熟。

关键词1:“第四代自动化测试工具”。你要告诉老板,用Java啦Ruby啦C#啦这些编程语言来编写测试用例,那是第三代(前两代是什么就随便你编吧)。第四代的特征就是“基于操作词汇”──也就是图形界面上可以拖的那个玩意,尽管你知道它背后就是一坨不能读、不能改、连SVN合并都困难的XML。

关键词2:“测试工厂”。这时候把界面打开,连上中央服务器,让老板看试点项目的测试用例。“坐在办公室就能知道所有项目的测试进展情况。”这句话是杀手锏。老板们一定会喜欢,而且会帮你推广这个工具。

只要被推广到更多的项目组,你就会变成红人。现在前面那些设计决策的重要性就逐渐体现了。因为测试用例不可重构,任何一个项目想要正经用你的工具都得找你帮忙做操作词汇,为此你就可以成立一个部门,拉更多的人来给你打这份苦工,自己当领导。但你又怕别人真的用得太多太频繁,那样的话你就得疲于支撑了。放心,因为RFT不稳定,因为每次执行都要连到中央服务器来取用例,因为不能通过命令行或者Ant之类的办法把它放进持续集成,还因为用鼠标拖拽就是比用键盘慢得多,自动化测试的进展会非常缓慢,你大可以安心享受自己的新办公室。

先别急着享受,好事才刚开始呢。那些深思远虑的设计决策确保了很多项目不会认真用你的工具。这时候作为推行先进自动化测试理念的红人,你正好可以在老板耳边吹吹风,让他们强迫所有项目使用。强迫的方式有很多,但你必须记住的手段是给测试人员做职业技能鉴定考试:必须学会用你的工具才能评级加薪。这招的关键在于一箭双雕:不仅可以强迫他们使用,而且确保了他们没时间没动力去了解别的测试工具──你当然不想这些傻瓜突然冒出来说“这个开源的工具比我们自己的好用多了,而且还有那么多社区高手在维护和支持,为什么不用它”,对吧?

强行推广之后,你接到的支撑需求肯定会剧增。这时你得好好培训一下客服的小弟。要让他们分清用户的来头。如果是老板重视的项目,如果办公室离你或者离老板很近,就得大力支持。如果来自什么边远山区的支撑需求,那就把它撂到一边凉快去吧。这些边远山区经常会提些奇怪的需求,例如“能不能不连中央服务器执行用例?我们这里无法连通公司内网”。让小弟们直接回复“不行”就可以了。无法连通公司内网的人同样无法有效地跟领导告状,不用担心他们。

好了。现在你已经从一个边缘程序员成功晋升为公司的红人。不仅有一帮小弟鞍前马后,而且一大帮项目头头们都得求着你优先支撑。这快感,又岂是交付一两个项目、开一两次庆功会所能比拟的?恭喜你。你不仅改变了自己的命运,还很有可能改变整个公司的命运呢。

噢,差点忘了最重要的……千万别用你们的测试工具来给自己的项目做自动化测试。微软那帮傻逼把这种行为叫做“吃自己的狗食”,可你做的是毒药,吃下去会害死自己的。切记,切记。

做工具需要知道界限。一个好的工具,应该只做一件事并把它做好,是为高内聚;应该以最容易、信息量最少的方式与其他工具集成,是为低耦合。这些道理,Eric Raymond 早就说过了,不应该再重复。

(跑题:GUI迷恋者的盲点在于,他们没有意识到鼠标点击是一个蕴含了多大信息量的操作。在1024×768的屏幕上找到一个48×48的图元然后向右拖拽530像素。啧啧。不懂得文本和命令行的重要性的人不配做工具。)

持续集成工具应该做的事就是让集成能够被“持续”起来。“集成什么”和“怎么集成”是软件开发者自己的事。测试工具应该做的事就是帮助编写和运行测试用例。“测试什么”和“怎么测试”是软件开发者自己的事。这就是一个明确并且信息量最小化的边界。

而坏的工具则总是尝试越界。通过把软件的集成过程本身纳入持续集成工具会让软件被集成得更好吗?不会。只会让软件开发者更加不了解自己的集成。通过把软件的测试过程本身纳入测试工具会让软件被测试得更好吗?不会。只会让软件开发者更加不了解自己的测试。其结果是,拥有现场信息和能力、应该关注这些事情的人不去关注,只管盲目堆代码而不管得到什么软件;没有能力关注这些事情的人被不断求助──他们也没有真正去关注,因为他们没有能力。

简而言之,试图用越界的工具大包大揽软件的质量保证,其结果是没人关注软件的质量。

推论是,自制轮子的工具本质是邪恶的。自制轮子的人没有办法像开源社区那样拒绝越界的非法要求。他们只能迫于上下两方面的压力把不该自己做的事纳入自己的产品中,并因此陷入不断为别人的事提供支撑而没有时间做好该做的事的泥沼。这种邪恶本质是内生的:不仅因为这些工具一定会越界,而且因为这些工具会被强加于人。因此自制轮子的工具永远不如开源工具。

(我知道我的客户会有一些人看我的博客。对了,这就是写给你们看的。你们知道我在说什么。)

InfoQ的一篇题为“敏捷遭遇实效营销”的新闻指出:敏捷方法不是产品开发中的银弹。当然我们早就知道没有银弹,但仍然有必要强调一遍,尤其是在这个敏捷方法在中国逐渐开始热门的时候。

有一件事是可以肯定的,即敏捷方法并不能解决业务中的根本性问题,尤其是当业务本身不能决定如何做,或无法决定优先级时,敏捷方法根本帮不上忙。

几乎同时,JavaEye出了一个题为“XP or not”的帖子,提出了几乎同样的观点。这位作者说“XP isn't suitable for every type of software development, it has its own suitable area”,显然这是毋庸置疑的事实,我们甚至用不着为此进行讨论。我们应该做的是,找出敏捷方法(具体说,XP)为什么和如何不适合产品开发,并且找出改进的方向。正如我在InfoQ那篇新闻下面回复的,

对于产品研发,只有敏捷是不足够的。敏捷能做出你想要的,但没办法保证做出好的或者正确的或者受欢迎的。而且作为从内部IT项目衍生而来的敏捷方法,它本身有一种趋势:把功能做到能用而非完美。对于内部IT项目,这很好,两个能用的功能往往能提供比一个完美的功能多得多的价值;但对于面向公共用户的产品,你麻烦了,因为不完美的功能很可能根本就没人用

王晓明显然经过和我在飞机上的讨论有了很多想法,并且这些想法看起来相当靠谱。问题的根源就在于:面对企业内部用户和面对公众用户,概念完整性的估价(priority)是完全不同的;同样,还有可用性——千万不要误会,我并不是打算说敏捷项目一定忽视概念完整性或者可用性。只是很多敏捷团队的经验来自类似C3项目这样的企业内部IT项目,他们的经验蒙蔽了他们的双眼,让他们看不到各种软件特性估价的变化。这个问题是比较容易解决的,只要意识到不够好用的功能将没有人用因此无法创造任何价值,他们就会重新调整自己对于各种软件特性的估价,因为敏捷的核心就在于价值驱动

不那么容易解决的问题是方法和工具的欠缺。这也就是为什么我说“只有敏捷是不足够的”。譬如说为了提高可用性我们就需要交互设计。还有很多类似这样的、适用于产品开发的方法和工具,它们从不同角度影响软件特性。敏捷能做出你想要的,但如果只有敏捷而缺乏这些方法和工具,很可能你永远不知道自己究竟想要什么。然而更严重的问题是看待这些方法和工具的态度,

交互设计是改进的办法之一。但很多敏捷的组织对此认识并不充分,他们只是在项目进行中让交互设计师来做一 次评估和设计。这是不足够的,就好像在软件项目的交付之前才进行QA工作是不足够的一样。质量来自整个流程,同样好的交互设计也来自整个流程。

敏捷团队都充分地意识到,质量保证必须贯穿整个流程进行,这是敏捷方法带来更高软件质量的根本原因所在——测试驱动和持续集成当然是很好的实践,但这些实践能够得以工作,是因为我们在流程层面对质量的重视。而对于概念完整性、可用性和其他软件特性,我们有类似这样的流程层面的重视吗?正如我在InfoQ的回复里说的,有了敏捷方法,还要有一套全流程的产品设计方法支持,才可能做出好的产品。这就是我们要去学习和探索的方向。