为了帮助讨论和理解,我把“敏捷项目中的测试”这一主题分解成4个区分的主题。今天,我讲一下我们怎样使用面向技术的例子来帮助和支援程序开发。
这里适用的一个是测试驱动开发,在Kent Beck的书中,David Astel最近的书,Phlip,J.B.Rainsberger接下来的书中都讨论了这种开发方式。我认为测试驱动开发(我现在会叫它例子驱动开发,example-driven development)是可靠的。它不是主流的开发方式,但是看起来要成为主流了。套用Geoffrey Moore的话,我认为它正在跨越鸿沟的路途中。
也可以这样说,例子驱动开发已经从Thomas Kuhn所说的“革命性的科学”发展到“正规科学”。在正规科学中,人们扩展了特定方法的适用范围。因此我们现在很多人在GUI应用EDD(sic),设法让它与遗留代码(legacy code)一起工作,讨论mock objects的好的使用方法,讨论处理私有方法的技术,等等。但是这些都不是重大的发展。
我希望不久的将来会看到更多同时拥有测试和编程的技巧的人被吸引到敏捷项目中来。这些人既不会成为像纯测试人员那样的好测试员,也不会成为像纯编程人员那样好的编程人员。但是那还是不错的,如果你跟我一样相信敏捷项目应该重视通才多于重视专才的话。
我不是这样的混合人物。我没有与纯编程人员一起做很多的结对编程。但是我注意到,在维持编程的进度和目标的希望与确保很多好的测试的主意被考虑到的希望之间存在着紧张的关系。我发现我自己在进入程序员模式和退出并考虑全局的之间振荡。从经验看来,我们需要更好的思路来管理这个过程,以及关于什么类型的“测试思考”在编码过程中是合适的。
也可能有一些测试员在敏捷项目中不担当程序员的工作。不过,他们中的一些人还是跟程序员结对讨论单元测试(关于程序员如何检查代码)。程序员学习如何避免哪些类型的bug,测试员学习他们正在测试的是什么。不知何故,加拿大的卡尔加里成为了这些活动的温床,我指望Jonathan Kohl,Janet Gregory和其他人告诉我怎样才能做好。
我需要强调这些都是关于人的。传统上,测试员与编程人员会有很紧密(或者很广阔)的关系。对于矩阵的支援程序员这部分,我相信传统的关系是不合适的。
我使用术语“checked examples(检查例子)”作为支援程序员的测试。我们可以把这个概念一分为二。一部分作为指引下一步编码的决定。另外一部分是自动化的例子,作为“改变探测器”(change detectors),看刚才的修改是否是你期待的。
通常的习惯是,改变探测器仅仅是保留的代码的保护性例子。(你让你的单元测试套件作为救助,一个对应一个地,在编码的同时测试。)那不是逻辑上的要求。我喜欢先建立一些关于什么时候做其他事情的知识。
例如,考虑这样的维护场景:你首先开发了一些代码例子。一个月后,别人加了一个新的例子并改变了代码以便匹配。很多之前为那部分代码开发的例子都成了“bad examples”坏例子了。(测试失败,但是因为他们现在是错误的,不是因为代码错误。)修正那些例子以便他们一致。我的意思是在下表的左边的事件序列本来是期望与右边的测试一样的。(先看左边栏,然后看右边。)
Example foo written Example bar written
Code written to match foo Code written to match bar
Example bar written (foo invalidated) Example better-foo written (bar is still a good example)
Code changed to match bar - oops, now foo doesn't check out Code changed to match better-foo (and bar continues to check out)
Update foo to be better-foo
最近坏掉的例子被重写以便匹配一个理想的开发顺序,在这个过程中不需要重写任何例子。但是为什么?在上表的左列,新的例子foo没有用于驱动开发,只是作为检查。对于驱动开发来说是最佳的可能对于检查来说不是最佳的。
假设软件系统开发切面层(shearing layers),切面层的接口通常是不会改变很大的。为了可维护性,在修改时移植坏掉的例子到界切面层是有意义的。取代一个例子对应一个类的一个方法的做法,我们现在使用一个例子对应整个子系统。那可能会很糟糕 - 想想调试 – 但是它减少了维护的负担,甚至能提供关于子系统的行为的完整文档的好处。
我希望人们分清楚两个角色 – 指引不远的将来和重新检查过去 – 会发现有建设性的知识。例如,什么时候编写面向技术的“改变探测器”(而这些与指引编程没有任何关系)可能会有用?
我在上面说的测试驱动开发是“期中一个适合”今天的主题的东西。那么其他适合的是什么?我不知道。EDD是否是最合适的?(是否最近可能发生革命性的改变?)我也不知道 – 我要依赖那些善于打破旧习的人来帮我找出来。对此我将非常感兴趣。