1 测试自动化
软件测试的工作量很大,但测试却极有可能应用计算机进行相当一部分自动化的工作,原因是测试的许多操作是重复性的 、 非智力创造性的 、 需要细致注意力的工作,而计算机就最适合于代替人类去完成这些任务。
测试自动化会对整个开发工作的质量 、 成本和周期带来非常明显的效果。一些适于考虑进行自动化的测试工作为:
(1)测试用例的生成(包括测试输入 、 标准输出 、 测试操作指令等)。
(2)测试的执行控制(包括单机与网络多机分布运行 、 夜间及假日运行 、 测试用例调用控制 、 测试对象 、 范围 、 版本控制等)。
(3)测试结果与标准输出的对比。
(4)不吻合的测试结果的分析 、 记录 、 分类和通报。
(5)总测试状况的统计,报表的产生。测试自动化与软件配置管理是密不可分的,与测试有关的资源都应在配置管理中统一考虑。
2 面向对象的测试
传统的软件测试策略是从 “ 小型测试 ” 开始,逐步走向 “ 大型测试 ” 。即从单元测试开始,然后进入集成测试,最后是系统测试。
面向对象程序的结构不再是传统的功能模块结构,作为一个整体,原有集成测试所要求的逐步地将开发的模块搭建在一起进行测试的方法已成为不可能。而且,面向对象软件抛弃了传统的开发模式,对每个开发阶段都有不同以往的要求和结果,已经不可能用功能细化的观点来检测面向对象分析和设计的结果。因此,传统的测试模型对面向对象软件已经不再适用。
2.1 面向对象测试模型
面向对象的开发模型突破了传统的瀑布模型,将开发分为 OOA 、 OOD 和 OOP 三个阶段。针对这种开发模型,结合传统的测试步骤的划分,可以把面向对象的软件测试分为:面向对象分析的测试 、 面向对象设计的测试 、 面向对象编程的测试 、 面向对象的单元测试 、 面向对象的集成测试和面向对象的系统测试。
2.2 面向对象分析的测试
传统的面向过程分析是一个功能分解的过程,是把一个系统看成可以分解的功能的集合。功能分解分析法的着眼点在于一个系统需要什么样的信息处理方法和过程,以过程的抽象来对待系统的需要。而面向对象的分析直接映射问题空间,将问题空间中的实例抽象为对象,用对象的结构反映问题空间的复杂实例和复杂关系,用属性和操作表示实例的特性和行为 。 OOA 的结果是为后面阶段类的选定和实现 、 类层次结构的组织和实现提供平台。因此,对 OOA 的测试,应从以下方面考虑:
(1)对认定的对象的测试。
(2)对认定的结构的测试。
(3)对认定的主题的测试。
(4)对定义的属性和实例关联的测试。
(5)对定义的服务和消息关联的测试。
2.3 面向对象设计的测试
传统的结构化设计方法,采用面向作业的思路,它把系统分解以后,提出一组作业,这些作业是以过程实现系统的基础构造,把问题域的分析转化为求解域的设计,分析的结果是设计阶段的输入。而 OOD 以 OOA 为基础归纳出类,并建立类结构或进一步构造成类库,实现分析结果对问题空间的抽象。
由此可见, OOD 不是 OOA 的另一思维方式,而是 OOA 的进一步细化和更高层的抽象, OOD 与 OOA 的界限通常是难以严格区分的。 OOD 确定类和类结构不仅是满足当前需求分析的要求,更重要的是通过重新组合或加以适当的补充,能够方便地实现功能的重用和扩充,以不断适应用户的要求。因此,对 OOD 的测试,应从如下三方面考虑:
(1)对认定的类的测试。
(2)对构造的类层次结构的测试。
(3)对类库的支持的测试。
2.4 面向对象编程的测试
典型的面向对象程序具有继承 、 封装和多态的新特性,这使得传统的测试策略必须有所改变。
封装是对数据的隐藏,外界只能通过被提供的操作来访问或修改数据,这样降低了数据被任意修改和读写的可能性,降低了传统程序中对数据非法操作的测试。
继承是面向对象程序的重要特点,继承使得代码的重用性提高,同时也使错误传播的概率提高。
多态使得面向对象程序对外呈现出强大的处理能力,但同时却使得程序内 “ 同一 ” 函数的行为复杂化,测试时不得不考虑对于不同类型参数具体执行的代码和产生的行为。
面向对象程序是把功能的实现分布在类中。能正确实现功能的类,通过消息传递来协同实现设计要求的功能。因此,在 OOP 阶段,忽略类功能实现的细则,将测试的焦点集中在类功能的实现和相应的面向对象程序风格,主要体现为以下两个方面。
(1)数据成员是否满足数据封装的要求。
(2)类是否实现了要求的功能。
2.5 面向对象的单元测试
传统的单元测试的对象是软件设计的最小单位 —— 模块,测试依据是详细设计说明书。单元测试应对模块内所有重要的控制路径设计测试用例,以便发现模块内部的错误。单元测试多采用白盒测试技术,系统内多个模块可以并行地进行测试。
对于面向对象的软件,单元的概念发生了变化。每个类和类的实例(对象)封装了属性(数据)和操纵这些数据的操作,而不是个体的模块,最小的可测试单位变成了封装的类或对象。因此,单元测试的意义发生了较大变化。不再孤立地测试单个操作,而是将操作作为类的一部分。
2.6 面向对象的集成测试
传统的集成测试,有两种典型的集成策略:
(1)自顶向下集成,它从主控模块开始,按照软件的控制层次结构,以深度优先或广度优先的策略,逐步把各个模块集成在一起。
(2)自底向上集成,从 “ 原子 ” 模块(即软件结构最低层的模块)开始组装测试。面向对象的软件没有层次控制结构,传统的自顶向下和自底向上集成策略已无太大意义。
此外,一次集成一个操作到类中(传统的增量集成方法)通常是不可能的。对 OO 软件的集成测试也有两种不同策略:
第一种称为基于线程的测试,集成系统的一个输入或事件所需的一组类,每个线程被集成并分别测试,并使用回归测试以保证没有产生副作用。
第二种称为基于使用的测试,首先测试那些几乎不使用其他类的类(称为独立类)并开始构造系统,在独立类测试完成后,下一层的使用独立类的类(称为依赖类)被测试。这个依赖类层次的测试序列一直持续到构造完整个系统。
2.7 面向对象的系统测试
通过单元测试和集成测试,仅能保证软件开发的功能得以实现。但不能确认在实际运行时,它是否满足用户的需要。为此,对完成开发的软件必须经过规范的系统测试。系统测试应该尽量搭建与用户实际使用环境相同的测试平台,应该保证被测系统的完整性,对临时没有的系统设备部件,也应有相应的模拟手段。系统测试时,应该参考 OOA 分析的结果,对应描述的对象 、 属性和各种服务,检测软件是否能够完全 “ 再现 ” 问题空间。
系统测试不仅是检测软件的整体行为表现,从另一个侧面看,也是对软件开发设计的再确认。
面向对象测试的整体目标是以最小的工作量发现最多的错误,与传统软件测试的目标是一致的,但 OO 测试的策略与传统测试有很大不同。这种不同主要体现在两个方面,
第一,测试的焦点从过程构件(模块)移向了类;
第二,测试的视角扩大到了分析和设计模型。