我曾经和来自不同开发机构的人探讨过关于他们如何管理软件开发,如何组织,他们遵循什么样的开发实践,以及什么样的开发实践真正有效。工作在小团队的大部分人都没有人手帮他们测试程序,因为测试人员们不是真正开发软件的人,所以通常觉得他们是多余的。这就意味着程序员许要自己测试他们的软件 – 或者用户来测试。
敏捷团队中的测试人员能做什么?
很少敏捷团队会觉得需要测试人员。测试人员被看作是瀑布时代的产物(需求、设计、编码、测试)。在XP团队,每个人都是程序员,每个程序员都要负责测试自己的代码,写自动的单元测试,使得用户需要的验收测试自动化。Scrum根本没有定义测试要做什么 – 团队会最终找到解决方案,因为他们会检阅自己并调整自己,以获得最佳的实践。
如果程序员已经测试了他们的代码(也通过结队的方式进行了代码审查),那么他们需要测试人员做什么呢?
Janet Gregory和 Lisa Crispin写了一本书来说明敏捷团队中测试人员的作用,它向程序员和测试人员说明测试人员是如何配合敏捷开发的,但这仍然没有改变大多数团队的看法,尤其在“工程驱动的文化”(程序员创立的创业团队)中更是如此。
他们的论点是敏捷团队的步伐相对于测试人员来说太快了,黑盒测试人员们仅仅通过写测试计划,通过手动的测试代码来测试,或许要不断的更新他们的质量中心或Selenium UI回归测试,这些都不可能追得上在短时间内就要发布新功能的团队的进度。如果测试人员不会用Fitness或Cucumber写验收测试,或者没有足够的业务知识帮助填补客户/产品拥有者的空当,不能回答程序员的问题的话,那么他们又有什么优势呢?
这个问题在持续开发中更为显著,一些公司如IMVU和Facebook,使得某种编程实践变得流行起来,他们查看自己的工作,写自动测试用例,查看代码看看测试是否通过了,更新都是很快的,然后自动发布到在线系统中去。
让用户来测试你的代码
一些公司把持续开发看作是“众包”(crowdsource)他们测试的机会 – 让他们的客户来为他们测试。这实际上很有竞争力。然而也很难用这种方法写出可靠安全的软件 – 可能也是不可能的。针对持续发布给用户的系统的质量问题,James Bach有一篇批评的文章,是关于他们花了20分钟时间去测试一个持续部署的程序,就发现在很短的时间内就发现了问题。
有一些持续部署的公司更小心些,他们按照Etsy/Flickr的做法,在晚上上线:持续的发布更新,但是在用户量很大之前就进行了测试,他们还会密切关注结果。
然而,很重要的一点是用户只能测试某些功能,事实上,也只有用户可以测试它们:一个功能是不是有用,一个功能是不是可用的,他们需要什么信息才能正确的完成一个任务,工作流程应该如何优化。这才是对比测试所应该达到的效果 – 通过实验不同的想法,功能和工作流程,收集数据,然后找到用户最喜欢什么,以及他们不喜欢什么。去尝试不同的方法,并获得反馈。
但是你不会问你的客户他们是否测试完毕了,代码是否有效,系统是否稳定安全,负载大的情况下是否正常工作。
你需要从测试团队中获得什么?
就算是最好的,最负责的,最有经验的程序员都会犯错。在我们公司,每个人经验都很丰富,其中有些人工作了10-15年以上了。他们很仔细的测试代码,每次check-in之后都会更新自动测试用例。在持续集成过程中这些测试都会运行 – 我们非常依赖于这些测试(现在已经有成千上万的测试用例了,并有较高的覆盖率),静态分析的缺陷核查,以及安全核查工具来对付基本的代码错误。所有的更改都会让另外一个高级的程序员来核查,从来没有过例外。
但就算有好的方法和工具,优秀的程序员还是会犯错:一些细微的问题(不一致,界面问题,数据转换和建立问题,没有编辑等问题)以及一些基础的问题 (负载下的运行失败,同步问题,缺少需求,规则错误,异常处理中的错误)。我想确保在用户发现错误之前发现大部分(尽管不是全部)的错误。程序员也是。
这也就是测试团队起作用的地方了。我们拥有一个小的,但是经验丰富的,有特别专长的测试团队。一个测试人员专注于验收测试,验证功能需求,可用性,以及业务工作流程。另一个测试人员专注于功能的回归测试以及业务规则的正确性和覆盖率,找到程序员测试用例中的规则漏洞,并在API层让集成测试自动化。还有个测试人员主要做操作测试,压力测试,以及soak test来找到峰值和垃圾回收的问题,破坏测试 – 尽可能的破坏系统。当其中一个人不在的时候,他们也知道如何担负他人的职责,但他们有自己独特的专长和技能,以及自己的解决问题的方法。
当我们初次建立系统的时候,我们有一个更大的测试团队,主要通过写测试计划,详尽的手工测试核查表,在UI层编写自动的回归测试,来测试覆盖率和可靠性。但用这种方法浪费了许多时间。
现在我们更依赖于程序员针对功能覆盖率和回归保护自己编写的自动测试用例。我们的测试团队将精力更多的放在探索性的功能以及操作,基于风险和以用户为中心的测试中去了,以找到最重要的缺陷,发掘系统的弱点。我们都喜欢这种方法,因为我们在测试中找到了真正的重要的缺陷,那些躲得过代码审查和单元测试的缺陷。
当程序员作了更改后,测试人员马上测试更改。他们和程序员一起结队去测试新功能,和程序员一起运行模拟来找出运行错误,竞态条件(race condition)以及现实世界中的时间相关的问题和工作流程问题。他们摧毁系统以确保错误探测和错误恢复机制是成功的。他们测试安全功能,和顾问一起搭建和管理测试。他们也和操作人员一起,和新用户以及新部门处理集成检查。他们和团队的其他人员一起以非常快的速度,每两周就发布到在线系统(有时更频繁)。
测试团队也会负责软件的发布。他们将每个发布都集中在一起,查看依赖,决定发布什么时候进行,什么将会发布,什么不会发布,他们会核对我们是否完成了整个团队同意去做的更改,他们会测试过去的测试用例还有数据转换测试,最后和操作人员一起发布到在线系统中去。
他们没有让整个团队的进度慢下来,他们也没有阻碍我们发布软件。他们确保了软件上线的时候正常工作。
测试人员找到更多的缺陷
我为高可靠性,高集成性的业务工作了很久,没有测试人员是不可取的 – 犯错的代价太高了。我不认为你可以创建真正的软件,而不需要人来测试它。除非你是在创业的早期,还处于概念的迸发期,或者你只有一个小团队,仅仅为内部使用而写的软件(可能你也没堵到这篇文章),否则你需要人来为你测试系统以确保系统是正常运行的。
不管你如何工作,不管你用什么方法 – 敏捷开发还是瀑布开发方法,都改变不了需要测试人员的事实。如果你推进得太快了,测试人员需要加快步伐,以适应能够获取信息的方式。好的测试人员可以做到的。
我就算再蠢也不会认为测试团队能找到所有的缺陷——虽然这是他们的工作。当然,我希望测试人员会在客户发现之前找到明显的错误。
我需要为他们做的也正好帮自己回答了一些重要的问题:我是否可以发布了?有什么还是粗糙的或者不稳定的或者不完善的?什么需要迟些发布?什么需要更进一步审查或者重写?设计中什么地方很薄弱?什么地方没有自动测试用例?哪里需要更好的测试工具?什么功能难以理解或不一致或者很难搭建?什么消息漏掉了,或者容易误导人的?我们是否做太多了,做太快了?我们是否需要更改设计,代码,还是设计或编码的方式,以使得系统更好用,更可靠?
测试不能提供所有的信息,但能提供一部分。好的测试可以提供许多有用的信息。——James Bach (Satisfice)
没有测试人员,你不仅发布了一些你本来应该没有错误的代码,你也失去了一些重要的信息,譬如你的软件真的那么好吗,例如你可以做什么让它更好。如果你想构建好的软件,那么现在你的机会来了。