目录
1 软件测试概述
1.1 软件测试的目标
测试是为了发现程序中的错误而执行程序的过程;好的测试方案是尽可能发现迄 今为止尚未发现的错误的测试方案;成功的测试是发现了至今为止尚未发现的错 误的测试。
1.2 测试准则
所有测试都应该能追溯到用户需求;(测试用例设计依据)
应该远在测试开始之前就制定出测试计划;
80%的错误很可能是由 20%的模块造成。
应该从“小规模”测试开始,并逐步进行“大规模”测试;
穷举测试是不可能的;
为了达到最佳的测试效果,可以找独立的第三方公司进行测试工作。
1.3 测试方法
静态测试工具-PMD
静态方法是指不运行被测程序本身,仅通过分析或检查源程序的语法、结构、过 程、接口等来检查程序的正确性。
PMD:是一个代码检查工具,它用于分析 Java 源代码,找出潜在的问题:(在 Eclipse 中 安装 PMD 插件)
1)潜在的 bug:空的 try/catch/finally/switch 语句
2)未使用的代码:未使用的局部变量、参数、私有方法等
3)可选的代码:String/StringBuffer 的滥用
4)复杂的表达式:不必须的 if 语句、可以使用 while 循环完成的 for 循环
5)重复的代码:拷贝/粘贴代码意味着拷贝/粘贴 bug
2 测试方案
所谓测试方案包括具体的测试目的(例如,预定要测试的具体功能),应该输入 的测试数据和预期的结果。通常又把测试数据和预期的输出结果称为测试用例。 (记忆)
通常测试目的包含如下几种:
看测试对象是否满足需求规格说明书和概要设计,满足目前的要求及未来的发展 需求。
看测试对象是否满足概要设计说明书。
看测试对象业务流程的合理性和正确性(详细设计说明书)。
看测试对象的功能、兼容、性能、稳定性、安全测试,是否满足要求。
3 白盒测试
对单一模块测试内部结构是否和详细设计相同,使用黑盒法还是白盒法?如何设 计测试用例?
使用白盒测试法 常见白盒测试法:逻辑覆盖法、基本路径覆盖法
3.1 语句覆盖
选择足够的测试用例,使得程序中每一条可执行语句至少被执行一次。
分析:执行语句 sacbed
测试用例:A=2,B=0,X=任意实数 覆盖 sacbed
语句覆盖特点:语句覆盖对程序的逻辑覆盖很少。语句覆盖不能走过所有支路。 语句覆盖是很弱的逻辑覆盖标准。
3.2 判定覆盖
含义:不仅每个语句必须至少执行一次,而且每个判定的每种可能的结果都应该 至少执行一次。
所有判定分支:
(1) a 点判定为 T
(2) a 点判定为 F
(3) b 点判定为 T
(4) b 点判定为 F
测试用例:
Ⅰ. 满足(aTbF)
A=3,B=0,X=3
覆盖 sacbd 结果: x=1
Ⅱ. 满足(aFbT)
A=2,B=1,X=1
覆盖 sabed 结果: x
或者:
Ⅰ. 满足(aTbT)
A=2,B=0,X=4
覆盖 sacbed
Ⅱ. 满足(aFbF)
A=1,B=1,X=1
覆盖 sab
特点:比语句覆盖强,但对程序逻辑的覆盖程度仍不高。
3.3 条件覆盖
含义:不仅每个语句至少执行一次,判定表达式中的每个条件都取到各种可能的 结果。
所有条件:
(1)A>1 (2)A≤1
(3)B=0 (4)B≠0
(5)A=2 (6)A≠2
(7)X>1 (8)X≤1
如果语言具备短路特性,本测试用例,需要增加,测试 B !=0 和 X>1 的用例 A=3,B=1,X=6
条件覆盖特点:条件覆盖通常比判定覆盖强,因为它使每个条件都取到了两个不 同的结果,判定覆盖却只关心整个判定表达式的值。但也有反例,如第二组测试 用例。判定覆盖不一定包含条件覆盖,条件覆盖也不一定包含判定覆盖。
各种覆盖测试用例的设计方法:
语句覆盖:对流程图中的语句进行编号。设计足够用例覆盖。
判定覆盖:对流程图中的所有判定,罗列出真假两种情况,对不矛盾的判定进行 组合并设计测试用例。
条件覆盖:对流程图中的所有条件,罗列出真假两种情况,对不矛盾的条件进行 组合并设计测试用例。
3.4 判断/条件覆盖
选择足够的测试用例,使得同时满足判定覆盖和条件覆盖。即:使得判定表达式 中的每个条件都取到各种可能的值,每个判定表达式也都取到各种可能的结果。
3.5 条件组合覆盖
选择足够的测试用例,使得每个判定表达式中条件的各种可能组合都至少出现一 次。
条件组合覆盖特点:条件组合覆盖是前述几种覆盖标准中最强的。满足条件组合 覆盖标准的测试数据,也一定满足判定覆盖、条件覆盖和判定/条件覆盖标准。
缺点:条件组合覆盖标准的测试数据并不一定能使程序中的每条路径都执行到。 (测试数据都没有测试到 sacbd )
总结:
语句覆盖发现错误能力最弱。
判定覆盖包含了语句覆盖, 但它可能会使一些条件得不到测试。
条件覆盖对每一条件进行单独检查,一般情况它的检错能力较判定覆盖强,但有时达不到判定覆盖的要求。
判定/条件覆盖包含了判定覆盖和条件覆盖的要求,但实际上不一定达到条件覆 盖的标准。
条件组合覆盖发现错误能力较强, 凡满足其标准的测试用例,也必然满足前 4 种覆盖标准。
以上五种覆盖方法,基本上是依次增强的(除少数如:条件覆盖和判定覆盖) 。随覆 盖级别的提高,所需设计的测试用例数量也急剧增加,开销数量级的加大。
补充:路径覆盖
含义: 设计足够的测试用例,使得程序中的所有可能路径都至少被执行一次。 路径:见各种逻辑覆盖关系图右边
4 黑盒测试
常用黑盒测试方法:等价类、边界值分析
4.1 等价类法
等价划分:在输入数据中选择一些有代表性的数据进行测试。使其可能较多的 发现错误。
如何选择代表性的数据? ——多段函数的测试
思想:将输入的数据,分成若干个等价类。
假定:每类中每个值在测试中的作用等价于其它值。
从每个等价类中选一个代表值。这些代表值形成要选择的子集。
等价类:等价类就是功能相同或作用相同的一类数据。
如何划分等价类:根据程序功能提到的条件,划分多个等价类。例如输入大学生 年龄,范围 16-30
等价类有:有效的等价类,无效的等价类。
划分等价类启发式规则:
(1) 输入数据范围划分:如输入模特年龄,年龄要求 16~25 岁。
一个有效的等价类 两个无效的等价类
20岁 15岁 40岁
(2) 输入数据的个数划分:如要求输入 N=10 个数据.
一个有效的等价类 两个无效的等价类
N=10 N=8 N=12
(3)规定了输入数据的一组值,且对每个值处理方式不同。则根据这一组值进行划分出多个有效类,一个无效类. 如:输入必须为:“教授,副教授,讲师,助教”中一种.
四个有效的等价类 一个无效的等价类
典型用例:副教授 助教 助课
(4)以输入数据必须遵循的规则进行划分:如:输入标示符:以字母开头字母数字组合串
一个有效的等价类 二个无效的等价类
Stu1 1K(也可用 _25) k&5
(5)若处理对象是表格,应该使用空表、含一条记录表、含多条记录表,表满四类。
( 6)若无法按数据类型划分,则可按结果类型划分。 例如:有一个程序是分析一个三角形的类型(等边、等腰、直角、普通)。
输入数据:
有效类 1 有效类 2 有效类 3 有效类 4 无效类 5
等边 等腰 直角 普通三角形 非三角
(5,5,5) (5,5,9) ( 3,4,5) (3,4,6) (0,5,8)
设计测试用例时两个步骤:
设计一个新的测试用例以尽可能多地覆盖尚未被覆盖的有效等价类,重复这一步 骤直到所有有效等价类都被覆盖为止;
设计一个新的测试用例,使它覆盖一个而且只覆盖一个尚未被覆盖的无效等价类, 重复这一步骤直到所有无效等价类都被覆盖为止。
比如:招服务员 ,看是否给面试资格。
要求: 女 >=20 则有面试资格。
模块结构:int judge(sex,age){}
举例:图书管理系统登录测试
分析登录各类文档:String(errorNumber) Login(userName,pas);
等价类表中条件分析:分析用例文档,只能分析出用户名和密码的匹配性。 从概要设计的界面设计中,分析出用户名和密码不能为空。
4.2 黑盒测试——边界值分析法
边界值:指输入等价类和输出等价类边界上的数据
思想:设计边界值测试方案进行分析
例如,如要求输入最少 1 到最多 10 个数值. 上例划分等价类:
一个有效的等价类 两个无效的等价类
1-10 >10 <1
等价用例: n=8 n=20 n=0
边界值 : n=1,10 n=11 n=0
边界法步骤:(1)划分等价类 (2) 找等价类的边界
一个用例尽量覆盖多的有效边界;一个用例只能覆盖一个无效边界
选择边界值的一些原则 :
选值:选择边界及边界附近的值。
(1)如果输入条件规定了值的范围,可以选择正好等于边界值的数据作为有效的测试用例,同时还要选择刚好越过边界值的数据作为无效的测试用例。 如输入值的范围是[1,100], 可取 0,1,100,101 等值作为测试数据。
(2)如果输入条件指出了输入数据的个数, 则按最大个数、 最小个数、比最小个数少 1 及比最大个数多 1 等情况分别设计测试用例。 如一个输入文件可包括 1~255 个记录, 则分别设计有 1 个记录、255 个记录, 以及 0 个记录和 256 个记录的输入文件的测试用例。
(3) 若输出规格规定了输出数值个数,根据输出个数设定测试用例。 如:一个论文检索系统,根据用户输入的命令显示有关文献的摘要,但每页最多 显示 4 篇“摘要”。最多显示 32 篇。则可以设计输出 0 篇,4 篇和 5 篇,32 篇,33 篇的测试用例,检查是否报错。
(4)如果程序中使用了一个内部数据结构,则应当选择这个内部数据结构的边界上的值作为测试用例。例:比如,输入/输出是线性表,线性表用栈处理。若模块功能是进栈操作。参数(栈,数据)。设计栈满时测试用例。看是否能进栈操作。若模块功能是出栈操作。参数(栈)。设计栈空测试用例。是否能出栈操作。 例如,如果程序中定义了一个数组,其元素下标的下界是 0,上界是 100,那么 应选择达到这个下标边界的值,如 0 与 100 作为测试用例。
黑盒测试,通常以等价类法为主,辅助以边界类法(用边界类时,并不需要面面俱到)。
5 软件测试
V 模型: 测试活动的展开次序正好与开发次序相反。 V 模型强调测试在系统工程各个阶段中的作用。
测试的级别:
5.1 单元测试
1、目的:保证每个模块作为一个单元能正确运行;发现的往往是编码和详细设 计的错误。
2、基于的文档和测试方法:详细设计说明书、主要使用白盒测试技术
模块本身不是一个程序,不能直接运行,需要靠其它模块来驱动和调用,因此需 要为其设计驱动程序(模拟其功能)。同时,一个模块运行中又调用到它的下属 模块,则需为其设计多个存根程序(支持模块)。
例如:测试 B 模块,设计一个 A 功能的驱动模块,设计一个 D,E的支持模块。
必须为每个单元测试开发驱动程序和(或)存根程序。
驱动程序:驱动程序是一个“主程序”,它接收测试数据,传送给被测试的模块, 并且印出有关的结果。
存根程序:存根程序代替被测试的模块所调用的模块。它使用被它代替的模块的 接口,可能做最少量的数据操作,印出对入口的检验或操作结果,并且把控制归还给调用它的模块。
驱动程序和存根程序代表开销,通常并不把它们作为软件产品的一部分交给用户。 写一个函数,判断某一个四位数是不是玫瑰花数(所谓玫瑰花数即该四位数各位 数字的四次方和恰好等于该数本身,如:1634=1+1296+81+256)。 在主函数中 调用该函数,输出所有玫瑰花数
#include <stdio.h>
int rose(int n)
{int a,b,c,d;
a=n/1000;
b=n/100%10;
c=n/10%10;
d=n%10;
if(a*a*a*a+b*b*b*b+c*c*c*c+d*d*d*d==n)
return 1;
Else return 0;
main()
{
int i,flag;
for(i=1000;i<10000;i++)
{flag=rose(i);
if (flag)
printf("%d\t",i);}
}
测试 main 的存根程序:rose
int rose(int n)
{printf("%d",n);
return 0;
}
int rose(int n)
{ printf("%d",n);
return 1;
}
测试 main 的存根程序第二种写法:rose
int rose(int n)
{printf("%d",n);
if(n==1643) return 1;
else
return 0;
}
5.2 集成测试(组装测试或联合测试)
1、目的:在单元测试的基础上,将所有模块按照设计要求组装成为子系统或系统,进行集成测试。
1)功能性测试。使用黑盒测试技术针对被测模块的接口规格说明进行测试。
2)非功能性测试。对模块的性能或可靠性进行测试。
2、基于文档及使用方法:概要设计说明书、黑盒测试法
由模块组装成程序时有两种方法:非渐增式测试方法、渐增式测试方法
非渐增式测试方法:先分别测试每个模块,再把所有模块按设计要求放在一起结 合成所要的程序; 非渐增式测试一下子把所有模块放在一起,并把庞大的程序作为一个整体来测试, 测试者面对的情况十分复杂。
渐增式测试方法:把下一个要测试的模块同已经测试好的那些模块结合起来进行 测试;测试完以后再把下一个应该测试的模块结合进来测试,每次增加一个模块;
渐增式测试方法:把程序划分成小段来构造和测试,在这个过程中比较容易定位 和改正错误;
渐增方式有两种集成策略:自顶向下、自底向上
1 自顶向下集成:从主控制模块(重要)开始,沿着程序的控制层次向下移动, 逐渐把各个模块结合起来。 例:首先测试主控模块 A,然后把 B 加进来测试 A,B。之后把 C加进来测试
在把附属于主控制模块的那些模块组装到程序结构中去时,可以使用:深度优先 的策略,宽度优先的策略。
深度优先:先组装在软件结构的一条主控制通路上的所有模块(先深后宽)。
宽度优先:沿软件结构水平地移动,把处于同一个控制层次上的所有模块组装起 来(先宽后深)
把模块结合进软件结构的过程由下述 4 个步骤完成:
第一步,对主控制模块进行测试,测试时用存根程序代替所有直接附属于主控制模块的模块;
第二步,根据选定的结合策略(深度优先或宽度优先),每次用一个实际模块代换一个存根程序(新结合进来的模块往往又需要新的存根程序);
第三步,在结合进一个模块的同时进行测试;
第四步,为了保证加入模块没有引进新的错误,可能需要进行回归测试(即,全部或部分地重复以前做过的测试)。
从第二步开始不断地重复进行上述过程,直到构造起完整的软件结构为止。
优点:
能够在测试的早期对主要的控制或关键的抉择进行检验。
如果选择深度优先的结合方法,可以在早期实现软件的一个完整的功能并且验证 这个功能。
缺点:存根程序代替了低层次的模块,在软件结构中没有重要的数据自下往上流。
2 自底向上集成:
第 0 步 先测试底层模块。
第一步,把低层模块组合成实现某个特定的软件子功能的族;
第二步,写一个驱动程序(用于测试的控制程序),协调测试数据的输入和输出;
第三步,对由模块组成的子功能族进行测试;
第四步,去掉驱动程序,沿软件结构自下向上移动,把子功能族组合起来形成更大的子功能族。
上述第二步到第四步实质上构成了一个循环。
3 回归测试:
在软件生命周期的任何一个阶段,只要软件发生了改变,就可能给软件带来问题。
(1)可能源于发现了错误并做了修改。
(2)也可能是因为在集成或维护阶段加入了新的模块。
回归测试:重新执行已经做过的测试的某个子集。以保证上述这些变化没有带来 非预期的副作用。(已测过的一部分黑盒和白盒)
4 不同集成测试策略的比较:
5.3 确认测试(系统测试)
1、目的:确认测试应检查软件能否按合同要求进行工作,即是否满足软件需求 说明书中的确认标准。
2、基于的文档及测试方法:需求规格说明书、黑盒测试法
5.4 验收测试
1、它产品发布之前所进行的软件测试活动,是技术测试的最后一个阶段,也称为交付测试。 分为 Alpha 测试和 Beta 测试。
Alpha 测试: Alpha 测试是由用户在开发环境下进行的测试,也可以是开发机构内部的用户在模拟实际操作环境下进行的测试。测试目的是评价软件产品的功能、 局域化、可用性、可靠性、性能和支持。α测试即为非正式验收测试。
Beta 测试: Beta 测试是由软件的多个用户在一个或多个用户的实际使用环境下 进行的测试。
2、基于文档: 需求规格说明书
手工测试和自动化测试:
手工测试:手工测试就是由人去一个一个的去执行测试用例,通过键盘鼠标等输 入一些参数,查看返回结果是否符合预期结果。手动测试是由测试人员根据测试 用例中描述的规程一步步执行测试,得到实际结果与期望结果进行比较的过程。 为了节省人力、时间或硬件资源,提高测试效率,便把以人为驱动的测试行为转 化为机器执行,由此引入了自动化测试的概念。
自动化测试:界面自动化、接口自动化、性能自动化。
我们一般所说的自动化测试就是指功能自动化测试,通过相关的测试技术,通过 编码的方式用一段程序来测试一个软件的功能,这样就可以重复执行程序来进 行重复的测试。如果一个软件一小部分发生改变,我们只要修改一部分代码,就 可以重复的对整个软件进行功能测试。这样就大大的提高了测试效率。
自动化测试概念和工具:
自动化测试指软件测试的自动化,在预设状态下运行应用程序或者系统,预设条件包括正常和异常,最后评估运行结果。将人为驱动的测试行为转化为机器执行 的过程。
常见的自动化测试工具:QTP、selenium、Rational Robot 、jmeter、appium、soapui、 Loadrunner 等等
软件自动化测试: