当前大部分的测试工具是软件的功能性测试功能(也被称为记录/回放工具),如Rational的Robot和Mercury 的Winrunner等。记录/回放工具的缺陷使我们在测试中不能过分依赖它。
缺陷:
记录/回放工具能够记录下用户和应用程序交互时的击键和鼠标的移动。击键和鼠标的移动都被记录成一个脚本,然后可以在测试执行期间“回放”。虽然这种方法对特定的情形是有益的,但是记录/回放功能大约仅仅是其全部功能的1/10。记录/回放脚本在首次记录生成之后必须要进行修改。对功能性测试的修改主要集中在通过GUI进行验证的测试,也称为黑箱测试。只是通过记录/回放直接创建脚本有一些严重的局限和缺点。
1.硬编码的数值。记录/回放工具根据用户的交互动作来生成脚本,其中也包含了从用户界面输入或者接受的任何数据。让数值在脚本中“硬编码”会给以后的维护工作带来问题。如果应用程序的用户界面或则其他方面发生了变化,那么硬编码的数值会导致脚本非法。例如:在记录期间生成脚本的时候,输入值、窗口坐标、窗口标题和其他值可能也被记入生成的脚本代码中。如果在应用程序中,这些值中任何一个发生了变化,那么测试执行期间这些固定的数值就成了罪魁祸首:测试脚本与应用程序的交互是错误的,或者彻底失败。另一个可能出问题的硬编码数值是日期戳。如果测试工程师在测试过程中记录了当前日期,那么几天后再次运行这个脚本会导致失败,因为脚本中包含了硬编码的数值不再和当前的日期匹配。
2.非模块化的、不易维护的脚本。测试工具产生的记录/回放脚本通常不是模块化的,维护起来非常困难。例如:可能许多测试过程都引用了一个WEB应用程序中特殊的URL,如果脚本中使用了硬编码的URL,那么这个URL的改变将会导致大量的脚本作废。在一个模块化的开发方法中,只有一个函数中引用,或则包装了这个URL。随后各个是引用它的脚本会调用这个函数,这样URL的任何变化只需要改动一处就可以了。
3.缺乏可重用性的标准。测试过程开发面临的最重要的课题之一是可重用性。如果测试创建专门的标准,明确地要求开发可复用的自动测试过程,那么就会极大地提高测试组的工作效率。如果把用户界面部分的测试封装进模块化的、可重用的脚本文件,供其他脚本调用,那么当用户界面经常不断变化的时候,脚本的维护工作量就会大大降低。
创建一个可重用的函数库时,最好把诸如数据读取、写入和确认、导航、逻辑以及错误检查功能分别归到不同的脚本文件中。自动测试开发的指导方针应该大量的借用高效的软件开发工作所遵循的原则。遵循与测试工具生成脚本的开发语言最接近的开发语言的指导方针,这是一个很好的时间。例如:如果工具生成的脚本类似于C语言,那么应该遵从C语言的开发标准;如果工具生成的脚本类似于BASIC语言,那么应该遵从BASIC语言的开发标准。
在自动测试开发中,只使用记录/回放方法生成的测试脚本是很难维护和重用的,这是明显的事实。虽然也有少数的情况,可使用未经加工的脚本,但是对于大多数情况,如果不在记录之后修改脚本,那么在测试执行期间,测试工程师会由于正在测试的应用程序的变化而反复记录脚本。使用记录/回放工具可能带来的潜在收益,一定会被不断重建测试脚本的无奈所抵消。这会使测试人员产生很强的挫折感,并且会对自动测试工具感到不满。
为了避免未经加工的记录/回放脚本带来的问题,应该建立可复用的测试脚本的开发方针。未经过加工的记录/回放脚本并不表示有效的自动测试。
解决方法:自制开发一个测试工具
为了去除自动测试工具的局限性和对核心组件进行更深入的测试,可以自制开发一个测试工具。这种定制的测试工具一般用健壮的程序语言编写,例如:独立的C++ 或则Java程序,定制的测试工具一般比自动测试工具生成的脚本运行的速度更快,也更灵活,因为这些脚本受限于测试工具的特定环境。
我们举一个适合用定制测试工具来测试任务的例子,假设一个应用程序的用途使根据用户提供的信息进行计算,并且把计算的结果生成报告。计算过程可能是复杂的,并且可能对各种输入参数的不同组合是敏感的。这可能会有数百万种潜在变化,这些变化会产生不同的结果,因此,对计算过程进行全面的测试才能保证计算的正确性。
手工开发和验证大量的计算性测试用例是非常浪费时间的。在大多数情况下,通过界面执行大量的测试用例也是非常缓慢的。此时一个更高效的方法是自制开发一个测试工具,它会直接针对应用程序的代码(一般是直接针对用户界面层之下的核心组件)执行测试用例。
另一种使用自制测试工具的方法是:对照遗留组件或者系统来比较新组件。两个系统通常使用的数据存储格式是不同的,用不同的技术实现的用户界面也是不同的。此时,为了在两个系统上运行相同的测试用例并且生成比较报告,自动测试工具需要一种特殊的机制来复制自动测试脚本。在最坏的情况下,单个测试工具不能同时兼容两个系统,此时两套测试脚本必须用两种不同的自动测试工具来开发。一个更好的替代方案是自制生成一个定制的、自动测试工具,它把两个系统之间的差异封装进独立的模块,这样我们就能够设计出同时适用于两套系统的测试。自制的自动测试工具可以把遗留系统产生的测试结果作为基线,并且通过比较两套结果和输出它们之间的差异来自动地验证新系统产生的结果。
达到上述目的的一种方法是使用自制工具适配器模式。自制测试工具适配器是一个模块,它通过转换或者改造正在测试地每个系统使之和自制测试工具兼容,这样自制测试工具可以通过适配器在系统种执行预定义地测试用例,并且把结果存储为相互之见可以自动比较地标准格式。对于每个开发出来地适配器必须能够直接和系统进行交互和针对系统执行测试用例。用一个自制测试工具测试两个系统需要不同地适配器并独立调用两次自制测试工具,每个系统调用一次。两次调用的结果应用保留起来并进行比较。图示描述了针对遗留系统和新系统执行测试用例的定制测试工具。
通过为每个系统使用不同的适配器,相同的测试用例可以用于多个系统。针对遗留系统的适配器来产生一组基线结果,这个结果用于和新系统的结果比较。
为了完成他们的任务,自制的测试工具适配器首先获得一组测试用例,然后按照顺序执行这些用例,从而直接测试每个系统的逻辑,绕过了用户界面。绕过用户界面使性能得到了优化,使得测试用例的吞吐量最大化。它还具有更高的稳定性。如果自制测试工具依赖于用户界面,那么用户界面的任何变化(在开发生命周期种,用户界面经常会经过多次修改)都可能导致自制测试工具对缺陷的漏识别。检查这样的结果会浪费大量宝贵的时间。
每个测试用例的执行结果被存储在一个或者多个结果文件中,存储的格式使相同的。与正在测试的系统无关。保存结果文件是为了与随后运行的测试产生的结果进行比较。比较可以有一个定制生成的结果工具来完成,这个工具按照一定的规则读取和评估结果文件,并且输出发现的所有错误或者差异。如果我们把结果格式化,那么也可以通过标准的“file diff”(比较文件差异)工具对它们进行比较。
与所有的测试类型一样,自制测试工具使用的测试用例可能使相当复杂的,特别是当自制测试工具所测试的组件使用于数学计算或者科学计算的时候,利用自制的测试工具就可以覆盖大部分的测试。