Download presentation
Presentation is loading. Please wait.
1
第10章 软件测试 软件测试是对软件规格说明、软件设计和编码的最全面也是最后的审查。
第10章 软件测试 软件测试是对软件规格说明、软件设计和编码的最全面也是最后的审查。 通过软件测试,可以发现软件中绝大部分潜伏的错误,从而可以大大提高软件产品的正确性、可靠性,进而可显著提高产品质量。 统计表明,软件测试工作往往占软件开发总工作量的40%以上。甚至3~5倍以上。
2
第10章 软件测试 本章将介绍: 软件测试的基本知识; 软件测试的常用方法和技术; 软件测试的过程; 软件的调试与排错技术;
第10章 软件测试 本章将介绍: 软件测试的基本知识; 软件测试的常用方法和技术; 软件测试的过程; 软件的调试与排错技术; 软件测试的工具。
3
第10章 软件测试 10.1 软件测试的基本知识 10.2 软件测试技术 10.3 软件测试过程 10.4 调试 10.5 测试工具
4
10.1 软件测试的基本知识 软件测试是执行程序发现并排除程序中潜伏的错误的过程。
10.1 软件测试的基本知识 软件测试是执行程序发现并排除程序中潜伏的错误的过程。 软件测试是软件投入运行前,对软件需求分析、设计、实现的强有力的最终审查。
5
10.1.1 软件测试的目标与原则 测试用例——为了进行有效的测试而设计的输入数据和预期的输出结果数据。
软件测试的目标与原则 测试用例——为了进行有效的测试而设计的输入数据和预期的输出结果数据。 Myers在其软件测试著作中对软件测试的目标提出以下观点: ①软件测试是为了发现错误而运行程序的过程; ②一个好的测试用例能够发现至今尚未发现的 错误; ③一个成功的测试是发现了至今尚未发现的错 误的测试。
6
测试原则 ①应尽早和不断地进行软件“测试”,即将这种“测试”贯穿于软件开发的各个阶段,坚持各个阶段的技术评审,以便尽早地发现和预防错误。
②测试用例中,不仅要选择合理的输入数据,还要选择不合理的输入数据。 ③在开发各阶段应事先分别制定出相应的测试计划,在测试开始后应严格执行,防止随意性。 ④对发现错误较多的程序模块,应进行重点测试。Pareto指出,测试发现错误的80%集中在20%的模块中。发现错误较多的模块质量较差,需重点测试,并要测试是否引入了新的错误。
7
测试原则 ⑤避免程序员测试自己的程序。 测试用例的设计应有第三方参与。对于大型软件的测试,一般的做法是:设计者与测试者共同完成单元测试任务,而综合测试由专门的测试机构负责,有时其中也可以有设计者参加 ⑥用穷举测试是不现实的,一般通过设计测试用例,充分覆盖所有条件或所有语句即可。 ⑦长期妥善保存测试计划、测试用例、出错统计和有关的分析报告。
8
10.1.2 软件测试的步骤 … 图10-1-1 测试步骤 部件 代码 单元测试 设计 规格说明 系统 功能需求 其他 软件需求 用户需求
软件测试的步骤 部件 代码 单元测试 设计 规格说明 系统 功能需求 其他 软件需求 用户需求 规格说明 用户 环境 部件 代码 单元测试 集成测试 功能测试 性能测试 验收测试 安装测试 … 集成后 的模块 功能 系统 验证, 生效的 软件 被接受 的系统 测试后 的模块 部件 代码 单元测试 在使用中的系统 图 测试步骤
9
10.1.2 软件测试的步骤 从软件工程的角度: 将单元测试与详细设计对应起来,即在详细设计阶段就应制定出单元测试计划;
软件测试的步骤 从软件工程的角度: 将单元测试与详细设计对应起来,即在详细设计阶段就应制定出单元测试计划; 而集成测试又称为综合测试,可以把概要设计和集成测试对应起来,在概要设计阶段就可以制定集成测试计划; 将功能测试、性能(行为)测试、验收测试统称为验收测试(也称确认测试),与软件系统需求分析阶段对应起来,在需求分析阶段就应制定出验收准则和验收测试计划,验收测试应提交经用户确认的软件产品; 最后,将软件、硬件等要素构成一个完整的基于计算机的系统,再进行系统测试,使系统测试与系统定义相对应,即在系统定义阶段就应制定系统测试计划。
10
10.1.2 软件测试的步骤 图10-1-2 软件工程的开发与测试的关系 系统工程 需求分析 概要设计 设计、编码 单元测试 集成测试
软件测试的步骤 系统工程 需求分析 概要设计 设计、编码 单元测试 集成测试 验收测试 系统测试 图 软件工程的开发与测试的关系
11
10.1.3 测试阶段的信息流 图10-1-3 测试阶段的信息流 正确的程序 软件配置 错误 排错 测试结果 测试 评价 可靠性预测 可靠性
测试阶段的信息流 正确的程序 软件配置 错误 排错 测试结果 测试 评价 可靠性预测 可靠性 模型 测试配置 错误统计 预期结果 图 测试阶段的信息流
12
10.1.3 测试阶段的信息流 测试的输入流有软件配置和测试配置。 软件配置由需求规格说明、设计说明、源代码等组成;
测试阶段的信息流 测试的输入流有软件配置和测试配置。 软件配置由需求规格说明、设计说明、源代码等组成; 测试配置包括测试计划、测试用例(其中包括预期的结果)、测试工具等组成。
13
测试结果评价 经常发现严重的错误并需要修改软件,则软件的质量和可靠性一定不高,需要进一步测试;
如果测试所发现的错误不多且易于改正,软件功能看起来也较完善,则需考虑两种可能: 1)软件质量和可靠性确实令人满意; 2)测试不全面,很可能还潜伏着严重错误; 如果测试过程没有发现任何错误,则很有可能是测试配置不合理。
14
10.1.4 软件测试的常用方法 1.静态测试 静态测试是采用人工检测和计算机辅助静态分析的方法对程序进行检测。
软件测试的常用方法 1.静态测试 静态测试是采用人工检测和计算机辅助静态分析的方法对程序进行检测。 人工检测是指靠人工走查程序或评审软件。这种走查与评审主要针对编码的质量和软件开发各个阶段的文档,特别是总体设计和详细设计阶段的错误。能发现30%~70%的逻辑设计和编码错误。 计算机辅助静态分析是指利用静态分析软件工具对程序进行静态分析,主要检测变量是否用错、参数是否匹配、循环嵌套是否有错、是否有死循环和永远执行不到的死代码等等。同时,它还可对程序的特性进行分析。
15
10.1.4 软件测试的常用方法 2.动态测试 动态测试是指事先设计好一组测试用例,然后通过运行程序来发现错误。 动态测试有两种测试方法:
软件测试的常用方法 2.动态测试 动态测试是指事先设计好一组测试用例,然后通过运行程序来发现错误。 动态测试有两种测试方法: 黑盒测试; 白盒测试。
16
软件测试的常用方法 黑盒测试,又称为功能测试——把被测的程序模块看成一个黑匣子,即完全不考虑程序的内部结构和处理过程,测试仅在程序的接口上进行。 白盒测试——即完全了解程序的内部结构和详细的处理过程,测试是在程序的内部结构上进行。要求针对每一条逻辑路径都要设计测试用例,检查每一个分支和每一次循环的情况。
17
开始 结束 穷举测试是不现实的。如上图,设循环体应执行30次,循环体中有4个独立的分支,则最多有4 30 ≈ 10 18个逻辑路径,假设每运行一个测试用例平均花费1毫秒,则需花费3千多万年。一般选用少量最有效的测试用例,以便覆盖每一个条件、每一个路径和每一个语句,从而以最少的代价发现尽可能多的错误。
18
软件测试中常见的错误类型 按照错误的影响和造成的后果进行分类,可分为:较小错误,中等错误,较严重错误,严重错误,非常严重的错误,最严重的错误。 按照软件生存周期各个阶段分类,可分为:问题定义错误、需求分析规格说明错误、设计错误、编码错误等等。 这里重点介绍一种按照错误的性质和范围进行分类的方法,可以将错误分为如下几类:
19
按照错误的性质和范围进行分类 1.功能错误 ①需求规格说明错误。主要是指其中有错误、多余或遗漏的功能,有二义性或自相矛盾。 ②设计实现错误。设计或实现的功能不是规格说明或用户所要求的功能。
20
按照错误的性质和范围进行分类 2.系统错误 ①外部接口错误。如与打印机的接口错误。
②内部接口错误。指各程序模块间的联系存在错误。如输入/输出、数据保护、子程序访问等。 ③硬件结构错误。如错误地理解I/O指令、中断处理、设备启动和初始化等而引起的错误。 ④软件结构错误。由于软件结构不合理或不清晰所引起的错误。往往在系统满载时才能发现。 ⑤操作系统错误。该类错误是由于不了解操作系统而引起的,操作系统本身也有错误。 ⑥控制与顺序错误。包括事件的时间顺序不正确、等待一个不可能发生的事件等等。 ⑦资源管理错误。既资源使用不当。资源死锁等。
21
按照错误的性质和范围进行分类 3.加工错误(算法错误) ①计算与操作错误。指计算、函数求值和一般操作过程中的错误。
②初始化错误。如忘记了初始化工作区、数据区,错误地对循环变量赋初值,不正确的初始化等等。 ③局部控制和次序错误。如遗漏路径、不可达到的代码段、循环嵌套或终止条件不正确、死循环等等。 ④逻辑错误。如多分支、判断条件不正确等。
22
按照错误的性质和范围进行分类 4.数据错误 ①动态数据错误。
②静态数据错误。静态数据指直接或间接地出现在程序或数据库中的数据,其内容和格式都是固定的。因此在内容或格式上都可能存在错误。 ③数据内容错误。是指由于内容被破坏或被错误地解释而造成的错误。 ④数据结构错误。包括数据结构说明错误和数据结构使用错误。 ⑤数据属性错误。数据属性是指数据内容的含义或语义,如整数、字符等。数据属性错误是指对数据属性的错误解释和错误使用而导致的错误。
23
按照错误的性质和范围进行分类 5.代码错误 代码错误主要包括语法错误、键入错误、对语句的理解错误等。
例如,Myers(1976)指出,美国第一个去金星的太空任务的失败是由于在一个Fortran do循环中缺少一个逗号。
24
10.2.1 白盒测试 白盒测试的原则是: ①保证程序中每一独立的路径至少执行一次; ②保证所有判定的每一个分支至少执行一次;
白盒测试 白盒测试的原则是: ①保证程序中每一独立的路径至少执行一次; ②保证所有判定的每一个分支至少执行一次; ③保证每个判定表达式中每个条件的所有可能结果至少出现一次; ④保证每一循环都在边界条件和一般条件至少各执行一次; ⑤验证所有内部数据结构的有效性。
25
几种典型的白盒测试技术 1.逻辑覆盖 逻辑覆盖是指设计测试用例对程序的内部分支逻辑结构进行部分或全部覆盖的技术。 1)语句覆盖 2)判定覆盖
3)条件覆盖 4)判定/条件覆盖 5)条件组合覆盖 6)路径覆盖 逻辑覆盖
26
1)语句覆盖 —使程序中的每个语句至少执行一次。
开始 a T b (x>1) AND (y=0) 语句段1 F c T d (x=2) OR (z>1) 语句段2 F e 结束 令x=2,y=0,z=4作为测试数据,程序执行路径为abcde,使语句段1和2各执行一次,实现了语句覆盖。它不能检测所有判定条件的错误。比如,错把z>1写成了z<1,则上述测试用例就无法检测出来了。
27
2)判定覆盖——分支覆盖 判定覆盖是指设计足够多的测试用例,使每个判定的每种可能结果都至少出现一次,也就是使每个判定的每个分支都至少执行一次。
28
可以设计如下两组数据以满足判定覆盖: x=3,y=0,z=1(通过路径abce); x=2,y=1,z=2(通过路径acde)。
判定覆盖必然满足语句覆盖。覆盖程度仍然不高。比如,错把z>1写成了z<1,则上述测试用例仍无法检测出来。因为它只覆盖了全部路径的一半。判定覆盖可以推广到多分支情况。 (x>1) AND (y=0) (x=2) OR (z>1) 语句段1 语句段2 开始 结束 T F a b c d e
29
3)条件覆盖 条件覆盖是指设计足够的测试用例,使每个判定表达式中的每个条件的每种可能值都至少出现一次。
如图,共有4个条件:x > 1,y = 0,x = 2,z > 1。 条件覆盖要求设计测试用例,覆盖第一个判定表达式的x >1,y = 0,x ≤ 1,y≠0等各种结果,并覆盖第二个判定表达式的x = 2,z > 1,x ≠ 2,z ≤ 1等各种结果。 开始 a T b (x>1) AND (y=0) 语句段1 F c T d (x=2) OR (z>1) 语句段2 F e 结束
30
3)条件覆盖 设计如下两组测试用例,可以满足条件覆盖的标准: x=2,y=0,z=3
(覆盖x>1,y=0,x=2,z>1,通过路径abcde); x=1,y=1,z=1 (覆盖x≤1,y≠0,x≠2,z≤1,通过路径ace)。 开始 a T b (x>1) AND (y=0) 语句段1 F c T d (x=2) OR (z>1) 语句段2 F e 结束
31
3)条件覆盖 但是,如果设计如下一组测试用例: x=1,y=0,z=3 (覆盖x≤1,y=0,x≠2,z>1,通过路径acde);
(覆盖x>1,y≠0,x=2,z≤1,通过路径ace)。 虽满足条件覆盖,但不满足语句覆盖和判定覆盖。 (x>1) AND (y=0) (x=2) OR (z>1) 语句段1 语句段2 开始 结束 T F a b c d e
32
4)判定/条件覆盖 它是指设计足够的测试用例,使得判定表达式中的每个条件都取到所有可能的值(即满足条件覆盖),并使每个判定表达式也都取到所有可能的判定结果(即满足判定覆盖)。
33
(覆盖x>1,y=0,x=2,z>1,通过路径abcde); x=1,y=1,z=1
4)判定/条件覆盖 x=2,y=0,z=3 (覆盖x>1,y=0,x=2,z>1,通过路径abcde); x=1,y=1,z=1 (覆盖x≤1,y≠0,x≠2,z≤1,通过路径ace)。 (x>1) AND (y=0) (x=2) OR (z>1) 语句段1 语句段2 开始 结束 T F a b c d e
34
条件组合覆盖是指设计足够的测试用例,使得每个判定表达式中条件的各种可能值的组合都至少出现一次。这是一种较强的逻辑覆盖。
5)条件组合覆盖 条件组合覆盖是指设计足够的测试用例,使得每个判定表达式中条件的各种可能值的组合都至少出现一次。这是一种较强的逻辑覆盖。
35
如图,两个判定表达式中含有4个条件,共有8种组合: ①x>1,y=0; ②x>1,y≠0; ③x≤1,y=0; ④x≤1,y≠0;
⑤x=2,z>1; ⑥x=2,z≤1; ⑦x≠2,z>1;⑧x≠2,z≤1。 (x>1) AND (y=0) (x=2) OR (z>1) 语句段1 语句段2 开始 结束 T F a b c d e
36
覆盖条件组合①和⑤,通过路径abcde; x=2,y=1,z=1; 覆盖条件组合②和⑥,通过路径acde; x=0,y=0,z=3;
覆盖条件组合④和⑧,通过路径ace。但未通过路径abce。 (x>1) AND (y=0) (x=2) OR (z>1) 语句段1 语句段2 开始 结束 T F a b c d e
37
6)路径覆盖 路径覆盖是指设计足够的测试用例,以覆盖被测程序中所有可能的路径。
如图,共有4条路径,设计以下4组测试用例,就可以覆盖这4条路径: x=2,y=0,z=3;覆盖路径abcde x=2,y=1,z=1;覆盖路径acde x=1,y=1,z=1;覆盖路径ace x=3,y=0,z=1;覆盖路径abce (x>1) AND (y=0) (x=2) OR (z>1) 语句段1 语句段2 开始 结束 T F a b c d e 没有覆盖条件组合③和⑦ ③x≤1,y=0 ⑦x≠2,z>1
38
实际测试 在实际测试时,为了达到充分测试的目的,一般以条件组合覆盖为主设计测试用例,然后再补充部分测试用例,以便实现路径覆盖。
39
白盒测试 2.基本路径测试 其主要思想是根据软件详细设计的过程性描述或源代码中的控制流程求出程序的环形复杂性度量,然后用此度量确定程序的基本路径集合,并由此导出一组测试用例来覆盖该集合中的每一个独立的路径,从而可以保证每个语句至少执行一次。
40
2.基本路径测试 【例10.1】试用基本路径测试法对如下的PDL描述或如图10-2-2所示的程序流程图设计测试用例。该例子描述了最多输入50个值(以–1作为输入结束标志),计算其中有效的学生分数的个数、总分数和平均值。
41
PROCEDURE average INTERFACE RETURNS average,sum,n1;*n1为有效成绩的个数。* INTERFACE ACCEPTS score; TYPE score[1,50] IS SCALAR ARRAY; TYPE average,n1,n2,sum IS SCALAR;*n2为输入值的个数。* TYPE i IS INTEGER; i = 1;n1=n2=0;sum=0; DO WHILE (score[ i ]<> – 1)AND(n2<50) n2 加 1; IF (score[ i ]>=0)AND(score[ i ]<=100) THEN n1 加 1; sum = sum + score[ i ]; END IF; i 加 1; END DO; IF n1> 0 THEN average = sum/n1; ELSE average = – 1; END average
42
n1=n1+1,sum=sum+score[i]
开始 1 i =1,n1=n2=0,sum=0 2和3 F Score[ i ]<>-1 AND n2<50 4 T n2=n2+1 5和6 F Score[ i ]>0 AND score[i]<100 7 T n1=n1+1,sum=sum+score[i] 8 i = i +1 9 F T n1>0 11 10 average= – 1 average=sum/n1 12 返回 图 过程average的程序流程图
43
【例10.1】 解:可按如下步骤设计测试用例: 步骤1:根据详细设计或代码导出过程average的流图。 R4 R5 R3 R1 R6 R2
9 3 4 11 R5 10 R3 5 12 R1 6 R6 R2 7 8
44
【例10.1】 步骤2:据流图确定环形复杂性度量V(G): 1)V(G)=E – N +2 = 16 – = 6 ; 其中E为流图中的边数,N为结点数; 2)V(G)= 6 (个区域); 3)V(G)= P + 1 = = 6 ; 其中P为判定结点的个数。在流图中,结点2、3、5、6、9是判定结点。
45
【例10.1】 步骤3:确定基本路径集合(即独立路径集合)。一条独立路径是指,和其他的独立路径相比,至少引入一个新处理语句或一个新判断的程序通路。V(G)值正好等于该程序的独立路径的条数。于是可确定7条独立的路径: 路径1:1—2—9—10—12 路径2:1—2—9—11—12 路径3:1—2—3—9—10—12 路径4:1—2—3—9—11—12 路径5:1—2—3—4—5—8—2… 路径6:1—2—3—4—5—6—8—2… 路径7:1—2—3—4—5—6—7—8—2…
46
【例10.1】 步骤4:为每一条独立路径各设计一组测试用例,以便强迫程序沿着该路径至少执行一次。 1)路径1的测试用例:
score[k]=有效分数值,当k < i ; score[ i ]= – 1 , 2≤i≤50; 期望结果:根据输入的有效分数算出正确的分数个数n1、总分sum和平均分average。 2)路径2的测试用例: score[ 1 ]= – 1 ; 期望的结果:average = – 1 ,其他量保持初值。
47
【例10.1】 3)路径3的测试用例: 输入多于50个有效分数,即试图处理51个分数,要求前51个为有效分数; 期望结果:n1=50、且算出正确的总分和平均分。 4)路径5的测试用例: score[ i ]=有效分数, 当i<50; score[ k ]<0 , k< i ; 期望结果:根据输入的有效分数算出正确的分数个数n1、总分sum和平均分average。
48
【例10.1】 5)路径6的测试用例: score[ i ]=有效分数, 当i<50; score[ k ]>100 , k< i ; 期望结果:根据输入的有效分数算出正确的分数个数n1、总分sum和平均分average。 6)路径7的测试用例:
49
3.循环测试 1)对于最多为n次的单循环,可设计测试用例实现下列测试: ①跳过循环,即一次也不执行; ②仅循环1次; ③循环2次;
④循环m次,m<n ; ⑤分别循环n – 1次,n次,n+1次。 2)对于嵌套循环的测试: ①从最内层循环开始测试,此时外层循环都取最小值,对内层进行单循环的测试; ②向外退一层进行测试,此时其内层循环取一些典型值,其外层循环仍取最小值; ③继续向外层扩展,直至测试完成。
50
10.2.2 黑盒测试 主要是测试软件是否满足功能需求。 黑盒测试主要测试的错误类型有: ①不正确或遗漏的功能; ②接口错误; ③性能错误;
黑盒测试 主要是测试软件是否满足功能需求。 黑盒测试主要测试的错误类型有: ①不正确或遗漏的功能; ②接口错误; ③性能错误; ④数据结构或外部数据访问错误; ⑤初始化或终止条件错误等等。 黑盒测试设计测试用例的方法: 等价类的划分、边界值分析、 错误推测、组合数据测试等。
51
1.等价类划分 等价类划分的思想是将输入数据按有效的(合理的)和无效的(不合理的)划分成若干个等价类,认为测试等价类中的一个代表值的结果就等于对该类其他值的测试。利用等价类划分的测试步骤如下: 1)划分等价类 从程序的功能说明中找出每个输入条件,然后将其划分成若干个有效和无效的等价类。下面给出等价类划分的几条经验性原则供参考:
52
等价类划分的几条经验性原则 ①如果规定了输入值的范围,则可划分出一个有效的等价类(输入值在此范围内)和两个无效的等价类(输入值小于最小值或大于最大值)。 ②如果规定了数据输入的个数,则可划分出一个有效的等价类(输入值的个数符合规定)和两个无效的等价类(输入值的个数少于或多于规定个数)。 ③如果规定了输入数据的一组值,而且程序对不同的输入值进行不同的处理,则每个允许的输入值是一个有效的等价类,此外还有一个无效的等价类(规定的这一组值以外的值)。
53
等价类划分的几条经验性原则 ④如果规定了输入数据必须遵循的规则,则可划分出一个有效的等价类(符合规则)和若干个无效的等价类(从不同的角度违反规则)。 ⑤如果输入条件规定了一个集合,则可划分出一个有效的等价类(此集合)和一个无效的等价类(此集合的补集)。
54
1.等价类划分 2)设计测试用例 ①等价类划分应列表,并为每一个等价类编号。
②设计一个有效等价类的测试用例,使其尽可能多地覆盖尚未被覆盖过的有效等价类。如此重复,直到所有有效等价类都被覆盖为止。 ③设计一个测试用例,仅覆盖一个无效等价类,如此重复,直到所有无效等价类都被覆盖为止。
55
2)设计测试用例 【例10.1】设有一个档案管理系统,要求用户输入以年月表示的日期。假设日期限定在1990年1月~2003年12月,并规定日期由6位数字字符组成,前4位表示年,后2位表示月。现用等价类划分法设计测试用例,来测试程序的“日期检查功能”。
56
【例10.1】 1)划分等价类并编号 表10-1等价类划分的结果 输入等价类 有效等价类 无效等价类 日期的类型 及长度 ①6位数字字符
②有非数字字符 ③少于6位数字字符 ④多于6位数字字符 年份范围 ⑤在1990~2003 之间 ⑥小于1990 ⑦大于2003 月份范围 ⑧在01~12之间 ⑨等于00 ⑩大于12
57
【例10.1】 2)设计测试用例,以便覆盖所有的有效等 价类 在表10-1中列出了3个有效等价类,编号分别为①、⑤、⑧,设计的测试用例如下:
测试数据 期望结果 覆盖的有效等价类 输入有效 ①、⑤、⑧
58
【例10.1】 3)为每一个无效等价类设计一个测试用例, 设计结果如下: 测试数据 期望结果 覆盖的无效等价类 95June 无效输入 ②
测试数据 期望结果 覆盖的无效等价类 95June 无效输入 ② 无效输入 ③ 无效输入 ④ 无效输入 ⑥ 无效输入 ⑦ 无效输入 ⑨ 无效输入 ⑩
59
2.边界值分析 边界值分析(boundary value analysis,BVA)是指设计测试用例,使程序在输入或输出的边界值或者边界值左右的值执行。 边界值分析方法可以单独设计测试用例,也可以作为等价类划分方法的补充,即在各个等价类中主要是选择边界上及其左右的值。例如例10.1中对月份范围的测试就可以选择00、01、02、11、12、13等数据作为测试用例。
60
边界值分析方法设计测试用例的经验性原则 1)如果输入条件指定了范围[a,b],则a、b以及紧挨a、b左右的各一个值都应作为测试用例。比如,学生成绩为[0,100],应取-1、0、1、99、100、101共6个值作为测试用例。 2)如果输入条件指定了输入数据的个数范围,则按最大、最小个数及其左右的个数各设计一个测试用例。比如,一个输入文件应包括1~255个记录,则应分别设计输入0个、1个、2个、254个、255个、256个记录的测试用例。 3)将规则1)和2)应用于输出条件,即设计测试用例使输出值达到边界值及其左右的值。
61
3.错误推测 错误推测法的基本思想是:程序测试员通过已经掌握的测试理论和实际测试中积累的经验,推测程序在哪些情况下可能发生错误,并将可能发生错误的情况列出,然后为每一可能发生错误的情况各设计一个测试用例。
62
3.错误推测 例如,测试一个对线性表(比如数组)进行排序的程序,可推测列出以下几项需要特别测试的情况: 1)输入的线性表为空表;
2)表中只含有一个元素; 3)输入表中所有元素已排好序; 4)输入表已按逆序排好; 5)输入表中部分或全部元素相同。 于是,可以针对以上列出的每一种情况各设计一个测试用例。
63
4.组合数据测试 实践表明,在单个测试用例没有测试出错误的情况下,采用测试数据的某种组合却可能检测出程序中隐藏很深的错误。
组合数据测试法可以采用的有效工具有判定表、判定树等。 以判定表为例,即列出输入数据的各种组合情况和程序相应的动作、可能的输出结果之间的对应关系,然后为判定表的每一列至少设计一个测试用例。
64
10.3 软件测试过程 从宏观的角度讲,软件测试过程一般可划分为单元测试、集成测试、验收测试和系统测试等几个主要测试阶段。
10.3 软件测试过程 从宏观的角度讲,软件测试过程一般可划分为单元测试、集成测试、验收测试和系统测试等几个主要测试阶段。 对于每一个测试阶段,都应包含制定测试计划、设计测试用例、测试实施和测试结果的收集评估等。 其中,测试计划应包括具体的测试步骤、工作量、进度和资源等。在测试的各个阶段,应适宜地选择黑盒测试和白盒测试方法,由开发人员和一个独立的测试小组单独、分别或共同完成测试任务,必要时还应有用户参加。
65
10.3.1 单元测试 单元测试的测试对象——程序模块。 单元测试的依据——根据详细设计的描述 制定的单元测试计划。
单元测试 单元测试的测试对象——程序模块。 单元测试的依据——根据详细设计的描述 制定的单元测试计划。 单元测试——多采用白盒测试技术。 单元测试——可以并行进行。
66
10.3.1 单元测试 1.单元测试的任务 1)模块接口测试 2)模块局部数据结构的测试 3)模块中所有独立路径的测试
单元测试 1.单元测试的任务 1)模块接口测试 2)模块局部数据结构的测试 3)模块中所有独立路径的测试 4)模块中各条错误处理路径的测试 5)模块边界条件的测试
67
1)模块接口测试 ①输入的实参与本模块的形参在个数、类型、顺序、量纲上是否一致;
②调用其他模块时所给实际参数与被调模块的形式参数在个数、类型、顺序、量纲上是否一致; ③调用预定义函数时所用参数的个数、类型、顺序、返回值的类型等是否正确; ④是否存在与当前入口点无关的参数引用; ⑤是否修改了只读型参数;
68
1)模块接口测试 ⑥各个模块对全局变量的定义和引用是否保持一致; ⑦是否把某些约束作为参数传递。
⑧如果模块内包括外部输入输出,还应测试文件属性、文件打开/关闭语句、格式说明、输入输出语句、缓冲区大小与记录长度是否匹配、是否处理了文件尾、输出信息中是否存在文字错误等方面的内容。
69
2)模块局部数据结构的测试 主要的测试内容有: ①不适合或不相容的类型说明; ②变量名不正确(拼写或截断错误等);
③变量无初值或初始化、缺省值有错; ④出现上溢出、下溢出、地址异常等。
70
3)模块中所有独立路径的测试 单元测试旨在找出如下错误:
①计算中常见的错误,有:运算符优先级错误、混合运算类型匹配错误、变量初值错、达不到精度、表达式不正确等。 ②不正确的比较判断和不恰当的控制流常见的错误,有:被比较的对象的类型不匹配、错误地使用逻辑运算符及其优先级、计算误差引起的判断错误、循环终止条件不合适、错误地修改了循环变量、迭代发散时不能退出循环等。
71
4)模块中各条错误处理路径的测试 我们希望程序模块具有较强的容错能力,这就需要在设计时能预见各种出错条件,并预先设计好各种出错处理通路,以便在用户出现错误时系统能给出恰当的提示而不使系统失效。 出错处理路径测试主要测试的错误有: ①异常处理不当; ②在程序自定义的出错处理程序段运行之前系统已介入; ③显示的出错信息难以理解或未能提供足够的错误定位信息; ④显示的错误与实际发生的错误不符等。
72
5)模块边界条件的测试 模块边界条件的测试是单元测试中最后、也是最重要的一项测试任务,因为程序最容易在边界上出错。可以采用边界值分析技术针对边界值及其左、右值设计测试用例,很有可能检测出新的错误。
73
2.单元测试的步骤 通常,单元测试在编码阶段进行。在源程序代码编制完成并经过编译检查和评审后,就可以开始进行单元测试。测试用例的设计应与评审工作相结合,根据测试计划和详细设计信息设计测试数据,并应给出对应的期望结果。 测试时需要为被测模块编制: 一个驱动模块(driver module)——用来模拟被测模块的上级调用模块,用它接收测试数据,并传送给被测模块,接收测试结果并输出。 若干个桩模块(stub module)——也称为存根模块,用来代替被测模块所调用的子模块。其作用是为被测模块提供所需要的信息,因此,越简单越好。
74
图10-3-1 软件层次结构图 图10-3-2 模块A的单元测试环境
M 驱动 模块 测试 用例 测试 结果 A B A C D E F 桩模块1 桩模块2 桩模块3 图 软件层次结构图 图 模块A的单元测试环境 测试软件(指驱动模块和桩模块)并不作为软件产品的一部分提交给用户。 有些模块用单元测试的方法不能进行充分的测试,可在集成测试的过程中完成详尽的测试。 提高模块内聚度可简化单元测试过程。
75
10.3.2 集成测试 集成测试 — 将软件组装成系统的一种测试技术。因此,又称为组装测试或综合测试。
集成测试 集成测试 — 将软件组装成系统的一种测试技术。因此,又称为组装测试或综合测试。 集成测试旨在发现与接口有关的错误。这些错误包括: ①数据通过接口时会丢失; ②一个模块的功能对另一个模块产生了不利影响; ③几个子功能组合起来没有实现主功能; ④全局数据结构出现错误; ⑤误差的不断积累达到不能接受的程度。 集成测试有两种集成方式: 非增量集成方式; 增量集成方式。
76
1.非增量集成方式 非增量集成方式是将经过单元测试的所有模块一次性全部组装起来,然后进行整体测试,最后得到所要求的软件系统。
这种集成方式容易出现混乱,开始可能遇到一大堆错误,错误定位非常困难,新旧错误交织在一起,会使测试变得更加困难。因此,一般不应采用这种集成方式。
77
2.增量集成方式 可分为自顶向下集成和自底向上集成两种方法。 1)自顶向下集成
自顶向下集成方式是从主控模块开始,按照软件的控制层次结构,以深度优先或广度优先的策略,逐步把各个模块组装在一起。
78
自顶向下集成测试的具体步骤 ①以主控模块作为驱动模块,其直接调用的下属模块都用“桩模块”代替;
②依据所选用的集成策略(深度优先或广度优先)所规定的次序,每次只用一个实际模块替代一个对应的桩模块; ③每结合进一个模块立即测试一遍; ④为了检测加入新模块是否引入了新的错误,每次都需要进行回归测试(即部分或全部地重复以前做过的测试)。 重复执行步骤②、③、④,每重复一次,增加一个模块,直至构造起整个软件结构为止。
79
M1 M1 M2 M3 M4 M2 S3 S4 M5 M6 M7 S5 S6 M8 图 被测软件系统结构图 深度优先策略 :①以M1作为驱动模块,首先将模块M2加入其中,此时模块M3、M4、M5、M6分别以桩模块S3、S4、S5、S6代替,于是对由M1、M2、S3、S4、S5、S6组成的子系统测试一遍;
80
深度优先策略 :②用M5代替S5,并将M8用桩模块S8代替,对由M1、M2、M5、S3、S4、S8、S6组成的子系统再测试一遍;
81
深度优先策略 :③用M8代替S8,对由M1、M2、M5、 M8、 S3、S4、、S6组成的子系统再测试一遍;
82
深度优先策略 :④用M6代替S6,对由M1、M2、M5、 M8、 M6 、 S3、S4组成的子系统再测试一遍;
83
深度优先策略 :⑤用M3代替S3,并以S7代替M7,对由M1、M2、M5、 M8、 M6 、 M3、S7、S4组成的子系统再测试一遍;
84
深度优先策略 :⑥用M7代替S7,对由M1、M2、M5、 M8、 M6 、 M3、M7、S4组成的子系统再测试一遍;
85
深度优先策略 :⑦用M4代替S4,对由M1、M2、M5、 M8、 M6 、 M3、M7、M4组成的子系统再测试一遍; 至此,整个系统测试完。
86
广度优先策略 M1 M2 M3 M4 M5 M6 M7 M8 广度优先策略——沿控制层次结构水平地向下移动,按一层一层的顺序将模块一个个地集成起来。如图的集成的顺序为M1、M2、M3、M4、M5、M6、M7、M8,在集成的过程中也需桩模块的配合。
87
自顶向下集成的优缺点 自顶向下集成的特点是不需要驱动模块,但需要大量的桩模块。
优点是能够尽早地验证程序的主要控制和判断机制,可以较早发现此类错误,从而减少以后的返工。 缺点是在测试较高层模块时,低层模块采用较简单的桩模块来代替,不能反映实际情况,测试可能不充分。
88
2)自底向上集成 即从程序结构的最底层模块开始组装和测试。这种测试需要一定数量的驱动模块,而不需要桩模块。 自底向上集成测试的具体步骤:
①把低层模块组织成实现某个特定的软件子功能的模块群(module cluster); ②为每一个模块群开发一个驱动模块,控制测试数据的输入和测试结果的输出; ③对每个模块群进行测试; ④去掉测试用的驱动模块,用较高层模块将几个模块群组成新的更大的模块群。 上述的②、③、④步重复执行,直至整个程序构造完毕。
89
自底向上集成举例 M1 M2 M3 模块群3 模块群1 模块群2 图 自底向上集成
90
自底向上集成举例 M1 M2 M3 D1 D2 D3 模块群3 模块群1 模块群2 图 自底向上集成
91
自底向上集成优缺点 优点: ①只需设计驱动模块,不需要设计桩模块,测试用例的设计也相对简单。
②由于涉及到复杂算法和直接输入输出的模块最先得到组装和测试,可以在早期解决这些最容易出问题的部分; ③自底向上集成可以实施多个模块并行测试。 缺点: 对高层控制与判断进行测试的时间较晚,如果到测试的后期才发现整体存在较严重问题,就不得不进行较大的返工,此时代价将是巨大的。
92
3)混合式测试及重点测试 自顶向下和自底向上两种集成测试方法的优缺点刚好相反,可结合起来使用,即对于上层模块采用自顶向下的方法,而对于下层模块采用自底向上的方法,这样不但可以大大减少了开发驱动模块和桩模块的数量,还可以充分发挥各自的优点。 在集成测试过程中应对关键模块进行重点测试。关键模块是指具有如下一个或多个特征的模块:①对应多条需求;②具有高层控制功能;③复杂、易出错;④有特殊性能要求。对关键模块应尽早测试,并应进行反复的回归测试。
93
3.集成测试文档 集成测试文档即测试说明书(test specifications)应给出集成的总体规划和某些特殊测试的描述。它将作为软件配置的一部分提交给用户。测试说明书的主要内容提纲如下:
94
测试说明书的主要内容提纲 1)测试范围 2)测试计划 A.测试的各个阶段和划分模块群情况 B.进度安排 C.开销软件(驱动和桩模块)
D.环境和资源
95
测试说明书的主要内容提纲 3)各个模块群测试过程的描述,包括: A.集成的顺序 ①用途 ②被测模式 B.模块群中各模块单元测试的情况
①模块的测试描述 ②开销软件描述 ③期望的结果
96
测试说明书的主要内容提纲 C.测试环境 ①特殊工具和技术 ②开销软件的描述 D.测试用例 E.模块群的期望结果等 4)实际测试结果
5)参考文献 6)附录。
97
验收测试 又称为确认测试。确认测试是一种验收形式的测试,主要是检查软件是否满足软件需求规格说明书中的确认标准,即测试软件能否按照合同的要求运行。
98
1.验收测试的实施 验收测试需要采用一系列的黑盒测试来完成。 参加人员有:专门的测试人员, 必须有用户或客户参加。
文档:需求规格说明书、用户手册等,应事先 制定测试计划,确定测试的种类、测试 进度、设计具体的测试用例。 软件验收测试的中心任务是测试软件是否满足合同规定的所有功能和性能,文档资料是否齐全,人机界面以及可移植性、兼容性、可维护性、容错能力等方面是否达到了用户的期望。
99
1.验收测试的实施 经过验收测试后,其结果可能是以下两种情况之一 : 1)功能、性能等各项指标满足需求规格 说明的要求,用户可以接受;
2)功能、性能等各项指标不满足需求规 格说明的全部要求,用户不能接受。 对于第二种结果,应提交一份问题分析报告。
100
2.软件配置复审 软件配置复审是验收测试的重要环节之一。软件配置复审的任务是审查软件配置(组成程序、所有文档资料、数据结构的所有项目)的正确性、完整性和一致性,以便确保软件配置齐全、分类有序,并包括软件维护所必需的细节,从而为以后的软件维护工作奠定了基础。
101
3.α、β测试 要验证所开发的软件是否真正满足最终用户的要求,就应由用户在其实际工作的环境中进行一系列的“验收测试”。
但一方面用户进行“验收测试” 可能导致开发延期,另一方面是一个软件产品不可能由每个用户验收。因此,通常的做法是采用“α、β测试”的方法。
102
1)α测试 所谓α测试,可以是由用户在开发环境下进行的一种测试,也可以是软件公司内部的“用户”在模拟实际操作环境下进行的一种测试。被测试的是即将面市的软件产品的α版本。 α测试是在受控制的环境下进行的测试,其目的是检测软件产品的功能(Function)、可使用性(Usability)、可靠性(Reliability)、性能(Performance)和支持(Support),即FURPS,特别是产品的界面和特色。 参加α测试的人员是除了开发人员之外最先“使用”产品的人员,他们提出的修改意见是很有价值的。经过α测试并对软件进行修改后,所生成的软件产品称为β版本。
103
2)β测试 β测试是由软件的多个用户在用户的实际使用环境下对软件产品的β版本进行的测试。
β测试,开发者不在现场,要求用户记录所遇到的问题,并定期向开发者报告异常情况、提出意见和建议,供开发者修改、完善。 β测试将进一步检测软件的FURPS,并着重于产品的支持性(包括文档、用户培训等)。在β测试阶段,软件产品的所有手册应完全定稿,可以向用户提交最终的软件产品了。
104
系统测试 软件开发完毕,就应和系统硬件、数据库等其他系统要素集成为一个完整的系统。在集成的过程中,要进行一系列的系统调试和测试,以便验证各个系统要素能否在软件的控制下有条不紊地工作,实现系统规格说明中所规定的系统功能、性能等系统需求。 系统测试需要有硬件工程师、软件工程师、数据库工程师、专业领域的专家等各类技术人员参加,协同完成调试和测试任务。
105
10.3.4 系统测试 在进行系统测试之前,软件工程师应该完成以下几项工作: 1)参与系统测试的规划和设计,从软件的角
系统测试 在进行系统测试之前,软件工程师应该完成以下几项工作: 1)参与系统测试的规划和设计,从软件的角 度保证系统测试的合理性; 2)设计测试用例,模拟错误数据和软件界面 可能发生的错误,记录测试结果,为系统 测试提供支持和帮助; 3)为测试软件系统的输入信息设计出错处理通路。 系统测试应根据系统规格说明书的验收准则进行各种不同的测试,目的是使系统充分运行,验证其是否实现了系统需求。
106
几类系统测试简介 ①功能测试:许多系统功能只有在系统环境下进行测试,才能验证是否满足系统功能需求。
②性能测试:在整个系统的真实环境下,必需进行系统性能测试,以便全面、可靠地测试系统的运行性能。 ③恢复测试:主要是验证系统的容错能力以及在发生错误导致系统失败后系统的恢复能力。测试的方法是采取各种方法使系统失败,再验证系统能否按照预定的要求尽快恢复。
107
几类系统测试简介 ④安全测试:检查系统对非法入侵者的防范能力。可由测试人员扮演入侵者的角色。
⑤容量测试:例如使操作系统作业队列“满员”,考核是否能处理规定数量的任务。 ⑥压力测试:对负荷可变的系统验证其在超负荷的情况下的承受能力。 ⑦可用性测试:对接口结构、输出量定义、出错信息、精度、响应方式的可用性的考核。 ⑧存储器测试:考核有关存储器的指标,如缓冲区的大小等。 ⑨兼容性/转换性能测试:用于测试程序的兼容性和变换规程。
108
几类系统测试简介 ⑩构成测试:对程序本身每种可能的构成进行测试,至少对每种硬设备,程序的最小和最大构成进行测试。
⑾可靠性测试:按照规格说明的规定,考核程序的可靠性。 ⑿可服务性测试:对系统的服务性手段如诊断程序、维护规程等的测试。 ⒀资料测试:测试用户资料的准确性。 ⒁规程测试:测试各类人员应执行的规程。 ⒂安装测试:对安装规程的考核测试。
109
10.4 调试 10.4.1 调试的概念 调试则是在进行了一次成功的测试之后立即开始的。
10.4 调试 调试的概念 调试则是在进行了一次成功的测试之后立即开始的。 调试的目的是确定错误的位置和引起错误的原因,并加以改正。因此,又称为排错或纠错。 实践表明,错误定位是软件工程中最困难的工作,确定发生错误的位置和内在原因所需的工作量几乎占整个调试工作量的90%。
110
10.4.1 调试的概念 隐藏在程序中的错误的特殊的性质包括: ①错误的表现远离引起错误的位置和内在原因,尤其对高度耦合的程序结构更是如此;
调试的概念 隐藏在程序中的错误的特殊的性质包括: ①错误的表现远离引起错误的位置和内在原因,尤其对高度耦合的程序结构更是如此; ②某些错误现象可能是假象; ③纠正一个错误可能引起多个错误,也可能掩盖其他错误; ④由于操作员的疏忽致使错误现象无法重现,很难追踪; ⑤错误可能不是直接由程序引起的; ⑥某些输入条件难于精确地再构造(如某些实时系统的输入次序不确定); ⑦错误现象时有时无。
111
10.4.2 调试策略 分为三类: 原始类; 归纳法 排除类; 回溯类。 演绎法 1.原始类(brute force)
调试策略 分为三类: 原始类; 归纳法 排除类; 回溯类。 演绎法 1.原始类(brute force) 其主要思想是“通过程序运行现场找错”。例如输出存储器、寄存器的内容,在程序中插入打印语句等等。这种方法的效率低,还需要修改程序,更依赖测试人员的能力和经验。
112
调试策略 2.归纳法调试 归纳法调试是从测试结果发现的错误入手,收集正常执行或出错的数据,分析他们之间的关系,提出出错原因的假设,然后再验证或否定这个假设。其具体步骤如下: 1)收集数据:收集程序做对了什么和做错了什么的有关全部数据; 2)整理、分析数据:对收集的数据进行分析、比较和整理,注意观察数据间的关系,从错误的症状中发现线索;
113
2.归纳法调试 3)提出假设:对这些线索进行研究和推测,提出有关错误产生的原因和部位的一个或多个假设。如果有多个假设,首先选择可能性最大的一个。 4)证明假设:由数据验证或反证假设,如果假设得到证实,据此阅读程序找出出错原因和位置并进行改正;如果无法验证,则可能假设错误或有多重错误,需要提出新的假设,进行新的验证。
114
调试策略 3.演绎法调试 演绎法是枚举所有可能引起出错的原因作为假设,然后从中排除不可能发生的原因和假设,对余下的假设进行不断地验证和改进,最后从中推演出出错的原因和部位。 4.回溯法调试 对小型程序进行调试,回溯法是一种有效的方法。该方法是从发现错误现象的地方出发,人工沿程序的控制流程向回追踪,直至找到产生错误的原因为止。但是,当程序的规模较大时,由于需回溯的路线显著增加,因此无法做到完全回溯,只好采用其他的调试方法。
115
10.5 测试工具 10.5.1 自动测试工具 1)模块驱动工具(module animate tool)
10.5 测试工具 自动测试工具 1)模块驱动工具(module animate tool) 2)静态分析器(static analyzers); 3)测试覆盖监视器; 4)程序正确性证明器; 5)测试数据生成器(test data generators); 6)环境模拟器; 此外,还有:代码审查器、测试文件产生器、测试验证器、符号处理系统、输出比较器、测试套具,等等。
116
调试工具 在早期,调试工具用符号调试器。 目前的大多数程序设计环境,如VB、VC++、Borland C++ Builder、PB、C#等都是带有CASE工具的集成开发环境,即将编辑、编译、连接、运行、调试、打包、项目管理、文件管理、部件管理、数据库等多个工具集成在一起。其中的调试工具常见的功能有设置断点,单步执行,跟踪,查看、修改变量或表达式的值等等。
117
习题 10.1 假设某程序读入三个整数,分别解释为三角形的各边,并据此打印信息,说明三角形是普通的、等腰的或等边的。为此程序设计一组有效的测试用例。 10.2 设计并实现上题说明的程序(必要的地方增加出错处理),用基本路径测试法设计测试用例,实际测试和调试后总结所得到的结果。
118
解:1)程序流程图如下: 输入a,b,c 输入a,b,c a+b<=c || |a-b|>=c 开始 1 2、3和4 F
5 T 输入a,b,c 6 和 7 F a+b<=c || |a-b|>=c 9 F T a==b 13 10 T F F a==c a==c 15 F T T b==c 17 11 8 16 T 14 12 输出普通 输出等腰 输出等腰 输出等腰 输出等边 输出不是 18 结束
119
2)C语言程序如下: #include<math.h> #include<stdio.h> void main() { int a ,b ,c; printf("please input a ,b ,c: "); scanf("%d,%d,%d ",&a,&b,&c); while( a<=0 || b<=0 || c<=0) { printf( " a ,b ,c must be > 0!\nplease input a ,b ,c: "); scanf("%d%d%d " ,&a ,&b ,&c); } if( a+b <= c || abs(a-b) >= c) printf("It is not a triangle!\n "); else if( a==b && a==c && b==c) printf( "It is a equilateral triangle!\n "); else if(a==b) printf("It is a isosceles triangle!\n "); else if(a==c) else if(b==c) else printf("It is a general triangle!\n ");
120
3)程序图(流图)如下: 4)求出环形复杂度: ①V(G)=E-N+2=26-18+2=10 ②V(G)=P+1=9+1=10
其中结点2、3、4、6、7、9、10、13、15是判定结点 ③V(G)=10(个区域) 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 R3 R1 R2 R4 R5 R6 R7 R8 R9 R10
121
5)确定基本路径集合(10条) 路径1: 1 – 2 – 5 – 2 路径2: 1 – 2 – 3 – 5 – 2 路径3: 1 – 2 – 3 – 4 – 5 – 2 路径4: 1 – 2 – 3 – 4 – 6 – 8 – 18 路径5: 1 – 2 – 3 – 4 – 6 – 7 – 8 – 18 路径6: 1 – 2 – 3 – 4 – 6 – 7 – 9 – 10 – 11 – 18 路径7: 1 – 2 – 3 – 4 – 6 – 7 – 9 – 10 – 12 – 18 路径8: 1 – 2 – 3 – 4 – 6 – 7 – 9 – 13 – 14 – 18 路径9: 1 – 2 – 3 – 4 – 6 – 7 – 9 – 13 – 15 – 16 – 18 路径10:1 – 2 – 3 – 4 – 6 – 7 – 9 – 13 – 15 – 17 – 18
122
6)为每一条独立路径设计设计用例: ①路径1的测试用例:a = – 3, b = 4, c = 5; 期望结果:输出 出错:a , b , c must be > 0! 提示输入:please input a , b , c: ②路径2的测试用例:a = 3 , b = – 4 , c = 5 ; ③路径3的测试用例:a = 3 , b = 4 , c = – 5 ; ④路径4的测试用例:a = 3 , b = 1 , c = 5 ; 期望结果:输出 : It is not a triangle! ⑤路径5的测试用例:a = 3 , b = 7 , c = 2;
123
⑥路径6的测试用例:a = 3 , b = 3 , c = 3 ; 期望结果:输出 : It is a equilateral triangle! ⑦路径7的测试用例:a = 3 , b = 3 , c = 5 ; 期望结果:输出 : It is a isosceles triangle! ⑧路径8的测试用例:a = 3 , b = 4 , c = 3 ; ⑨路径9的测试用例:a = 3 , b = 4 , c = 4 ; ⑩路径10的测试用例:a = 3 , b = 4 , c = 5 ; 期望结果:输出 : It is a general triangle!
Similar presentations