确保有效的测试
一旦用例被适当的设置并且开发团队就他们所扮演的角色达成共识,这些用例就成为方案中其他部分的基础。实际上,这是最好的利用它们所提供功能的方法。
工程团队建造一个开发方案,其中至少要包括:一份将要被建造的组建的清单,以及每一个组建的时间期限。清楚的描绘主用例的特性需求和实际工作特性的组件必要性之间的关系是非常重要的。
识别这些核心组件并且定义它们的用例是非常关键的步骤,它使得应用程序功能性的早期测试变成可能。如果该核心组件能够在开发周期的初期被完成,那么测试人员就能够开始为基本的规则集合撰写测试脚本并且确认该工具功能的有效性。
在我们的例子中,系统用例“运行代码复审”使得测试人员能够为该核心功能制定能够测试计划,甚至可以在代码被编写出来之间就实现这一点。测试人员还可以为主流程和可选项目创建一套手工测试脚本。
测试类型
最简单的测试形式,同时也是非常有效的一种测试形式,就是聚集一大批受过良好训练的用户来针对该应用程序的各种不同特性来进行测试和演练,并且将测试结果(发现的问题和缺陷)报告给代码开发团队。这种确认形式很简单:拥有越多的用户,就会检查出更多的缺陷。不同的用户群将用不同的方式使用该工具并且进一步增加被检查出来的问题的数量。然而,有一些与此相关的问题。直到该软件为用户使用做好准备的那一刻之前,我们都有可能没有足够的时间来开展广泛的测试计划了。不同的用户可能使用不同的产品。更重要的是,完全依靠人工是非常昂贵而且非常不可靠的。
还有更多的事情需要考虑。如果没有一个清楚的测试计划,就不可能采取同样的测试方法来对不同版本的应用程序中的相同特性加以测试。如果没有测试工具的协助,对于每一次测试我们所采取的测试步骤将会大不相同。并且,我们将会疏漏一下很少用到的,但却是潜在的重要的情节。
手动测试和回归测试
手动测试 是指以确定一个特定的系统相应为目标的一套动作。手动测试的另外一种选择就是自动测试。两者都属于功能测试的类型.自动测试意味着您使用一个专门的工具或者一批脚本来对一套应用程序组件进行测试,记录应用程序的反应,将其与想定值进行比较,从而决定测试是否成功。所有这些工作都没有人工干涉。自动操作使得您可以一遍又一遍的重复同一项测试,具有人工永远无法达到的精确性。自动操作功能测试的例子包括IBM Rational Robot以及IBM Rational Functional Tester。
回归测试,用来衡量应用程序的质量,既可以手动处理也可以自动处理。您能够从自动功能性测试或者自动开发者测试(详见下文)中聚集一组回归测试组合工具。可靠的回归测试的关键因素就是景区的再现这些测试。因此,在被称作测试脚本的文档精确的定义测试步骤,并且在每一个回归测试中严格的按照这些步骤操作是非常必要的。在此之后,您就可以放心的使用这些测试结果,既不必担心有问题报告,也不必再去衡量其质量了。
测试的成功与否同您在制定测试计划、文档化手动测试和自动测试上所投入的时间长短是有着密切的联系的。下面是一些实现有效测试的具体的建议:
根据用例制定您的测试计划。首先开始测试主用例流程,然后扩展到可选流程。正如前面所描述的,关键是保持您的用例中的适当的粒度和模块性。
通过测试计划来组织您的手动测试,通过第一批测试就开始采用一种统一的方法记录和分析测试结果。重复的、统一的操作(即使是手动的)也将会提高您工作的质量。
自动测试首先具有相对简单可行的执行路径,但是每一次运行它都需要大量的入口数据。运用现成的数据池来完成测试脚本(例如,进行数据驱动测试)。
开发者测试
将用例转换为有效的测试通常会遇到一个大的障碍:代码底层中的一大块部分直到开发周期的后期才能够提供给功能测试。因此,如果一些组件在被组装进正在运行的应用程序之前就被测试将是一件好的事情。而这正是开发者测试所符合的。
开发者测试是一套关注于提高代码质量的活动,它经常被开发者使用。开发者测试包括两个主要方面:
自动化单元和组件测试。包括代码评审,单元或组件测试,以及代码覆盖分析。
手动测试和调试。包括运行跟踪,声明,内存泄漏检测和内存用法分析,性能评测,线程分析,等等。
自动批处理测试可以使用例如JUnit工具——一种集成在IBM Rational应用程序开发器里的代码复审工具,也可以使用IBM Rational PurifyPlus提供的附加的方法来确保高质量的软件。在开发环境下找到并且修改缺陷就意味着在后来会出现更少的功能性错误。并且可以节省出更多的时间来编写代码和引介更多的自动控制。另外,拥有可靠的可重复性的自动单元测试和代码复审,可以使您收集到关于代码质量的有价值的方案,获得前面所描述的一样的好处。
对于大多数组织,实现开发者测试的主要障碍就是对所需要工具的学习曲线。通常,个体的开发者测试工具注重于软件质量中某一个相对狭窄的方面。如果团队成员不具备自动开发者测试的经验,那么如何找到合适的工具和决定采用何种类型的测试就成为呈现在我们面前的巨大的挑战。因此,开发计划不应当仅仅将时间投入到开发和调试应用程序组件上,也应当将时间和资源投入到培训、设置、分析和报告有关执行自动开发测试方面。这一初期投资将会很快的带来回报,它将使得测试团队检测更少的功能性错误。它同样也会提高团队成员理解代码原理的水平。
下面是一些关于以开发者测试为开始的建议:
如果您即将进行单元测试,那么在运行单元测试的同时开始收集代码覆盖数据,从而对整套单元测试进行完全的评估。
如果您即将开发C++应用程序,那么请您运行关键用例,并且通过工具对动态内存分配进行分析。内存恶化的问题是本地C++应用程序的一个关键的方面,也是造成许多意想不到的和难于再现的缺陷的根源。
至少在每一个合成结构中的组件内收集执行的基线,并且随时监视执行的过程。
如果您即将开发一个Java/J2EE应用程序,那么请您在一组基本测试中监视内存使用情况和内存中的对象类型。
在开始时应用一把最重要的静态分析规则,将它们应用于每一个结构中,并且不断向您的代码底部添加更多的规则。这必将会减少运行结果中出现的错误。
开发者测试并不会取代功能回归测试,手动的或者自动的。它只是通过在开发环境中检测问题,从而在整体上提高了测试的效率,因为在这时修改起来相对更加容易。
积极测试和消极测试
积极的测试将关注点放在应用程序主流程的确认上,正如用例文档中所定义和区分出的优先次序那样。消极的测试则通常关注于那些应用程序性能极限的测试方面(例如,“破坏应用程序”)。
在我看来,一份好的测试计划应当明确的关注于确认用例路径,而不是包括极限测试。通常,您可以通过数据驱动测试来对极限进行评估,数据驱动测试应用不同的数据集来对某个单一的实例进行测试,这是为了确定应用程序对于特定问题和异常而不是标准的参数集的反应。
下面我来谈我的最后一项策略。