软件测试概述
1.软件测试产生的背景和基本概念
软件中缺陷产生的原因:
人在软件的设计阶段所犯的错误是导致软件失效的主要原因 软件复杂性是产生软件缺陷的极其重要的根源
控制错误的方法:
预防错误 规范化 CMM、UML 文档化 迭代与软件体系结构 查找和纠正错误 软件测试 编程调试
2.软件测试与调试的区别
测试(testing)的目的与任务 目的:发现程序的错误 成功的测试:发现了未曾发现的错误 任务:通过执行程序,暴露潜在的错误
调试(debugging)的目的与任务 目的:定位和纠正错误 任务:消除软件故障,保证程序的可靠运
3.软件测试的基本思想
- 软件开发与软件测试
- 软件测试技术概览
- 持续的软件测试
- 软件测试的原则与经验
4.软件测试用例:
所谓测试用例是为特定的目的而设计的一组测试输入、执行条件和预期的结果;测试用例是执行测试的最小实体
测试步骤:测试步骤详细规定了如何设置、执行、评估特定的测试用例。
5.软件测试的对象
软件测试不等于程序测试 软件测试贯穿于软件定义和开发的整个期间 需求分析,概要设计,详细设计,以及程序编码等各个阶段所得到的文档,包括需求规格说明,概要设计规格说明,详细设计规格说明以及源程序,都是软件测试的对象
6.软件测试衡量标准
多 能够找到尽可能多的、以至于所有的BUG 快 能够尽可能早地发现最严重的BUG 好 找到的BUG是关键的、用户最关心的 找到BUG后,能够重现找到的BUG,并为修正BUG提供尽可能多的信息 省 能够用最少的时间、人力和资源发现BUG 测试的过程和数据可以重用
7.软件产品的组成
客户需求 产品说明 设计文档:
- 结构文档。描述软件整体设计的文档,包括软件所有主要部分的描述以及相互之间的交互方式。
- 数据流图。表示数据在程序中如何流动的正规示意图。通常由圆圈和线条组成,所以也称为泡泡图。
- 状态转换图。将软件分解为基本状态或者条件的另一种正规示意图,表示不同状态间转换的方式。
- 流程图。用图形描述程序逻辑的传统方式。流程图现在不流行了,但是一旦投入使用,根据详细的流程图编写代码是很简单的。
- 代码注释。有一个老说法:写一次代码,至少被别人看10次。在软件代码中嵌入有用的注释是极为重要的,这样便于维护代码的程序员轻松掌握代码的内容和执行方式。
8.软件生命周期 软件产品从形成概念开始-开发-使用-维护-退役
9.软件开发 软件开发主要由概要设计、详细设计、编程调试、单元测试、组装测试、系统测试和验收测试等阶段组成。
10.软件测试过程V模型
V模型反映了测试活动与分析设计活动的关系。图中,从左到右描述了基本的开发过程和测试行为,非常明确的标注了测试过程中存在的不同类型的测试,并且清楚的描述了这些测试阶段和开发过程期间各阶段的对应关系。 V模型指出,单元和集成测试应检测程序的执行是否满足软件设计的要求;系统测试应检测系统功能、性能的质量特性是否达到系统要求的指标;验收测试确定软件的实现是否满足用户需要或合同的要求。 局限性:仅把测试作为在编码之后的一个阶段,是针对程序进行的寻找错误的活动,而忽视了测试活动对需求分析、系统设计等活动的验证和确认的功能
11.软件测试过程W模型
相对于V模型,W模型增加了软件各开发阶段中应同步进行的验证和确认活动。W模型由两个V字型模型组成,分别代表测试与开发过程,图中明确表示出了测试与开发的并行关系。 W模型强调:测试伴随着整个软件开发周期,而且测试的对象不仅仅是程序,需求、设计等同样要测试,也就是说,测试与开发是同步进行的。W模型有利于尽早地全面的发现问题。例如,需求分析完成后,测试人员就应该参与到对需求的验证和确认活动中,以尽早地找出缺陷所在。同时,对需求的测试也有利于及时了解项目难度和测试风险,及早制定应对措施,这将显著减少总体测试时间,加快项目进度。 局限性:在W模型中,需求、设计、编码等活动被视为串行的,同时,测试和开发活动也保持着一种线性的前后关系,上一阶段完全结束,才可正式开始下一个阶段工作。
12.软件测试的四个阶段 单元测试、集成测试、系统测试、验收测试。是“从小到大”、“由内至外”、“循序渐进”的测试过程,体现了“分而治之”的思想。
- 单元测试的粒度最小,主要测试单元是否符合“设计”,检验每个软件单元能否正确地实现其功能满足其性能和接口要求。
- 集成测试界于单元测试和系统测试之间,起到“桥梁作用”,将经过单元测试的模块逐步进行组装和测试, 检测系统是否达到需求对业务流程及数据流的处理是否符合标准,检测系统对业务流处理是否存在逻辑不严谨及错误。
- 系统测试的粒度最大,主要测试系统是否符合“需求规格说明书”,是否按软件需求规格说明中确定的软件功能、性能、约束及限制等技术要求进行工作。
- 验收测试与系统测试非常相似,主要区别是测试人员不同,验收测试由用户执行。
13.测试的信息流
测试过程中需要三类输入:
- 软件配置:包括软件需求规格说明、软件设计规格说明、源代码等;
- 测试配置:包括测试计划、测试用例、测试驱动程序等。实际上,在整个软件工程过程中,测试配置只是软件配置的一个子集。
- 测试工具:为提高软件测试效率,可使用测试工具支持测试。例如:测试数据自动生成程序、测试结果分析程序等
测试结果分析:比较实测结果与预期结果,评价错误是否发生 排错(调试):对已经发现的错误进行错误定位和确定出错性质,并改正这些错误,同时修改相关的文档
14.测试的种类
名称 说明 黑盒测试: 基于软件需求,而不是基于软件内部设计和程序实现的测试方式。功能性测试 白盒测试: 基于软件内部设计和程序实现的测试方式。结构性测试 单元测试: 主要测试软件模块的源代码。一般由开发人员而非独立测试人员来执行,因为测试者需要懂得该单元的设计与程序实现,测试者可能需要编写另外的驱动程序(driver)和桩(stub)。 集成测试: 将一些“构件”集成一起时,测试它们能否正常运行。这里“构件”可以是程序模块、客户机-服务器程序等等。 功能测试: 测试软件的功能是否符合功能性需求,通常采用黑盒测试方式。一般由独立测试人员执行。 系统测试: 测试软件系统是否符合所有需求,包括功能性需求与非功能性需求。一般由独立测试人员执行,通常采用黑盒测试方式。 回归测试: 指错误被修正之后或软件功能、环境发生变化后全部或部分地重复以前做过的测试。回归测试的困难在于不好确定哪些内容应当被重新测试。 验收测试: 由客户或最终用户执行,测试软件系统是否符合用户需求。 可靠性测试: 也称稳定性测试,连续运行被测系统,检查系统运行时的稳定程度 安全性测试: 测试系统对非法侵入的防范能力。对程序的危险防止和危险处理进行的测试,以验证其是否有效。测试人员扮演非法入侵者 容错性测试/健壮性测试: 检查系统的容错能力,软件在异常条件下自身是否具有防护性的措施或者某种灾难性恢复的手段。测试人员扮演对产品操作一点也不懂的客户,在进行任意操作。 比较测试: 通过与同类产品比较,考察该系统的优点、缺点。 Alpha 测试: 一种先期的用户测试,此时系统刚刚开发完成。 Beta测试: 一种后期的用户测试,此时系统已经通过内部测试,大部分错误已经改正,即将正式发行。
-
按照软件测试是否执行程序而论,软件测试可以分为静态测试和动态测试; 静态测试:对软件进行分析、检查和审阅,不实际运行被测试的软件。静态测试约可找出30~70%的逻辑设计错误。 动态测试:通过运行软件来检验软件的动态行为和运行结果的正确性。两个基本要素:被测试程序,测试数据(测试用例)。内容 :生成测试用例,运行程序,验证程序的运行结果
-
按照软件测试用例的设计方法而论,软件测试可分为白盒测试法和黑盒测试法;
-
按照软件设计方法是否采用面向对象设计技术而论,软件测试又可以分为传统测试方法和面向对象测试方法; 其它特定环境及应用的测试
15.什么是测试用例?
一个测试用例就是一个文档,其目的是确定应用程序的某个特性是否正常的工作。 一个测试用例应当有完整的信息,如:测试用例ID号,测试用例名字,测试用例的目的,测试条件、输入数据需求、步骤和期望结果。
测试用例ID:
目的:
前提:
输入:
预期输出:
后果:
执行历史:
示例:
“用户名” “口令” “预期结果” 说明
“user10” “pass10” 进入系统 正确的用户名和口令(6位)
“user789” “pass789” 进入系统 正确的用户名和口令(7-9位)
16.黑盒测试 黑盒测试:功能性测试,数据驱动测试。是在已知软件产品具有何种功能的前提下,用来检验每个功能是否能够正常使用,需求是否满足的一个测试方法,在软件开发后期进行。把程序看成是一个不能打开的黑盒子,在不考虑程序内部结构的情况下,测试人员用操作接口的方式进行测试,检查程序能否按照需求指定的功能接收输入数据产生正确的结果。
黑盒测试的用例设计方法:
- 边界值分析
假设正在测试一个电子商务网站的注册页面。该页面要求用户提供他们的年龄。最小允许年龄为18岁,最大允许年龄为100岁。请列出边界测试用例,以确保页面正确地处理这些边缘情况。
测试情况 输入 预期输出
最小允许年龄 18 成功注册
低于最小允许年龄 17 收到错误消息“您必须年满18岁才能注册。”
最大允许年龄 100 成功注册
超过最大允许年龄 101 收到错误消息“抱歉,您的年龄不能超过100岁。”
边界条件内的值 50 成功注册
负数 -10 收到错误消息“年龄必须为正整数。”
非数字 abc 收到错误消息“请输入有效的年龄。”
- 等价类划分
序号 功能项 有效等价类 编号 无效等价类 编号 1 a+b 0< 取值 > 99 1 取值<0 ,取值>100 1,3
- 基于决策表的测试
规则
C1:a,b,c构成三角形 Y
C2:a==b Y
C3:a==c Y
C4:b==c Y
A1:非三角形
A2:不规则三角形
A3:等腰三角形
A4:等边三角形 Y
A4:不符合逻辑
- 因果图 E(互斥/异或):表示a,b两原因不会同时成立,最多一个能成立 I(包含):a、b、c三个原因中至少有一个必须成立 O(唯一):a、b当中必须有一个,且仅有一个成立 R(要求):当a出现时,b必须也出现,不可能a出现b不出现; M(强制或屏蔽):结果a是1时,结果b必须是0;结果a是0时,结果b的值不定;
1-分析需求,列出原因和结果
原因 结果
C1:第一个字符是# E1:给出提示信息N
C2:第一个字符是* E2:修改文件
C3:第二个字符是数字 E3:输出信息M
2-找出因果关系,原因与原因之间的约束关系,画出因果图。 3-将因果图转化为决策表
条件:
C1: 1
C2: 1
C3: 1
动作:
E1:
E2:
E3:
不可能 ✅
- 正交实验设计
- 状态测试
黑盒测试的优点有: 1)比较简单,不需要了解程序内部的代码及实现; 2)与软件的内部实现无关; 3)从用户角度出发,能很容易的知道用户会用到哪些功能,会遇到哪些问题; 4)基于软件开发文档,所以也能知道软件实现了文档中的哪些功能; 5)在做软件自动化测试时较为方便。
黑盒测试的缺点有: 1)不可能覆盖所有的代码,覆盖率较低,大概只能达到总代码量的30%; 2)自动化测试的复用性较低
17.白盒测试
结构测试,逻辑驱动测试 前提:知道软件产品内部工作过程。 目标:通过测试来检测软件产品内部动作是否按照规格说明书的规定正常进行。 重点:从程序的控制结构导出测试用例。按照软件内部的结构测试程序,软件中的每条通路是否都能按预定要求正确工作。 在软件开发早期(即编码阶段)执行。 白盒子测试的方法: 1-控制流测试: 语句覆盖:每一个语句至少被执行一次 分支覆盖:每个分支至少被执行一次 路径覆盖:所有可能路径。
2-数据流测试 数据流测试:基于数据流图,设计测试用例以覆盖数据流图上的各个路径 定义覆盖:要确保测试用例能够访问并涉及到程序所有变量的定义 引用覆盖:覆盖程序中使用变量的所有引用 定义-引用覆盖:变量的定义,所有引用
18.测试阶段与测试技术对应表
测试阶段 主要依据 测试技术 主要测试内容 单元测试 详细设计文档 白盒测试 接口测试、路径测试 集成测试 概要设计文档,需求文档 白盒测试,黑盒测试 接口测试、路径测试,功能测试、性能测试 系统测试 需求文档 黑盒测试 功能测试、性能测试、用户界面测试、安全性测试、压力测试、可靠性测试、安装/反安装测试 验收测试 需求文档,验收标准 黑盒测试
20.完整的软件测试工作应该贯穿整个软件生命周期
- 开发的不同阶段都有软件测试工作
- 软件测试工作的各个步骤分散在整个软件生命周期中。
Part-2 静态测试
1.静态测试
静态测试指不运行被测程序本身,而通过分析或检查源程序的语法、结构、过程、接口等检查程序的正确性。
静态测试中的被测对象是各种与软件相关的有必要进行测试的产物,这些被测对象包括了软件需求规约、软件设计说明书、源程序的结构、流程图、符号等。静态测试从这些被测对象中找错。
静态测试常用的方法有:代码走查、数据流分析、控制流分析和信息流分析。
目的是发现软件开发过程中的缺陷和错误,从而提高软件的可靠性和可维护性
静态测试是指在不运行软件的情况下,对软件的需求、设计、代码等进行分析、检查、评审的过程,
2.代码审查/代码走查
代码审查(Code Inspection):1.代码审查准备阶段:在此阶段,主要是为了检查和评估程序源代码做好准备。2.程序阅读:在此阶段,参与者需要对代码进行全面和仔细的阅读,以便能够理解代码的结构、功能和实现方式。3.审查会:在此阶段,参与者将汇集在一起,讨论代码审查的结果,并确定必要的更改和修改。4.跟踪及报告:在此阶段,参与者需要跟踪问题并持续地监控实施中的修复。
代码走查(Walkthrough):代码走查以小组方式进行
3.需求定义的静态测试 4.设计文档的静态测试 5.源代码的静态测试
Part-3 边界值测试
1.功能性测试的主流方法
- 边界值分析:基本边界值分析、健壮性测试、最坏情况测试、健壮最坏情况测试
- 等价类划分 :弱一般、强一般、弱健壮、强健壮
- 判定表
- 因果图
2.边界值分析/健壮性测试/最坏情况测试/健壮最坏情况测试/特殊值测试/举例/随机测试/边界值测试的方针
边界值分析:最小值、略高于最小值、正常值、略低于最大值和最大值 如果有一个变量个数为n的函数,使除一个以外的所有变量取正常值,使剩余的那个变量取最小值、略高于最小值、正常值、略低于最大值和最大值,对每个变量都重复进行。对于一个变量个数为n的函数,边界值分析会产生4n+1个测试用例
数据流测试:是一种关注变量定义赋值点和引用或者使用这些值的点的结构性测试,主要用于路径测试的真实性检查。
3.次日程序的问题描述-边界值分析 次日问题是一个有三个变量表的函数:月,日,年。函数返回输入日期后面的那个日期。变量月,日,年,都具有整数值,且满足以下条件。C1: 1<= month <= 12.C2:1<=day<= 31.C3:1812<=year<= 2012 通过变量的取值范围对基本边界值分析方法进行归纳。对于次日函数,有月,天,年对应的变量,采用类FORTRAN语言(例如PASCAL 或者Ada可以吧变量Month定义为枚举类型1月,2月,12月)不管什么语言,最小值,略高最小值,正常值,略低最大值和最大值更具上下文可以确定。
最小值:对于月、日和年都取其最小值。因此,输入为 1/1/1812。
略高于最小值:对于月和日取其最小值,年取略高于最小值。例如,输入为 1/1/1813。
正常值:使用一个正常的并且可以实际出现的日期作为输入。例如,7/15/2000。
略低于最大值:对于月和日取其最大值,年取略低于最大值。例如,输入为 12/31/2011。
最大值:对于月、日和年都取其最大值。因此,输入为 12/31/2012。
边界值分析的局限性: 假定N个变量是相互独立的,没有考虑这些变量之间的相互依赖关系
3.健壮性测试的基本思想
是边界值分析的一种简单扩展,除了使用五个边界值分析取值,还要通过采用一个略超过最大值(max+)的取值,以及一个略小于最小值(min-)的取值
例如 a∈[1,5], b∈[6,10]
则 a的取值:0,1,2,3,4,5,6
b的取值:5,6,7,8,9,10,11
(a,b)的取值: (3,5), (3,6), (3,7), (3,8), (3,9), (3,10), (3,11), (0,8), (1,8), (2,8), (3,8), (4,8), (5,8), (6,8)
4.一个变量个数为n的函数的健壮性测试会产生多少个测试用例? 6n+1
5.一个变量个数为n的函数的边界值分析测试会产生多少个测试用例? 4n+1
6.最坏情况测试的基本思想
边界值测试分析采用了可靠性理论的单缺陷假设。最坏情况测试拒绝这种假设,关心当多个变量取极值时会出现什么情况。
对每一个变量,分别确定一个包含最小值、略高于最小值、正常值、略低于最大值、最大值这五个元素的集合,然后对这些集合进行笛卡尔积计算,以获得测试用例 X1的取值:x1min, x1min+, x1nom, x1max-, x1max X2的取值:x2min, x2min+, x2nom, x2max-, x2max
例如 a∈[1,5], b∈[6,10]
则 a的取值:1,2,3,4,5
b的取值:6,7,8,9,10
(a,b)的取值:
(1,6), (1,7), (1,8), (1,9), (1,10)
(2,6), (2,7), (2,8), (2,9), (2,10)
(3,6), (3,7), (3,8), (3,9), (3,10)
(4,6), (4,7), (4,8), (4,9), (4,10)
(5,6), (5,7), (5,8), (5,9), (5,10)
一个变量个数为n的函数的最坏情况测试会产生5n个测试用例
7.一个变量个数为n的函数的最坏情况测试测试会产生多少个测试用例? 5的N次方
8.最坏情况测试与基本边界值分析方法的比较
基本边界值分析测试用例是最坏情况测试用例的真子集 。
9.健壮最坏情况测试
对每一个变量,分别确定一个包含最小值、略高于最小值、正常值、略低于最大值、最大值,以及一个略超过最大值的取值,和一个略小于最小值的取值 这样七个元素的集合,然后对这些集合进行笛卡尔积计算,以生成测试用例
例如 a∈[1,5], b∈[6,10]
则 a的取值:0,1,2,3,4,5,6
b的取值:5,6,7,8,9,10,11
(a,b)的取值:
(0,5),(0,6), (0,7), (0,8), (0,9), (0,10), (0,11)
(1,5),(1,6), (1,7), (1,8), (1,9), (1,10), (1,11)
(2,5),(2,6), (2,7), (2,8), (2,9), (2,10), (2,11)
(3,5),(3,6), (3,7), (3,8), (3,9), (3,10), (3,11)
(4,5),(4,6), (4,7), (4,8), (4,9), (4,10), (4,11)
(5,5),(5,6), (5,7), (5,8), (5,9), (5,10), (5,11)
(6,5),(6,6), (6,7), (6,8), (6,9), (6,10), (6,11)
10.一个变量个数为n的函数的健壮最坏情况测试会产生多少个测试用例? 7的N次方
11.特殊值测试 边界值分析假定N个变量是相互独立的,没有考虑这些变量之间的相互依赖关系 次日的边界值分析测试用例是不充分的 没有强调2月和闰年 月、日和年变量之间存在着依赖关系 特殊值测试使用领域知识、使用类似程序的经验开发测试用例的特殊值 设计多个测试用例会涉及2月28日、2月29日和闰年
12.三角形问题边界值分析测试用例
问题描述:我们可以设三角形的3条边分别为A、B、C。如果它们能够构成三角形的3条边,必须满足:
A>0,B>0,C>0,且A+B>C,B+C>A,A+C>B。
如果是等腰的,还要判断A=B,或B=C,或A=C。
如果是等边的,则需判断是否A=B,且B=C,且A=C
假定每条边的取值范围是[1,200]
每条边的取值
1, 2, 100, 199, 200
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
double a, b, c;
cout << "Please input three numbers between 1 and 200: ";
cin >> a >> b >> c;
if (a < 1 || a > 200 || b < 1 || b > 200 || c < 1 || c > 200) {
cout << "Error: The input numbers are out of range." << endl;
return -1;
}
if (!(a + b > c && a + c > b && b + c > a)) {
cout << "Cannot form a triangle." << endl;
return 0;
}
if (a == b && b == c) {
cout << "This is an equilateral triangle." << endl;
} else if (a == b || b == c || a == c) {
cout << "This is an isosceles triangle." << endl;
} else {
cout << "This is a scalene triangle." << endl;
}
return 0;
}
13.三角形问题边界值分析测试用例
(1, 2, 100, 199, 200)
(1, 2, 100, 199, 200)
(1, 2, 100, 199, 200)
(100,100,1)(100,100,2) (100,100,100) (100,100,199) (100,100,200)
(100,1,100)(100,2,100) (100,100,100) (100,199,100) (100,200,100)
(1,100,100)(2,100,100) (100,100,100) (199,100,100) (200,100,100)
14.次日问题函数最坏情况测试用例
月份取值 1, 2, 6, 11, 12 (0,1, 2, 6, 11, 12,13) 日期取值 1, 2, 15, 30, 31 (0,1, 2, 15, 30, 31,32) 年取值 1812, 1813, 1912, 2011, 2012 (1811,1812, 1813, 1912, 2011, 2012 ,2013)
(0, 0), (0, 1), (0, 2), (0, 15), (0, 30), (0, 31), (0, 32),
(1, 0), (1, 1), (1, 2), (1, 15), (1, 30), (1, 31), (1, 32),
(2, 0), (2, 1), (2, 2), (2, 15), (2, 30), (2, 31), (2, 32),
(6, 0), (6, 1), (6, 2), (6, 15), (6, 30), (6, 31), (6, 32),
(11, 0), (11, 1), (11, 2), (11, 15), (11, 30), (11, 31), (11, 32),
(12, 0), (12, 1), (12, 2), (12, 15), (12, 30), (12, 31), (12, 32),
(13, 0), (13, 1), (13, 2), (13, 15), (13, 30), (13, 31), (13, 32)
再求与年的笛卡尔积
15.佣金程序的问题描述
步枪销售商在亚利桑那州境内销售制造商制造的步枪机、枪托和枪管。 枪机卖45美元,枪托卖30美元,枪管卖25美元。销售商每月至少要售出一枝完整的步枪,生产限额考虑到大多数销售商在一个月内可销售70个枪机、80个枪托和90个枪管。销售商在每访问一个镇子之后,给制造商发出电报,说明在那个镇子中售出的枪机、枪托和枪管数量。到了月末,销售商要发出一封很短的电报,通知-1个枪机被售出,以便制造商知道当月的销售情况 销售商的佣金为:销售额不到(含)1000美元的部分,为10%;1000(不含)到1800(含)美元的部分,为15%;超过1800美元的部分为20% 佣金程序生成月份销售报告,汇总售出的枪机、枪托和枪管总数,销售商的总销售额,以及佣金。佣金问题的输入空间 低于较低平面的值,对应低于1000美元门限的销售额,佣金为10% 两个平面之间的值,是15%佣金区域 高于较高平面的值,对应高于1800美元门限的销售额,超过部分的佣金为20%
寻找输出边界值(销售额)为100美元、1000美元、1800美元和7800美元对应的输入变量组合?
答: 当销售额为100美元时,佣金为10% 输入变量组合:1枝枪机、0枝枪托和0根枪管
当销售额为1000美元时,佣金为15% 输入变量组合:22枝枪机、0枝枪托和0根枪管(共计990美元,接近1000美元门限点) 当销售额为1800美元时,佣金为15% 输入变量组合:55枝枪机、20枝枪托和0根枪管(共计1795美元,接近1800美元门限点)
当销售额为7800美元时,佣金为20% 输入变量组合:70枝枪机、80枝枪托和90根枪管 需要
通过电子表格或编写程序可以自动设计测试用例,节省了大量计算工作 最大值和最小值的确定很容易,给出的数正好便于生成边界点。 比如销售额接近1000美元和1800美元门限点的值。输出值域的边界值
写出佣金问题的输出特殊值测试?
答:
枪击10 枪托9 枪管9 销售额 1005 佣金 100.75 边界点+
枪击18 枪托17 枪管19 销售额 1795 佣金 219.25边界点-
枪击18 枪托19 枪管17 销售额 1805 佣金 221 边界点+
佣金问题的测试用例 关键点测试用例9是1000美元的边界点 枪机卖45美元,枪托卖30美元,枪管卖25美元,均卖10个 调整输入变量则可以得到略低和略高于该边界的值 测试用例6-8 测试用例10-12
测试用例17恰好是1800美元临界值 枪机卖45美元,枪托卖30美元,枪管卖25美元,各卖18个 通过调整输入变量取值,可以构造略低于和略高于该临界值的输出 测试用例14-16 测试用例18-20
16.边界值分析的原则
如果输入条件规定了取值范围,或规定了值的个数,测试用例选择:范围的边界内,刚刚超出范围的边界外的值;或者说:最小值、稍高于最小值、正常值、稍低于最大值、最大值
例1:程序的规格说明:“重量在10~50公斤范围内的邮件,其计算邮费……”
测试用例选择:取10公斤,10.01公斤,25公斤,49.99公斤,50公斤
例2:“某输入文件可包含1~255个记录,”
测试用例选择:记录个数取1,2,120,254,255
17.一个函数有2个输入,一个是大写A到Z的字母,另一个是在0到100之间的数字(可以取到边界),分别用边界值分析、健壮性测试和最坏情况测试的方法写出测试用例。
边界值分析
(A,B,N,Y,Z)
(0,1 50,99,100)
(N,0)(N,1)(N,50)(N,99)(N,100)
(A,50)(B,50)(N,50)(Y,50)(Z,50)
健壮性测试:
(A,B,N,Y,Z)
(-1,0,1 50,99,100,101)
(N,0)(N,1)(N,50)(N,99)(N,100)
(A,50)(B,50)(N,50)(Y,50)(Z,50)
(A,B,N,Y,Z)
(0,1 50,99,100)
(A,50)(B,50)(N,50)(Y,50)(Z,50)
(A,50)(B,50)(N,50)(Y,50)(Z,50)
(B,50)(B,50)(N,50)(Y,50)(Z,50)
(C,50)(C,50)(N,50)(Y,50)(Z,50)
....
18.等价类测试
等价类的划分有两种不同的情况: 有效等价类(合理等价类) 无效等价类(不合理等价类) 划分等价类的标准: 覆盖 不相交 代表性
- 如果输入条件规定了取值范围,可定义一个有效等价类和两个无效等价类。「学生成绩0~100」有效:60,无效-1,101
- 如果规定了输入数据的个数,则类似地可以划分出一个有效等价类和两个无效等价类「学生只能选修1~3门」『有效:学生只能选修1~3门』『无效:不选。无效:选修超过3门』
- 输入条件规定了输入值的集合,或是规定了“必须如何”的条件,则可确定一个有效等价类和一个无效等价类「标识符以字母开头”」 「有效等价类:以字母开头的字符串」「无效等价类:以非字母开头的字符串」
- 如规定了输入数据的一组值,且程序对不同输入值做不同处理,则每个允许的输入值是一个有效等价类,并有一个无效等价类(所有不允许的输入值的集合)「输入条件说明学历可为:专科、本科、硕士、博士四种之一」「有效等价类:①专科、②本科、③硕士、④博士」「无效等价类:①其它任何学历」
- 如果规定了输入数据必须遵循的规则,可确定一个有效等价类(符合规则)和若干个无效等价类(从不同角度违反规则)「校内电话号码拨外线为9开头」「有效等价类:① 9+外线号码」「无效等价类:①非9开头+外线号码 ② 9+非外线号码,…」
- 如果确知,已划分的等价类中各元素在程序中的处理方式不同,则应将此等价类进一步划分成更小的等价类
工资所得税计算:计税额=工资– 1600
有效:
1 不超过500元的 5%
2 超过500元至2,000元的部分 10%
3 超过2,000元至5,000元的部分 15%
4 超过5,000元至20,000元的部分 20%
5 超过20 000元至40 000元的部分 25%
6 超过40,000元至60,000元的部分 30%
7 超过60,000元至80,000元的部分 35%
8 超过80,000元至100,000元的部分 40%
9 过100,000元的部分 45%
无效:a
19.设某公司要打印2001~2005年的报表,其中报表日期为6位数字组成,其中,前4位为年份,后两位为月份。
有效 无效
个数: 6位数字 非数字,少于6,多于6
year: 2001~2005 小于2000,大于2005
month: 1~12 小于01 ,大于12
测试数据 期望结果 覆盖范围
200105 输入有效 等价类①②③
测试数据 期望结果 覆盖范围
001MAY 输入无效 等价类④
20015 输入无效 等价类⑤
2001005 输入无效 等价类⑥
200005 输入无效 等价类⑦
200805 输入无效 等价类⑧
200100 输入无效 等价类⑨
200113 输入无效 等价类⑩
20.城市的电话号码由两部分组成。这两部分的名称和内容分别是: 地区码:以0开头的三位或者四位数字 电话号码:以非0、非1开头的七位或者八位数字假定被调试的程序能接受一切符合上述规定的电话号码,拒绝所有不符合规定的号码,就可用等价分类法来设计它的测试用例
输入数据
地区码
有效等价类
以0开头的3位数串
以0开头的4位数串
无效等价类
以0开头的含非数字字符的3位或4位字符串
以0开头的小于3位的数串
以0开头的大于4位的数串
以非0开头的3位或4位数串
电话号码:
有效等价类
以非0、非1开头的7位数串
以非0、非1开头的8位数串
无效等价类
以0开头的7位或8位数串
以1开头的7位或8位数串
以非0、非1开头的含非数字字符的7位或8位字符串
以非0、非1开头的小于7位数串
以非0、非1开头的大于8位数串
测试数据 期望结果 覆盖范围
010 23145678 显示有效输入 (1)、(8)
023 2234567 显示有效输入 (1)、(7)
0851 3456789 显示有效输入 (2)、(7)
0851 23145678 显示有效输入 (2)、(8)
21.三角形问题接受三个整数A、B和C作为输入,将其用作三角形三条边的长度值,程序的输出是由这三条边确定的三角形的类型:等边三角形、等腰三角形、不等边三角形或非三角形。
我们可以设三角形的3条边分别为A,B,C 如果它们能够构成三角形的3条边,必须满足:A>0,B>0,C>0,且A+B>C,B+C>A,A+C>B 如果是等腰的,还要判断A=B,或B=C,或A=C 如果是等边的,则需判断是否A=B,且B=C,且A=C
22.“三角形问题接受三个整数A、B和C作为输入,将其用作三角形三条边的长度值,程序的输出是由这三条边确定的三角形的类型:等边三角形、等腰三角形、不等边三角形或非三角形。”
我们可以设三角形的3条边分别为A,B,C 如果它们能够构成三角形的3条边,必须满足:A>0,B>0,C>0,且A+B>C,B+C>A,A+C>B 如果是等腰的,还要判断A=B,或B=C,或A=C 如果是等边的,则需判断是否A=B,且B=C,且A=C
是否是三角形的三条边
有效:
A>0
B>0
C>0
A+B>C
A+C>B
B+C>A
无效:
A<=0
B<=0
C<=0
A+B<=C
A+C<=B
B+C<=A
是否是等腰三角形
有效:
A=B
B=C
A=C
无效:
A!=B And B!=C And C!=A
是否是等边三角形
有效:
A=B and B=C and C=A
无效:
A!=B
B!=C
C!=A
23.等价类测试的分类
- 弱一般等价类测试:弱一般等价类测试通过使用一个测试用例中的每个等价类(区间)的一个变量实现.
-
一个变量个数为n的函数的弱一般等价类测试会产生多少个测试用例? 区间个数的最大值
- 强一般等价类测试
-
一个变量个数为n的函数的强一般等价类测试会产生多少个测试用例?各个输入变量区间数的乘积
-
弱健壮等价类测试
- 强健壮等价类测试
24.一个具有两个自变量X1和X2的函数F,F实现位一个程序,且,输入变量X1和X2的边界以及边界内的区间 a<= x1 <= d 且程序对X1取「a,b)「b,c」「c,d」 做出不同的处理 e <=X2 <=g 区间为「e,f」「f,g」
25.三角形问题的输出(值域)等价类
4种可能出现的输出
不是三角形、非等边三角形、等腰三角形和等边三角形
输出(值域)等价类:
R1={<a,b,c>:有三条边a、b和c的等边三角形}
R2={<a,b,c>:有三条边a、b和c的等腰三角形}
R3={<a,b,c>:有三条边a、b和c的不等边三角形}
R4={<a,b,c>:三条边a、b和c不构成三角形}
26.弱一般等价类测试/弱健壮性测试/强健壮性测试
弱一般等价类测试
测试用例 a b c 预期输出
WN1 5 5 5 等边
WN2 2 2 3 等腰
WN3 3 4 5 不等边
WN4 4 1 2 非三角
弱健壮性测试
测试用例 a b c 预期输出
WN1 -5 5 5 a取值在不允许的取值值域内
WN2 2 -2 5 b取值在不允许的取值值域内
WN3 3 4 -1 c取值在不允许的取值值域内
WN4 500 5 2 a取值在不允许的取值值域内
WN5 2 200 5 b取值在不允许的取值值域内
WN6 3 4 100 c取值在不允许的取值值域内
强健壮性测试
测试用例 a b c 预期输出
WN1 -5 5 5 a取值在不允许的取值值域内
WN2 2 -2 5 b取值在不允许的取值值域内
WN3 3 4 -1 c取值在不允许的取值值域内
WN4 -5 -5 5 a,b取值在不允许的取值值域内
WN5 2 -2 -5 b,c取值在不允许的取值值域内
WN6 -3 4 -1 a,c取值在不允许的取值值域内
27.NextDate 函数包含三个变量 month、day和year,函数的输出为输入日期后一天的日期。 例如,输入为1989年5月16日,则函数的输出为1989年5月17日。 要求输入变量 month、 day和year均为整数值,并且满足下列条件,也就是有效等价类:1 ≤ month ≤12 /1≤ day ≤31 /1812≤ year ≤2012
无效等价类:month<1,month>12,day<1,day>31,year<1812,year>2012
次日问题的弱一般等价类测试
弱一般等价类测试
month day year 输出
6 15 1912 1912/6/16
弱健壮性测试
month day year 输出
6 15 1912 1912/6/16
-1 15 1912 month 不在有效值域
13 15 1912 month不在有效值域
1 -1 1912 day 不在有效值域
13 32 1912 day不在有效值域
1 -1 1911 year 不在有效值域
13 32 2013 year不在有效值域
强健壮性测试
month day year 输出
6 15 1912 1912/6/16
-1 15 1912 month 不在有效值域
13 15 1912 month不在有效值域
1 -1 1912 day 不在有效值域
13 32 1912 day不在有效值域
1 -1 1911 year 不在有效值域
13 32 2013 year不在有效值域
-1 -1 1912 month,day 不在有效值域
...
等价类测试的关键是等价关系的选择。如果能更细致地选择等价关系,那么得到的等价类可能更有用。 等价关系的要点是,等价类中的元素将被“同样处理”。通过关注更具体的处理,可降低粒度。
M1={月份:每月有30天}
M2={月份:每月有31天}
M3={月份:此月是2月}
D1={日期:1≤日期≤28}
D2={日期:日期=29}
D3={日期:日期=30}
D4={日期:日期=31}
Y1={年:年=2000}
Y2={年:年是闰年,且年≠2000}
Y3={年:年是平年}
按照新的等价类划分的方法产生的弱一般等价类测试
弱一般等价类测试
month day year 输出
6 15 1912 1912/6/16
2 30 2001 不可能的输入
6 31 2000 不可能的输入
改进的强一般等价类测试用例
28.回顾佣金问题 步枪销售商在亚利桑那州境内销售制造商制造的枪机、枪托和枪管。枪机卖45美元,枪托卖30美元,枪管卖25美元 销售商每月至少要售出一枝完整的步枪,生产限额考虑到大多数销售商在一个月内可销售70个枪机、80个枪托和90个枪管 销售商在每访问一个镇子之后,给制造商发出电报,说明在那个镇子中售出的枪机、枪托和枪管数量。到了月末,销售商要发出一封很短的电报,通知-1个枪机被售出 销售商的佣金为:销售额不到(含)1000美元的部分,为10%;1000(不含)到1800(含)美元的部分,为15%;超过1800美元的部分为20% 佣金程序生成月份销售报告,汇总售出的枪机、枪托和枪管总数,销售商的总销售额,以及佣金
佣金问题的等价类测试用例
除了变量的名称和端点值区间不同之外,与次日函数的第一个版本完全相同,佣金问题也只有一个弱一般等价类测试用例,这个测试用例同样也等于强一般等价类测试用例
佣金问题同样也有7个弱健壮测试用例
强健壮性等价类测试用例
强健壮等价类测试
ID 枪机 枪托 枪管 输出
1 -1 40 45 枪机不在有效值域
2 35 -1 45 枪托不在有效值域
3 35 40 -1 枪管不在有效值域
4 -1 -1 45 枪机,枪托不在有效值域
....
29.佣金问题的输出值域等价类测试
根据佣金值域定义三个变量的等价类: S1={<枪机,枪托,枪管>:销售额≤1000} S2={<枪机,枪托,枪管>:1000 < 销售额≤1800} S3={<枪机,枪托,枪管>:销售额>1800}
ID 枪机 枪托 枪管 销售额 输出
1 5 5 5 500 50
2 15 15 15 1500 175
3 25 25 25 2500 360
30.等价类测试方法
- 如果输入数据以离散值区间和集合定义,则等价类测试是合适的,当然也适用于如果变量值越界系统就会出现错误的系统
- 如果程序函数很复杂,则等价类测试是合适的。在这种情况下,函数的复杂性可以帮助标识有用的等价类,就像次日函数一样
31.练习:某公司招聘人员,其要求为:学历:本科及以上;专业:计算机或通信;年龄:22-30岁。请用弱一般等价类测试,强一般等价类测试和弱健壮等价类测试方法写出测试输入数据。
弱一般等价类测试
ID 学历 专业 年龄 输出
1 本科 计算机 27 符合要求
一个变量个数为n的函数的弱一般等价类测试会产生多少个测试用例?区间个数的最大值
强一般等价类测试
ID 学历 专业 年龄 输出
1 本科 计算机 27 符合要求
2 硕士 计算机 29 符合要求
3 博士 计算机 29 符合要求
一个变量个数为n的函数的强一般等价类测试会产生多少个测试用例?各个输入变量区间数的乘积
弱健壮性测试
ID 学历 专业 年龄 输出
1 本科 计算机 27 符合要求
2 本科一下 计算机 29 不符合要求
3 本科 非计算机 29 不符合要求
4 本科 计算机 31 不符合要求
Part-4 基于判定表的测试
1.判定表的组成
条件桩 条件项 规则
动作桩 动作项
三角形问题基于判定表的测试用例
a,b,c构成三角形? N Y Y Y
a=b - Y
a=c - Y
b=c - Y
非三角形 X
不等边三角形
等腰三角形
等边三角形 X
贯穿条件项和动作项的一列
2.问题要求:”对功率大于50马力且维修记录不全的机器,或者已运行10年以上的机器,应给予优先的维修处理……” 假定,“维修记录不全”和“优先维修处理”均已在别处有更严格的定义 按5步建立判定表
功率大于50
维修记录不全
运行10年以上
优先维修处理
其他处理
3.次日函数基于判定表的测试用例
等价类集合
M1={月份:每月有30天}
M2={月份:每月有31天}
M3={月份:此月是2月}
D1={日期:1≤日期≤28}
D2={日期:日期=29}
D3={日期:日期=30}
D4={日期:日期=31}
Y1={年:年是闰年}
Y2={年:年不是闰年}
月在M1
月在M2
月在M3
日在D1
日在D2
日在D3
年在Y1
基于等价类的带有互相排斥条件决策表
等价类集合
M1={月份:每月有30天}
M2={月份:每月有31天}
M3={月份:此月是2月}
D1={日期:1≤日期≤28}
D2={日期:日期=29}
D3={日期:日期=30}
D4={日期:日期=31}
Y1={年:年=2000}
Y2={年:年是闰年,且年≠2000}
避免条件项“重叠”,减少冗余
Y3={年:年是平年}
月在 M1 M1 M1 M1 M2 M2 M2 M2 M3 M3 M3
日在 D1 D2 D3 D4
年在
不可能
日增1
日复位
月增1
月复位
年增1
3.佣金问题基于判定表的测试用例
决策表分析不太适合佣金问题 在佣金问题中只有很少的判断逻辑 if-then-else逻辑很突出 输入变量之间存在逻辑关系 涉及输入变量子集的计算 输入与输出之间存在因果关系 很高的McCabe圈复杂度
4.练习
某银行发放贷款原则如下 1对于贷款未超过限额的客户,允许立即贷款。2对于贷款超过限额的客户,若过去还款记录好且本次贷款在2万元以下,可作出贷款安排;否则拒绝贷款。请绘出发放贷款的决策表并优化。
贷款未超过限额 T
还款记录好 T
本次贷款在2万元以下 T
允许立即贷款 T F
5.功能性测试
这些方法的共同之处就是将程序看作是将输入映射到输出的数学函数。根据研究输入值的属性演变成基于边界值的方法,等价类的方法和判定表的方法、因果图、正交测试等。
6.边界值分析
边界值分析:单缺陷、正常值 健壮性测试:单缺陷、有异常情况 最坏情况测试:多缺陷、正常值 健壮最坏情况测试:多缺陷、有异常情况
7.等价类划分
弱一般:单缺陷、正常值 强一般:多缺陷、正常值 弱健壮:单缺陷、异常值 强健壮:多缺陷、异常值
8.判定表,决策表
9.每种测试方法的精细程度
边界值分析 不识别数据或逻辑依赖关系,采用非常机械的方式生成测试用例,很容易被自动化
等价类划分 注意到数据依赖关系和函数本身使用这些手段需要更多的考虑,还需要更多的判断和技巧 首先要考虑如何标识等价类,之后的处理也是机械的
判定表 要求测试人员既要考虑数据,又要考虑逻辑依赖关系 通常通过一遍尝试可能不能得到决策表的条件,但是如果有了一个良好的条件集合,所得到的测试用例就是完备的,在一定意义上还是最少的
精细程度从小到大 测试用例效果从小到大
10.根据两个因素计算半年保险金 投保人的年龄 驾驶历史记录 保险金=基本保险费率×年龄系数-安全驾驶折扣 年龄系数是投保人年龄的函数 如果投保人驾驶执照上的当前点数(根据交通违规次数确定)低于与年龄有关的门限,则给予安全驾驶折扣 驾驶人年龄范围为从16岁到100岁 如果投保人有12点,则驾驶人的执照就会被吊销(因此不需要保险) 基本保险费率随时间变化,对于这个例子,是每半年500美元
年龄和点数在最坏情况边界值测试下的取值
年龄 16 17 54 99 100
点数 0 1 6 11 12
Part-5 结构性测试-控制流测试
控制流测试:以程序图为基础(结点表示语句片断,边表示控制流),通过图论的一些知识完全从程序的结构来定义结构性的测试,而不考虑代码本身的内在关系
基于数据流的测试:从代码本身的内在关系出发进行的一种结构性的测试
1.逻辑覆盖
语句覆盖: 判定覆盖:判定覆盖(Decision Coverage):要求每个判断语句的两种结果至少执行一次,以覆盖所有可能的路径。
判定覆盖(Decision Coverage):要求每个判断语句的两种结果至少执行一次,以覆盖所有可能的路径。
条件覆盖:条件覆盖(Condition Coverage):在判定覆盖的基础上,要求每个条件语句中的每个条件都取到true和false两种可能值。
判定-条件覆盖:要求每个判断语句中的每个条件都取到true和false两种可能值,并且每个判断本身的判定结果(真假)都至少执行一次。
条件组合覆盖:条件组合覆盖要求覆盖每个判断语句的所有条件组合,以确保所有可能情况都被测试到。
路径覆盖:路径覆盖(Path Coverage):要求覆盖程序中所有可能的路径,即从程序的入口进入,直到所有可能的出口,期间每条可行的路径都走一遍。这是最严格的覆盖标准。
int a,b;
double c ;
scanf("%d,%d,%f",&a,&b,&c); // 读入 a, b, c
if (a > 0 && b > 0) { // 如果同时满足 a > 0 和 b > 0
c = c / a; // 执行除法运算,并将结果赋值给 c
}
if (a > 1 || c > 1) { // 如果 a > 1 或者 c > 1
c = c + 1; // 将 c 加一
}
c = b + c; // 将 b 和 c 相加,将结果赋值给 c
printf("%d, %d, %.2f\n", a, b, c); // 输出 a, b, c ,其中 c 保留两位小数
语句覆盖
a=2 b=1 c=6
判定覆盖
a=-1 b=0 c=0
a= 2 b= 1 c= 2
条件覆盖
a=-1 b=0 c=0
a= 2 b= 1 c= 2
判定-条件
a=-1 b=0 c=0
a= 2 b= 1 c= 2
条件-组合
a=1 b=1 c=1
a=2 b=1 c=2
a=-1 b= -1 c=-1
a=2 b=-1 c=2
路径风格
a=1 b=1 c=1
a=1 b=1 c=2
a=0 b=1 c=2
a=0 b=1 c=1
2.DD路径
程序图/控制流图 节点: 以标有编号的圆圈表示。它代表了程序流程图中矩形框表示的处理、菱形表示的两个到多个出口判断以及两条到多条流线相交的汇合点。可以把几个节点合并成一个,合并的原则是:若在一个节点序列中没有分支,则我们可以把这个序列的节点都合并成一个节点
3.半路径/路径 半路径:就是一条没有回路的路径,它的起点和终点没有限制,但是路径中相邻的某两条边必须有公共的一个节点。
路径:是由一系列边组成的,每两条相邻的边必须满足第一条边的终止节点是第二条边的起始节点,才能形成一条合法的路径。
4.有向图中的两个结点ni和nj
0-连接,当且仅当ni和nj之间没有路径 1-连接,当且仅当ni和nj之间有一条半路径,但没有路径 2-连接,当且仅当ni和nj之间有一条路径 3-连接,当且仅当ni和nj之间有一条路径,并且从nj到ni有一条路径
5.DD-路径是程序图中的一条链 情况1:由一个结点组成,indeg=0; 情况2:由一个结点组成,outdeg=0; 情况3:由一个结点组成,indeg≥2 或 outdeg≥2; 情况4:由一个结点组成,indeg=1 并且outdeg=1; 情况5:长度≥1的最大链
6.McCabe圈复杂度 分支节点数加1/ E – N + 2
7.基路径测试步骤 导出程序流程图的拓扑结构——控制流图(程序图) 计算控制流图的McCabe圈复杂度(设为n) 确定基本路径集,即构造n条独立路径
原始
在B处翻转
在F处翻转
在H处翻转
在J处翻转
1-2-3-6-7-9-10-1-11
1-11
1-2-3-4,5-10-1-11
1-2-3-6-8-9-10-1-11
8.练习
原始
2 3 10 5 6
1-2-10-11-13
1-2-10-12-13
1-2-3-10-11-13
1-2-3-4-5-8-9-2
1-2-3-4-5-6-8-9-2
1-2-3-4-5-6-7-8-9-2
8.请分别选出用语句覆盖,条件覆盖,路径覆盖应用哪组测试用例(请写出设计过程)。
语句覆盖:(1)(2) 条件覆盖:(1)(4) (2) 路径覆盖:(1)(4) (2)
9.基路径测试一下程序
Part-6 结构性测试-基于数据流的测试
数据流测试关注变量接收值的点和使用这些值的点
覆盖每个定义-使用路径一次
1.变量定义的节点 DEF(v, n) 变量v的值由对应结点n的语句片段处定义
DEF(lockPrice,7)
DEF(locks,13)
2.变量使用的节点 USE(v, n) 变量v的值在对应结点n的语句片段处使用
USE(commission,33)
USE(commission,41)
USE(v, n)是一个谓词使用(记作P-use),当且仅当语句n是谓词语句;否则,USE(v, n)是计算使用(记作C-use)
- 谓词使用的结点,其出度≥2
- 计算使用的结点,其出度≤1
3.变量v的定义-使用路径(记作du-path) P中的所有路径集合PATHS(P)中的路径,使得对某个v∈V,存在定义和使用结点DEF(v, m)和USE(v, n),使得m和n是该路径的最初和最终结点
4.变量v的定义清除路径(definition-clear path,记作dc-path) 最初和最终结点DEF(v, m)和USE(v, n)的PATHS(P)中的路径,使得该路径中没有其他结点是v的定义结点,没有定义节点,可以是为、
结点序列<11,12,13,14,15,16,17>组成的路径(11,17)是定义清除路径
Program Commission(input,output)
Dim locks, stocks, barrels As Interger
Dim lockPrice, stockPrice, barrelPrice As Real
Dim totalLocks, totalStocks, TotalBarrels As Integer
Dim lockSales, stockSales, barrelSales As Integer
Dim sales, commission As Real
lockPrice = 45.0
stockPrice = 30.0
barrelPrice = 25.0
totalLocks = 0
totalStocks = 0
totalBarrels = 0
Input(locks)
While NOT (locks = -1)
Input(stocks, barrels)
totalLocks = totalLocks + locks
totalStocks = totalStocks + stocks
totalBarrels = totalBarrels + barrels
Input(locks)
EndWhile
Output("Locks sold: ",totalLocks)
Output("Stocks sold: ",totalStocks)
Output("Barrels sold: ",totalBarrels)
lockSales = lockPrice*totalLocks
stockSales = stockPrice*totalStocks
barrelSales = barrelPrice*totalBarrels
sales = lockSales + stockSales + barrelSales
Output("Total sales: ",sales)
If (sales>1800.0)
Then
// commission:定义
commission=0.10*1000.0
// commission:定义+使用
commission=commission+0.15*800.0
//commission:定义+使用
commission=commission+0.20*(sales-1800.0)
Else If (sales>1000.0)
Then
// commission:定义
commission=0.10*1000.0
// commission:定义+使用
commission=commission+0.15*(sales-1000.0)
// commission:定义+使用
Else commission=0.10*sales
EndIf
Endlf
Output("Commission is $",commission)
End Commission
5.全定义覆盖准则
集合T满足程序P的全定义(all definition)准则,当且仅当对于所有变量v∈V,T包含从v的每个定义结点到v的一个使用的定义清除路径
6.全使用覆盖准则 集合T满足程序P的全使用(all use)准则,当且仅当对于所有变量v∈V,T包含从v的每个定义结点到v的所有使用的定义清除路径
7.全使用覆盖与全定义-使用覆盖的区别
b:定义X,Y
c:引用X和Y 定义X
d:引用X和Y 定义Y
结点b定义x,y,结点c和d使用b所定义的x,y
全使用覆盖:检查每个定义的所有可传递到的使用,但对如何从一个定义传递到一个使用不作要求。
全定义覆盖:使用覆盖要求检查所有可能的路径,但为了避免有环路时的无穷多条路径,限制只检查无环路的或只包含一条环路的路径
8.基于程序片的测试
13 Input(locks)
14 While NOT (locks = -1)
15 Input(stocks, barrels)
16 totalLocks = totalLocks + locks
17 totalStocks = totalStocks + stocks
18 totalBarrels = totalBarrels + barrels
19 Input(locks)
20 EndWhile
变量locks上的片:
S1: S(locks,13)=(13)
S2: S(locks,14) = (13,14,19,20)
S3: S(locks,16) = (13,14,16,19,20)
S4: S(locks,19) = (19)
9.定义节点 定义节点 – DEF(v,n)
使用节点 – USE(v,n)
谓词使用 – P-use
计算使用 – C-use
定义-使用路径 – du-path:变量v的定义-使用路径(记du-path)P中的所有路径集合PATHS(P)中的路径,使得对某个v∈V,存在定义和使用结点DEF(v, m)和USE(v, n),使得m和n是该路径的最初和最终结点
定义-清除路径 – dc-path:变量v的定义清除路径(definition-clear path,记作dc-path)最初和最终结点DEF(v, m)和USE(v, n)的PATHS(P)中的路径,使得该路径中没有其他结点是v的定义结点
全定义覆盖准则:测试路径需要覆盖所有定义点和任意一个使用点,用dc-path扩展成测试路径
全使用覆盖准则:测试路径需要覆盖所有定义点和所有使用点,用dc-path扩展成测试路径
全定义-使用路径覆盖准则:测试路径需要覆盖所有定义点到所有使用点的路径,用dc-path扩展成测试路径
10.练习 写出a变量的定义-使用路径,并判断是否定义清除路径。写出变量a的程序片。
a=5;
While(C1) {
if (C2){
b=a*a;
a=a-1;
}
print(a);
}
//https://blog.csdn.net/william_munch/article/details/85273730
定义节点:1,5 使用节点:4,5,6 定义使用路径: 1-2-3-4 是 1-2-3-4-5 否 1-2-3-4-5-6 否
https://wenku.baidu.com/view/80295fcd852458fb760b5684?pcf=2&re=view&bfetype=new&bfetype=new&_wkts_=1684201483711&login_type=weixin
Part7-结构性测试
1.何时停止测试?
当继续测试没有产生新失效时 当继续测试没有产生新缺陷时 当所要求的覆盖率达到时
2.用于方法评估的指标的定义
功能性测试手段M生成m个测试用例,并且根据标识被测单元中的s个元素的结构性测试指标S来跟踪这些测试用例。执行m个测试用例时,会经过n个结构性测试元素
方法M关于指标S的覆盖率C(M,S),是n与s的比值,即C(M,S)=n/s 方法M关于指标S的冗余R(M,S),是m与s的比值,即R(M,S)=m/s 方法M关于指标S的净冗余NR(M,S),是m与n的比值,即NR(M,S)=m/n
3.DD-路径测试 即判定/分支覆盖:程序中每个判定的各个分支至少经历一次
4.基路径测试 控制流图/程序图的圈复杂度V(G)=11,因此基本路径集包括11条独立路径
Part8-集成测试
1.集成测试的方法?
基于分解的集成: 这种方法将系统分解为多个模块,逐步地将每个模块与其他模块组合起来进行测试,直到整个系统被完全集成为止。在集成过程中,可以采用增量式的方式,根据测试结果不断调整和优化模块间的接口和交互。
基于调用图的集成: 这种方法使用系统内部的调用图来确定测试顺序和优先级。测试人员先对系统中的基本模块进行测试,然后从调用关系中找出下一个需要测试的模块,逐步往后测试,直到整个系统被完全集成为止。
包括: 成对集成测试(Pair-wise Integration Testing) 相邻集成测试(Neighborhood Integration Testing)
成对集成测试: 主要考虑组件之间的交互作用。它将每个组件与其它组件配对,确保每个组件至少与另一个组件进行了一次交互。这种方法能够有效地发现组件之间的接口问题,但可能无法检测到组件内部的问题。
相邻集成测试: 则是在组件的层次结构上进行的测试。该方法从最底层的组件开始,逐层向上测试,直到整个系统被测试为止。这种方法优点是可以发现组件内部的问题,并且具有逐渐推进、逐步加深的过程,缺点是测试所需时间相对较长。
基于路径的集成:
这种方法主要是针对复杂系统的测试,它通过模型验证或静态代码分析等方式,建立系统的控制流模型和数据流模型,然后根据这些模型来生成测试用例并进行测试。在测试过程中,测试人员会关注系统中的各种路径和变量赋值情况,以确保系统在各种情况下都能正常运行。
2.什么是集成测试? 集成测试将经过单元测试的模块逐步进行组装和测试 集成测试验证程序和概要设计说明的一致性 集成测试在模块组装后查找模块间接口的错误
3.什么是结构化的分析方法?
- 功能模型:数据流图
- 数据模型:E-R图
- 控制模型:有限状态机
4.MM-路径? 穿插出现模块执行路径和消息的序列。 用来描述包含在不同单元之间转移控制的模块执行路径序列,这种转移是通过消息完成的 MM-路径总是代表了可行的执行路径,并且这些路径要跨越单元边界 在经过扩展的程序图中可以发现MM-路径,其中的结点表示模块执行路径,边表示消息。MM-路径图是一种有向图,其中的结点表示模块执行路径,边表示单元之间的消息和返回
5.程序(Page200-202) 写出第一次尝试正确PIN输入的MM-路径
Part9-系统测试
1.系统测试 回归测试(regression testing) 功能测试(function test) 用户界面测试(GUI test) 压力测试(stress test) 性能测试(performance test) 安全测试(security test) 容错测试(recovery test)
2.线索
子系统功能由一组ASF节点和串行流边构成的有向图表示。源ASF和汇ASF分别是入口和出口点,其中“ATM卡输入”作为源ASF,“会话结束”作为汇ASF。系统线索是从源ASF到汇ASF的路径,它表示了系统中指令或操作的执行顺序。线索图是对系统的ASF图进行抽象化处理,将一系列操作表示为按特定顺序连接在一起的节点,并通过有向边表示操作的执行顺序。
3.基于数据的线索测试 基于数据的线索测试适用于数据驱动的系统,特别是以数据库为基础的系统。 图书馆系统的一些典型事务处理: 图书馆添加图书 图书馆撤除图书 图书馆增加借阅者 图书馆删除借阅者 向借阅者出借图书 借阅者返还图书处理
数据驱动的系统,特别是以数据库为基础的系统,可以借助基于数据的线索测试来进行测试。而在图书馆系统中,各种事务处理都涉及到数据的输入、输出和处理,因此基于数据的线索测试非常适用于该系统。以下是具体的组线索示例:
DM1:检查每个关系的基数 针对每个关系,编写测试用例并进行测试,以验证基数是否符合预期。例如,对于“图书”关系,可以验证添加一本图书后图书数量是否增加了1。 DM2:检查每个关系的参与 对于每个关系,检查它是否参与了所有需要它参与的事务处理,以确保所有数据都能被正确地处理和更新。例如,对于“借阅记录”关系,需要验证它是否正确记录了每次图书的借阅和归还。 DM3:检查关系之间的函数依赖关系 对于多个关系之间的函数依赖关系,需要设计一组测试用例,并进行测试,以确保系统的数据处理逻辑是正确的。例如,如果“借阅记录”依赖于“图书”和“借阅者”关系,那么需要验证当图书或借阅者信息发生变化时,相关的借阅记录是否正确地被更新。 额外线索示例:不能借出不属于图书馆的图书 针对这种特殊的逻辑关系,需要设计一组测试用例,并进行测试,以确保系统能够正确地处理这种情况。例如,在借阅时,需要验证当借阅者尝试借阅不属于图书馆的图书时,系统是否会拒绝该请求并提示错误信息
4.基于用例的线索
5.基于事件的线索测试
Part-10 面向对象的测试
1.面向对象软件的特征:
封装性:将数据和对数据的操作封装在类中,保证数据的安全性 继承性:通过继承可以实现代码复用,减少冗余代码量 多态性:通过重载、重写等方式可以实现同名函数的不同功能,
2.面向对象软件测试层次
单元测试-详细设计:针对单个类或方法进行测试的过程,以保证它们的功能正确。
集成测试-概要设计:针对不同类之间的交互进行测试的过程。在集成测试中,会将单元测试通过的类组合起来进行测试,以确保它们在整个系统中的协作和交互没有问题。
系统测试-需求规格说明:对整个软件系统进行测试的过程,确保其符合用户需求,并且能够正常地运行。
3.Date.increment的单元测试
用等价类测试方法,定义三个等价类:
D1={日期: 1<=日期<月的最后日期}
D2={日期: 日期是非12月的最后日期}
D3={日期: 日期是12月31日}
4.以类为单元的测试
5.面向对象的集成测试
6.基于协作图的成对集成测试
7.面向对象软件的MM-路径 面向对象软件的MM-路径和传统软件的MM-路径很相似,都是通过路径描述模块之间的调用关系。但是,在面向对象软件中,使用“消息”来表示对象之间的通信,而不是函数或过程的调用。因此,MM-路径被定义为一系列被消息隔开的方法执行序列。这样可以更好地表达对象之间的交互关系和依赖关系。
与传统软件一样,一个方法也可能有多条内部执行路径,即相同的方法可以由不同的输入执行出不同的结果。这种情况下,可以根据输入参数、状态等条件将方法执行路径划分成多个子路径。
MM-路径从某个方法开始,当到达某个自己不发送任何消息的方法时结束,这就是所谓的消息静止点。这意味着在整个MM-路径中,只考虑对象之间的消息传递,不考虑对象内部的方法调用。同时,MM-路径还需要满足一些其他的要求,比如完整性、可达性、有效性等。这些要求可以帮助测试人员找到系统中潜在的缺陷和错误,并尽早修复它们,从而提高软件的质量和可靠性。
8.顺序图几乎等价于MM路径
9.原子系统功能(ASF)? 面向对象软件中的MM-路径是由消息连接起来的方法执行序列. 原子系统功能(ASF)是一种MM-路径,ASF从输入端口事件开始,经过一系列对象之间的消息传递和方法执行,最终到达输出端口事件。
10.练习:请写出次日问题中输入是“2010-12-31”的MM路径
11.练习:在货币转换程序中线索<s1,s7>、<s2,s6,s8>
代表什么意思,对它们的测试是否有意义,为什么?
Part-11用户界面测试GUI测试
Part-12测试管理
1.动态测试的过程 编码(单元测试)——设计(集成测试)——规格定义(系统测试)——用户需求(验收测试)
2.单元测试 静态测试+百盒测试
3.集成测试 黑盒测试
4.系统测试 黑盒测试
5.验收测试 黑盒测试
6.回归测试 黑盒测试+百盒测试
7.缺陷跟踪 缺陷跟踪系统
8.不是所有缺陷都会修改 时间原因 产品说明书更改 测试员错误理解造成的缺陷 修改风险太大 修改性价比太低 缺陷报告不够有效
Part-13测试驱动开发
1.测试驱动开发的基本概念: 测试驱动开发(TDD,Test Driven Development)是一种软件开发方法论,其基本思想是在编写代码之前先编写测试用例,然后通过不断的测试与重构来达到代码质量的提高和功能的完善。TDD的核心是测试,它强调在代码实现之前先编写测试用例,然后根据测试用例来编写代码,最后再进行测试和重构。
2.测试驱动的基本流程: 测试驱动开发的基本流程包括以下三个步骤: (1)编写测试用例:根据需求和功能编写测试用例。 (2)编写代码:根据测试用例编写代码。 (3)运行测试:运行测试用例,检查代码是否符合要求。
3.测试驱动的所采用的技术及工具: 测试驱动开发所采用的技术和工具包括: (1)单元测试框架:如JUnit、TestNG等。 (2)Mock框架:如Mockito、EasyMock等。 (3)持续集成工具:如Jenkins、Travis CI等。 (4)自动化构建工具:如Maven、Gradle等。
4.对NextData的测试驱动开发: NextData可以采用测试驱动开发来提高代码质量和开发效率。具体实现步骤为:先编写测试用例,然后编写代码,最后运行测试用例进行验证。在测试驱动过程中,可以使用JUnit等单元测试框架和Mockito等Mock框架来进行测试和模拟。
5.自动化测试执行(测试框架): 自动化测试执行是指通过编写测试脚本来自动执行测试用例,以减少手动测试的工作量和提高测试效率。常用的自动化测试框架包括Selenium、App、Robot Framework等。
6.Junit框架示例: 下面是一个简单的JUnit测试用例示例:
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class MyTest {
@Test
public void testAdd() {
int num1 = 5;
int num2 = 7;
int result = num1 + num2;
assertEquals(12, result);
}
}
7.测试驱动开发的优缺点: 测试驱动开发的优点包括: (1)提高代码质量:通过编写测试用例,可以更加全面地测试代码,减少代码中的缺陷。 (2)提高开发效率:测试驱动开发可以帮助开发人员更快地定位和解决问题提高开发效率。 (3)提高代码可维护性:测试驱动开发可以促使开发人员编写更加可维护的代码。 (4)提高代码设计:测试驱动开发可以促使开发人员在编写代码之前先考虑代码的设计。
测试驱动开发的缺点包括: (1)需要学习新的方法:测试驱动开发需要开发人员学习新的方法和工具。 (2)增加开发时间:测试驱动开发需要编写测试用例和进行测试,因此可能会增加开发时间。 (3)测试用例的维护:测试用例需要随着代码的更新而进行维护,可能会增加开发人员的工作量。
8.模型驱动开发与测试驱动开发对比: 模型驱动开发(MDD,Model Driven Development)和测试驱动开发(TDD,Test Driven Development)都是一种软件开发方法论,但它们的重点不同。MDD的重点是通过模型来驱动代码的生成,而TDD的重点是通过测试来驱动代码的编写。MDD更加注重模型的设计和生成,而TDD更加注重代码的测试和重构。 模型驱动开发依赖于建模技术,测试驱动开发依赖于测试技术。
Part-14 单选题
1.在黑盒测试中,着重检查输入条件组合的方法是(因果图法) 2.单元测试主要从下面五个基本特征进行测试,分别是:模块接口、局部数据结构、独立路径和出错处理 3.版本管理是对系统不同版本进行的(标识与跟踪)过程 4.对软件是否能达到用户所期望的要求的测试称为(验收测试) 5.在进行软件测试时,首先应当进行(单元测试),然后再进行组装测试,最后再进行有效性测试。 6.从下列叙述中选出能够与软件开发需求分析、设计、编码相对应的软件测试(确认测试、组装测试、单元测试) 8.易用性测试包括的内容(安装测试,菜单测试,界面测试) 9.在进行单元测试时,常用的方法是(采用白盒测试,辅之以黑盒测试) 10.根据软件需求规格说明书,在开发环境下对已经集成的软件系统进行的测试是(系统测试) 11.软件质量保证活动的目标为:制定和规划软件质量保证的任务,客观地验证软件产品和各项任务是否遵循适用的标准、规程和需求,相关小组和个人保持良好的沟通,及时通知他们在软件质量保证方面的认识和结果,高层管理人员能够参与并帮助解决项目中不能解决的不相容问题。而选项B(用最少的时间和人力,找出软件中潜在的各种错误和缺陷)应为软件测试的目标,两者要区分开来。 12.回归测试的目的是:(确保修正过程中没有引入新的缺陷) 13.关于软件质量保证和软件测试的描述:软件质量保证和软件测试是软件质量工程的两个不同层面的工作。在软件质量保证的活动中也有一些测试活动。软件测试是保证软件质量的一个重要环节。 14.软件测试的对象包括(源程序、目标程序、数据及相关文档) 15.瀑布模型:瀑布模型适用于软件需求确定,开发过程能够釆用线性方式完成的项目, 16.软件质量的定义是( 软件特性的总和,以及满足规定和潜在用户需求的能力) 17.软件测试对软件质量的意义(度量与评估软件的质量,改进软件开发过程,发现软件错误。) 18.① 黑盒测试与软件具体实现无关,所以如果软件实现发生了变化,测试用例仍然可以使用; ② 设计黑盒测试用例可以和软件实现同时进行,因此可以压缩项目总的开发时间。主要应用于集成测试、确认测试、系统测试、验收测试 19.系统测试关注的是(项目或产品范围中定义的整个系统或产品的行为) 20.设计功能测试用例的根本依据是(用户需求规格说明书) 21.界面元素测试包括:窗口测试、菜单测试、图标测试、文字测试、鼠标测试。 22.回归测试是对已被测过的程序实体在修改缺陷或变更后进行的重复测试,以此来确认在这些变更后是否有新的缺陷引入系统 23.静态测试和动态测试的区别描述正确的是( 静态测试并没有真正的运行软件,而动态测试需要运行软件) 24.下面那个属于静态分析(编码规则的检查,程序结构分析,程序复杂度分析) 25.动态测试用例规格说明的内容包括(①前置条件②输入数据③预期结果 ) 26.边界值分析法进行健壮性测试,需要对程序的每个输入变量选取( 略小于最小值、最小值、略大于最小值、正常值、略小于最大值、最大值,略大于最大值)来设计测试用例。 27.某程序输入X为整数类型变量,1<=X<=10,如果用边界值分析法设计测试用例,则X应该取( 0, 1, 10, 11)边界值。 28.某程序的一个输入变量的取值范围是正整数,那么这个变量的有效边界值的数是(0) 29.基本的测试过程主要由下面哪些活动组成:①计划和控制(control)②分析和设计③实现和执行④评估出口准则和测试报告⑤测试结束活动 30.在规格说明不完全的情况,最适合采用的测试技术是(基于经验的测试技术) 31.软件的六大质量特性包括(功能性、可靠性、可用性、效率、可维护、可移植0 32.黑盒测试技术包括:边界值分析、因果图、等价类划分、状态转换 33.DD路径和MM路径的区别:DD路径是模块内程序执行路径。MM路径是模块间执行路径序列。V(G)= e-n+2p 34.线索有不同的层次:单元级线索——指令执行路径或者DD-路径。继承测试线索是MM-路径,即模块执行和消息交替序列。系统级线索是院子系统功能序列。 单元测试的线索是模块内的路径的执行序列。集成测试的线索是模块间的路径执行序列。系统级的线索是系统输入到输出的路径。 35.基于用例的线索测试(Use-case-based testing)、基于事件的线索测试(Event-based testing)、基于端口的线索测试(Port-based testing)和基于数据的线索测试(Data-based testing)是软件测试方法的四种类型。下面我们将分别介绍它们的概念,如何进行测试,以及举一个例子并进行分析。 36.线索测试
基于用例的线索测试(Use-case-based testing) 概念:基于用例的线索测试是一种以用户使用场景为基础的测试方法,通过分析用户需求和使用场景,设计出具有代表性的测试用例。
如何做:确定软件的功能需求,分析用户使用场景,编写用例,设计测试数据和预期结果,执行测试并记录实际结果,对比预期结果和实际结果。
例题:一个简易计算器软件,测试用例可以是“两个数相加”
例题分析:在这个例子中,我们可以通过以下步骤进行测试:
分析用户需求:用户需要进行加法运算 设计测试用例:输入两个数值,执行加法操作 设计测试数据和预期结果:例如,输入1和2,预期结果是3 执行测试并记录实际结果 对比预期结果和实际结果
基于事件的线索测试(Event-based testing) 概念:基于事件的线索测试是一种以用户触发的事件为基础的测试方法,通过模拟用户操作来检查软件在特定事件触发下的响应。
如何做:确定软件中的事件,设计测试用例模拟事件触发,执行测试并验证软件在事件触发时的响应是否符合预期。
例题:一个在线购物网站,测试用例可以是“用户点击购物车图标”
例题分析:在这个例子中,我们可以通过以下步骤进行测试:
分析用户事件:用户点击购物车图标 设计测试用例:模拟用户点击购物车图标 执行测试并验证软件响应:购物车页面正确显示,包括购物车内的商品列表等信息
基于端口的线索测试(Port-based testing) 概念:基于端口的线索测试是针对软件的输入输出端口进行测试的方法,主要验证软件接口和与外部系统的交互是否正确。
如何做:分析软件的输入输出端口,设计测试用例针对端口进行测试,验证软件与外部系统的交互是否符合预期。
例题:一个天气查询应用,测试用例可以是“从天气数据提供商获取数据”
例题分析:在这个例子中,我们可以通过以下步骤进行测试:
分析软件端口:应用从天气数据提供商获取数据的接口 设计测试用例:模拟应用请求天气数据 执行测试并验证软件与外部系统交互:确保应用能正确解析并显示从天气数据提供商获取的数据
端口的输入事件考虑:
Pl1:每个端口输入事件发生。
Pl2:端口输入事件的常见序列发生。
Pl3:每个端口输入事件在所有相关数据语境中发生。
Pl4:对于给定语境,所有不合适的输入事件发生。
Pl5:对于给定语句,所有可能的输入事件发生。
端口的输出事件考虑:
PO1:每个端口输出事件发生。
PO2:每个端口输出事件在每种情况下发生。
基于数据的线索测试(Data-based testing) 概念:基于数据的线索测试是一种以软件处理数据为基础的测试方法,主要关注软件在不同数据输入下的表现。
如何做:确定软件处理的数据类型,设计具有不同数据特点的测试数据,执行测试并验证软件在处理这些数据时的表现是否符合预期。
例题:一个文本编辑器软件,测试用例可以是“打开不同编码格式的文本文件”
例题分析:在这个例子中,我们可以通过以下步骤进行测试:
分析软件处理的数据类型:文本文件的编码格式(如UTF-8、GBK等) 设计测试数据:准备具有不同编码格式的文本文件。 执行测试并验证软件表现:确保文本编辑器能正确识别和显示不同编码格式的文本文件内容
1 a=5;
2 While(C1) {
3 if (C2){
4 b=a*a;
5 a=a-1;
6 }
7 print(a); }
1-5
4-5-7