8.1 Software Faults and Failures
1. 软件产生缺陷的原因
①需求错误(不是客户想要的)、需求缺失、需求不可实现
②错误的设计、错误的代码
③设计正确但是设计实现不正确
…
编码啊测试啊都会出现… # 待补充
错误的需求:不是客户想要的
缺少需求
需求无法实施
设计有缺陷
代码有缺陷
设计实施不当
软件测试 Software Testing
运行软件或模拟软件的执行,发现软件缺陷的过程
注意点
- 软件测试通过运行程序代码的方式来发现程序代码中潜藏的缺陷,这和代码走查、静态分析形成鲜明对比。
- 软件测试的目的是为了发现软件中的缺陷。它只负责发现缺陷,不负责修复和纠正缺陷
在程序代码中找出软件缺陷
程序是运行软件的载体
通过执行代码运行软件
通过软件运行发现缺陷
程序是软件缺陷的载体
缺陷分布在模型、文档和代码中
最终会反映在程序代码上
软件测试的原理
程序本质上是对数据的处理
设计数据(测试用例) → 运行测试用例(程序来处理数据) → 判断运行结果(是否符合预期结果)
测试用例
为软件测试而设计的数据称为测试用例(Test Case)
测试用例是一个四元偶
- 输入数据:交由待测试程序代码进行处理的数据
- 前置条件:程序处理输入数据的运行上下文,即要满足前置条件
- 测试步骤:程序代码对输入数据的处理可能涉及到一系列的步骤,其中的某些步骤需要用户的进一步输入
- 预期输出:程序代码的预期输出结果
软件测试的任务
软件测试的目的
目的
发现软件中的缺陷
最大限度、尽可能多的找到缺陷
功效
发现的缺陷越多
软件中遗留的缺陷越少
交付的软件质量越高
后期维护工作量就越少
只有找到错误才是一个成功的测试
Faults的类型
2. 主要的缺陷类型
①算法缺陷:由于处理步骤的某些错误,使得对于给定的输入构件的算法或逻辑没有产生适当的输出
②计算和精度缺陷:公式的实现是错误的,或者计算的结果没有达到要求的精度
③文档缺陷:文档与实际做的事情不一致
④压力或过载缺陷:填充数据结构时超出规定的能力
⑤能力或边界缺陷:系统活动达到指定的极限时,系统性能变得不可接受
⑥计时或协调故障:多线程执行,进程间的协调问题
⑦性能故障:系统不能以规定的速度执行
⑧硬件和系统软件缺陷:提供的硬件和软件并没有按照文档中的操作条件和步骤运作
⑨标准和过程缺陷:代码不符合标准
主要的缺陷类型(10种):
- 算法缺陷:算法某些处理步骤或逻辑有问题,导致软件的部件对于输入数据不能给出正确的输出;
- 计算和精度缺陷:算法或公式在编程实现时逻辑没错,但是计算过程出现了错误或者精度达不到要求,从而无法获取正确输出;
- 过载缺陷(压力缺陷):程序运行时**,数据填充量会超过数据结构的规定容量**引起的缺陷;
- 能力缺陷(边界缺陷):系统活动量达到系统极限时,系统性能变的不可接受,称为能力缺陷;
- 性能缺陷(吞吐量缺陷):系统在常规状态下就不能以需求规定的速度执行;
- 时序性缺陷(协调缺陷):几个同时或有严格执行顺序的进程协调出现问题;
- 文档缺陷:文档描述与程序实际行为不符;
- 恢复性缺陷:系统失效时,程序无法再恢复也是一种缺陷;
- 硬件和系统软件缺陷:作为底层支持的硬件和系统软件没有按照文档中的操作条件和步骤运作时,也可引起软件的问题;
- 标准和规格缺陷:代码没有遵守组织机构的标准和过程。这个缺陷最大的影响在于:不按照标准的代码可能在测试和修改时让人不好理解,引起问题。
正交缺陷分类:使任意一个缺陷只属于一个类别的缺陷分类方案称为正交缺陷分类。
如果故障属于不止一个类,则失去了度量的意义。
8.2 Testing Issues
测试过程
3. 测试的各个阶段和任务
测试的各个阶段如上图所示,具体包括:
- 单元测试:验证组件的功能。依据文档:程序代码与配套文档。
- 集成测试:验证系统组件是否能正确的协同工作。依据文档:系统体系结构文档SAD、程序设计规格说明。
- 功能测试:验证系统是否能执行需求规格说明中描述的功能。依据文档:软件需求规格说明书SRS。
- 性能测试:验证系统的软硬件表现和性能是否符合需求规格说明文档。这一步之后,软件系统应当能在客户的实际工作环境中成功执行,这时我们说产生了一个被确认的系统。依据文档:软件需求规格说明书SRS。
- 验收测试:验证系统是否满足了客户的需求定义(需求定义和需求规格说明是有区别的)。依据文档:客户需求定义。
- 安装测试:验证系统能否在用户使用的真实环境中安装并正常运行。依据文档:用户环境的说明。
系统测试:功能测试、性能测试、验收测试和安装测试统称为系统测试。
4. 测试的态度
为什么需要独立的测试团队?
新程序员不习惯将测试看做是一个发现的过程,可能仅仅将程序视作问题的解决方案,为没有考虑问题本身。但是客户对系统的在某些条件下能够运行并不感兴趣,相反,他们感兴趣的是确保系统在所有条件下都能适当运行。所以,作为一个开发人员,无论故障出现在系统的何处,也无论是谁引起这些故障,你的目标应该是尽可能多地去除故障。
为了从测试过程中排除个人情感,通常是用一个独立的测试小 组来测试系统,这样就避免了故障的个人责任与可能多地发现故障的需要之间的冲突。
5.【必考!】 测试方法:黑盒测试和白盒测试
黑盒测试:从外部观察测试对象,将其看作是一个不了解其内容的黑盒,向黑盒提供输入数据并记录产生的输出,基于程序功能和性能
- 优点:不受测试对象内部结构合逻辑的约束
- 缺点:测试是非完备的
白盒测试:根据测试对象的内部结构,用不同的方式来测试,或者说是基于程序的内部结构来设计测试用例
- 优点:覆盖面广、完备
- 缺点:工作量大,无法测试遗漏路径
黑盒测试:人员在完全不了解程序内部的逻辑结构和内部特性的情况下,只依据程序的需求规格及设计说明,检查程序的功能是否符合它的功能说明。其原则是依据系统需求文档、系统设计文档、程序设计文档进行测试,正确的结果是系统完成了所有该做的,拒绝了一切不该做的。
- 优点:测试人员不受程序所带来的束缚,测试更具有客观性。
- 缺点:有时会无法进行完备的测试,在不知道程序内部逻辑的情况下,设计测试时就可能无法面面俱到。
白盒测试:人员拥有全套文档,以程序内部结构为基本依据,手动或自动进行测试。
- 优点:有助于进行更细致、切中要害的测试。
- 缺点:全路径、极度细致的测试不现实。
黑盒测试的分类方法包括如下四种:
- 等价分类法:输入域划分为若干等价类,并且从每个等价类里选择有代表性的少量用例代表其余所有情况。其根本逻辑在于:如果这些代表性用例没有出现问题,那么其他的一般也没有问题。
- 边界值分析法:在等价分类法的基础上,把测试值选在等价类的边界上,经验告诉我们这往往有更好的效果。
- 错误猜测法:根据测试人员的经验,猜测程序中哪些地方容易出错,并补充出用例;此方法适合作为其他方法的补充。
- 因果图法:适用于被测试程序有很多输入条件,程序的输出又依赖输入条件的各种组合的情况。
等价分类法中,等价类可以分为有效等价类和无效等价类两种,前者是正常输入,后者是不应当输出正确结果的无效输入。在划分等价类时,需要尽可能“密铺”式划分,并且尽可能不对测试的实体整体添加限制条件以提升可扩展性。
对有效等价类的用例,尽量用一个用例覆盖尽可能多的等价类,这是因为任意一个有效等价类的处理出现问题都会产生故障,被我们发现,我们可以以此减少测试次数;对无效等价类,必须为每一个无效等价类都设计一个专内验证该点的用例,这是因为所有无效等价类的表现都是不正常返回,不进行共用以避免多个错误一起发生导致漏过一些错误。用例可以进一步区分为如下三种:
- 弱一般等价类:测试每个一般等价类都至少出现在用例中一次即可。
基于单缺陷假设:失效很少因为两个或更多缺陷同时共同引发。
- 弱健壮等价类:考虑有效等价类之外,划分出的无效等价类,并且每个等价类在用例中至少出现一次即可;仍基于单缺陷假设。
- 强一般等价类:测试用例应当遍历等价类的所有笛卡尔积组合;基于多缺陷假设。
白盒测试的方法包括两种:
- 逻辑覆盖法。
- 路经测试法。
逻辑覆盖法是一组逻辑覆盖方法的统称,按照程序逻辑覆盖程度分为:
- 语句覆盖:每条语句至少执行一次。
- 判定覆盖(分支覆盖):每一分支至少执行一次,又称分支覆盖。
- 条件覆盖:每个条件均按“真”和“假”两种结果至少执行一次。
- 条件组合覆盖:某个分支的虽然只有一种结果,但可能由多个条件组合而成。条件覆盖只要求单个条件一次真一次假即可,条件组合覆盖要求覆盖所有组合,即使有些组合最终结果一样。
满足条件覆盖不一定满足分支覆盖,例如a && b,当用例包括a=false, b=true和a=true, b=false时就满足条件覆盖,但显然不满足分支覆盖。
路经测试法借助程序图设计测试用例,包括四种:
- 结点覆盖:经过所有结点,相当于逻辑覆盖中的语句覆盖。
- 边覆盖:覆盖所有边,相当于逻辑覆盖中的判定覆盖。
- 完全覆盖:同时满足结点覆盖和边覆盖,也即走过所有位置,这是测试简单程序的最低标准。
- 路径覆盖:程序图中每条路径都至少经过一次。
路经覆盖法与穷举测试有所不同,路径覆盖法并不关注循环次数,某个循环语句循环1次和n次对于路径覆盖法是一样的,但是穷举测试则认为它们是不同的。
软件测试技术——白盒测试技术
基于程序内部的执行流程来设计测试用例
设计测试用例思想
根据程序单元内部工作流程来设计测试用例
发现程序单元缺陷
运行待测试的程序,检验程序是否按内部工作流程来运行的,如果不是则
存在缺陷
特点
必须了解程序的内部工作流程才能设计测试用例
以下步骤也要学会
步骤一:根据程序逻辑画出流程图
步骤二:将流程图转换为流图
流图:刻画程序控制结构但不涉及程序过程性细节
步骤三:确定基本路径集合
步骤四:针对测试路径设计测试用例
步骤五:运行程序检验测试用例
运行待测试的程序代码
逐个输入测试用例
分析程序的运行路径
如果运行路径与期望路径不一样,则存在缺陷
软件测试技术——黑盒测试技术
基于程序的外在功能和接口来设计测试用例
思想
根据已知的程序功能和性能(而非内部细节),设计测试用例并通过测试检验程序的每个功能和性能是否正常
依据
程序的功能和性能描述
特点
知道程序功能和性能,不必了解程序内部结构和处理细节
黑盒测试发现的错误类型
测试软件系统是否满足功能要求:
- 不正确或遗漏的功能
- 界面错误
- 数据结构或外部数据库访问错误
- 性能错误
- 初始化和终止条件错误
黑盒测试的特点
黑盒测试与软件如何实现无关,如果软件实现发生变化,测试用例仍然可以使用
黑盒测试用例的开发可以与软件实现并行进行,能够缩短软件开发周期
等价分类法!!
黑盒测试——等价分类法
输入条件为一范围
划分出三个等价类:
(1) 有效等价类(在范围内),(2) 大于输入最大值,(3)小于输入最少值
输入条件为一值
划分为三个等价类
(1) 有效,(2) 大于,(3) 小于
输入条件为集合
划分二个等价类
(1) 有效(在集合内),(2) 无效(在集合外)
输入条件为一个布尔量
划分二个等价类
(1) 有效(此布尔量),(2)无效(布尔量的非
边界值分析法!!
黑盒测试——边界值分析法
输入条件是一范围(a,b)
a,b以及紧挨a,b左右的值应作为测试用例
输入条件为一组数
选择这组数最大者和最小者,次大和次小者作为测试用例
如果程序的内部数据结构是有界的
应设计测试用例使它能够检查该数据结构的边界
要会设计设计用例 啥多少个输出
8.3 Unit Testing 单元测试
6.单元测试
发现构件中的故障
①通过程序对代码审查
②编译代码、排除语法错误
③开发测试用例
测试用例的概念:以测试程序为目的而挑选的输入数据,包含对应的期望结果 测试用例是一个四元偶(包含输入条件、前置条件、测试步骤、预期数据)
测试用例这么写就行
8.4 Integration Testing 集成测试
7.集成测试及主要方法的分类
①将构建组合在一起进行测试,使得发生失效时,能够对导致引起失效的原因有所了解
②方法分类:自底向上、自顶向下、一次性集成、三明治集成 # 有图
分类:
1、自底向上集成
含义:使用这种测试方法的时候,每一个处于系统层次中最底层的构件先被单独测试,接着测试的是那些调用了前面已测试构件的构件。反复采用这种方法,直到所有的构件测试完毕。
先测试系统最底层的模块,接着测试调用这些底层模块的模块,直到测试完毕。
2、自顶向下集成
含义:顶层构件通常是一个控制构件,是独立进行测试的。然后将被测构件调用的所有构件组合起来,作为一个更大的单元进行测试。重复这样的操作直到所有的构件都被测试。
先测试系统最上层的模块,接着测试顶层模块调用的下层模块,直到测试完毕。
3、一次性集成
先测试每一个模块,之后将所有模块一并集成。
先测试每一个构件,然后将所有的构件一次性的集成。只适用于小型系统。
4、三明治集成
将系统分成三层,目标层处于中间、目标层上有一层,目标层下有一层。在顶层采用自顶向下的方式集成,在较低层采用自底向上的方式集成,测试集中于目标层。
8.传统测试方法跟OO测试的区别
在需求分析和验证阶段
测试用例生成
源代码分析
覆盖分析
(1) 测试用例的充分性:对过程语言而言,系统改变时,我们可以针对改变测试是否正确,并使用原有测试用例验证剩余功能是否同原来一致。但是面向对象测试中,我们可能需要编写不同的测试用例
(2) 面向对象趋于小粒度,并且平常存在于构建内的复杂性常常转移到构件之间的接口上,这意味着,其单元测试比较容易,但是集成测试涉及面更加广泛
(3) 传统测试和面向对象测试主要集中在:需求分析和验证、测试用例生产、源码分析和覆盖分析
9.构建驱动component driver
a runtine that calls a particalar component and passes a test case to it.
一种特殊类型的软件组件,用于调用正在被测试的组件,并为其提供假设的输入数据,以检查其正确性
集成测试及其主要方法的分类?(驱动模块、桩模块的概念)
构件驱动程序:在测试最底层的构件时,因为没有现成的已测试的构件调用底层的待测试构件,所以我们需要编写特定的代码来辅助集成。构件驱动程序就是调用特定构件并向其传递测试用例的程序,即代替上级模块传递测试用例的程序。
桩(stub):一种专用程序,用于模拟测试时缺少构件时的活动。桩应答调用序列,并传回输出数据,使测试能够正常的进行下去,即代替下级模块的仿真程序。
正式技术评审 formal technical review
不可能避免软件存在问题,只能尽可能少的去减少bug