因此,最合理的引入测试的阶段是在需求阶段。需求阶段的测试工作的重点是如何定义测试计划,如何定义接受测试并获得客户的认可,在需求阶段结束的时候,必须保证所有的需求都是可测试的,都拥有测试用例,需求阶段另一个重要的测试任务是准备构建测试沙盒,建立一个测试环境,以及这个软件项目所需要的测试数据;在设计阶段,测试工作的重点则在于如何定义各个模块的详细测试内容,最好的方式是实现测试代码,并构建测试框架,对于一些比较复杂的项目,甚至还需要编写一些测试工具。实践中我们发现,在XUnit的基础上扩展出一个测试框架是一种简单但又实用的方法。XUnit的重点是对自动化测试提供了一个通用的框架,捕获异常,记录错误和失败,并利用组合模式对Test Case和Test Suite进行管理。实际上,还有很多工作是可以在XUnit框架上继续开展的,例如,软件开发中是不是存在较为通用的测试用例?这样,你就可以定义一些抽象的测试用例,并以此作为测试框架的基础。再比如,我们希望每天晚上在进行日集成的时候,测试结果能够通过短信直接发送到负责人的手机上,那么我们可以在框架中嵌入这部分的功能。这些都属于对测试框架的积累。对一个软件组织来说,很有必要花费时间对测试框架进行积累。这可以简化测试的工作量,并提升软件的质量。
测试过程
我们一开始说,测试有其自己的过程,虽然XP并没有花费太多的笔墨来描述自己的测试过程,但经过细心的观察,我们可以发现,在XP中同样存在着一个测试过程:
这个过程是从用户故事(或者是我们在上一章中推荐的用例)开始的,用户故事不但为版本计划提供了需求,而且为接受测试提供了测试场景。而对于客户参与的接受测试来说,它为每一次的迭代提供了反馈,包括bug的反馈和下次迭代信息的反馈。只有客户认可了接受测试,软件才能够发布小版本。这是XP过程最高层次的测试过程。
在上文中,我们提到引入测试最好的时机是在需求分析阶段。因为测试生命周期的起源活动-测试计划和测试用例都需要需求的支持。我们再参考RUP的过程:
我们看到,RUP建议在先启阶段就开始测试活动。在开发过程的前期就进行测试活动,其目的是为了提高软件的可测试性。软件设计如果没能够考虑软件的可测试性,那么测试的成本就会升高,软件质量随之下降。有时候,单元测试或是组件测试是很难进行的。因此,我们需要专门针对类或组件的可测试性进行测试。例如,对于一个实现企业流程的组件,之间涉及到大量的状态、事件、分支选择等等因素。对这样的组件进行组件测试的代价是非常高的。如果能够在组件设计的时候,能够考虑到测试性,例如,将组件拆分为粒度更小的子组件,或是在组件中内嵌供测试使用的方法,能够直接操纵组件的状态。在设计时充分考虑可测试性,是降低测试成本的关键。而设计测试的源泉,正是先启阶段中对需求的分析。对流程组件测试的依据,正是源于项目涉众对流程的需求。
测试的一些实践问题
严格按照先维护测试,再维护代码的顺序要实现变更。在实践中,测试优先常常发生的一个问题是,设计变更影响到测试代码的时候,开发人员往往会绕过测试代码,直接修改代码。
在刚刚接触测试优先思路的时候,我严格按照先写测试的做法编写代码,但是当代码需要修改时,有时候只是一些非常小的修改,这时候我仍然保持原有的习惯,直接对代码进行了修改,在完成代码的修改之后,我突然意识到测试代码需要修改,于是我又修改了代码,由于只是一个小修改,我认为没有必要再运行测试了。这件事情很快被我遗忘了,但隐患就此埋下。到了两天后的集成测试时,测试程序捕捉到了这段代码的错误,经过调试,发现当时认为简单的修改忽略了一种极端的情况。定位错误,调试代码,并通过测试的时间远远超过了当初贪图省事节省的时间。所幸的是,代码在下一个检查点(集成测试)被发现出来。 完善测试网。在我学习并实践测试优先的时候,我所处的团队正处于项目的中期,已经有大量的没有实现测试的代码被创建出来,当时我采取的思路是,新编写的代码必须遵循新的测试方法,旧有的代码保持现状。这样做可以节省一定的成本,但是很快我们发现,投入力量把现有的代码加上测试是绝对值得的。加上测试的代码能够迅速回应变化,仅仅这一点,就值得我们重建测试网。此外,由于需要构建测试,我们还发现了原有代码中一些接口定义不合理或是不规范的地方。 而在另一些一开始就采用测试优先思路的项目中,往往遇到的问题是,随着项目的进展,后期的测试代码越来越优秀。这时候,我们需不需要对原有的测试代码进行改进呢?答案是肯定的,你一定会从中获益的,对于自动化测试来说,修改测试代码并重新运行测试的代价并没有你想象中的那么大。
文章来源于领测软件测试网 https://www.ltesting.net/