集成测试,也叫组装测试或联合测试。在单元测试的基础上,将所有模块按照设计要求(如概要设计文档)集成为子系统或系统,是单元测试的逻辑扩展。最简单的形式是:两个已经测试过的单元组合成一个组件,并测试它们之间的接口。
集成测试中,我们主要关注的是以下内容:
在把各个模块连接起来时,穿越模块接口的数据是否会丢失;
各个子模块组合起来,能否达到预期要求的功能;
一个模块的功能是否会对另一个模块的功能产生不利的影响;
全局数据结构是否有问题;
单个模块的误差积累起来是否会被放大,从而达到不可接受的程度。
在集成测试时,我们需要关注被测模块的实际调用情况,并结合模块之间的接口来进行测试。而无需过于关注其内部实现(内部实现已在单元测试验证了)
常见接口类型
我们已经知道,集成测试关注的是模块之间的接口。可以将“接口”作为切入点。纵观模块之间的接口,我们可以归纳为以下几种类型:
通信协议:两个模块之间通信采用的是标准的或者自定义的协议;协议中即包含数据部分,又包含控制部分;而大部分实现将数据与控制通过一条链路来传递,往往通过不同的消息包进行分离;
调用关系:模块A调用模块B,实际上是由模块A向模块B发出了一条控制指令,这里数据传递体现的不是很明显,往往体现为参数与返回值;
文件、数据库、队列、第三方中间件等:表现的主要是数据的传递;
共享资源:比如共享一段“存储区域”,其中涉及的关键资源主要是“锁”了;这样的两个模块在运行时往往分布到不同的进程或者线程中,表现为对资源的竞争,以及数据的共享。
同步:一个模块的运行需要另外一个模块的触发,双方往往存在“信号”等通知机制,也可以理解为一种特殊的控制方式。
集成测试思路
明确了测试对象以后,就可以按照一般的测试方法设计和实施测试了。可按如下思路进行测试:
找出系统中的各种接口,如需要传递哪些数据?存在哪些控制指令?如数据(协议包)中字段取值,指令参数变化等;
将不同的控制指令等划分等价类,找出每类的代表,就得到了测试数据,让每类数据流与控制流均通过接口一次,从而实现接口测试的完全性;
另外,也要考虑模块的集成能否准确体现业务上的关联?各个模块是否具备其角色的全部属性和接口?
当然,集成测试不会太关心业务或者需求,那是系统测试的事了。但此时想想,往往能够得到意外的收获。
测试方案是一个重要的活动,其包含了对测试对象的分析,采用的集成策略,以及设计的各种测试用例等。测试方案文档应该按照公司规定的模板进行编写,并采用测试方案和测试报告结合的方式,最后将测试结果的分析追加到测试方案中。测试方案应包括以下的主要内容:
被测特性的分析,即对整个测试的对象做个简要而精准的分析说明;如测试的是一个程序,则应说明该程序的主要功能和特征;
采用的集成策略,如自顶向下或自底向上的集成策略,并说明采用此种策略的原因和理由;
测试对象的详细描述和设计测试用例,说明设计的思路。这里的对象就是具体的测试内容,如两模块之间的的接口;
测试结果的分析,测试完成后,根据测试中发现的问题,应对每个测试对象的结果进行分析和说明。并在最后说明整个测试情况,发现的缺陷数量,各种等级缺陷的分布情况,以及缺陷清单。
测试的实施包括两个部分的内容;
编写测试驱动和桩程序;
根据设计的测试用例进行测试。
在测试过程中,根据集成策略的不同,需要编写测试驱动程序或桩程序。将未经测试的但需要调用的模块用桩程序代替;将未经测试但需要使用的上级模块用驱动程代替。对已经通过了测试的模块,则可以直接使用原程序。
测试中应该注意对测试驱动和桩的保存,以便后期进行回归测试。因此在编写的时候就考虑该需求;并且要有一定的可维护性,以便规格变更时,进行简单修改即可应用到测试。
测试驱动和桩程序编写好后,就可以根据测试用例设置测试数据,对测试的模块接口等进行测试和确认。并将发现的所有软件缺陷录入到CQ缺陷库,并通知相应的开发人员进行修改。
如此重复直到完成所有模块的测试。
一般来说,都是考虑基于系统测试功能分解的集成测试,通过树结构或文字的形式表示分解出的模块功能图。
树形图表示一个拥有6个模块的功能分解树,集成的顺序有多种选择:从树顶开始向下(自顶向下集成)、从树底开始向上(自底向上集成)、自顶向下和自底向上两种方式组合起来(三明治集成,或叫混合集成)。这些集成顺序都是假设模块已经通过单独测试。
自顶向下集成从主程序(树根)开始。所有被主程序调用的下层模块都作为“桩模块”出现,桩模块就是模拟被调用模块的一次性代码。一般来说,测试人员要开发桩模块,开发了主程序所需的所有桩模块之后,就可以测试主程序,就像它是一个独立模块一样,使用适当的黑盒测试和白盒测试技术进行测试。
上图所示为一个系统的集成过程。方框都是用来代替对应模块的桩程序,首先对主程序A进行测试,用三个桩程序代替其调用的三个模块,然后逐步采用实际的模块取代这些桩模块。如果新加入的实际模块调用其他的模块,则也需要为其开发相应的桩模块。如此反复,直到所有模块都被集成。
为了能够准确地实施测试,应当让桩程序正确而有效地模拟子模块的功能和合理的接口,不能是只包含返回语句或只显示该模块已调用的信息,而不执行任何功能的哑桩程序。如果不能使桩程序正确地向上传递有用的信息,可以采用以下解决办法:
将很多测试推迟到桩程序用实际模块替代了之后进行;
进一步开发能模拟实际模块功能的桩程序;
自底向上集成和测试软件
自顶向下集成方式的缺点是需要建立桩程序。要使桩程序能够模拟实际子模块的功能十分困难,同时涉及复杂算法,真正输入/输出的模块一般在底层,他们是最容易出问题的模块,到测试和集成的后期才遇到这些模块,一旦发现问题导致过多的回归测试。