第十四章-软件测试策略
(1)什么是软件测试
测试是执行程序的过程,目的是在交付给最终用户之前找到错误。目的是为了发现软件设计和实现过
程中因疏忽所造成的错误。
(2)验证与确认V&V
(verification and validation)
验证是指确保软件正确的实现某一特定功能的一系列活动。(是否可以正确实现需求)
确认指的是确保开发的软件可追溯到客户需求的另外一系列活动。(是否是按照客户需求开发的)
(3)软件测试组织
开发者:理解系统,但是将会“温和的测试”,是交付驱动式的;以开发者来看,测试是破坏性的;开发者精心地设计和执行测试,试图证明其程序的正确性,而不是注意发现错误。
独立的测试人员:必须了解系统,但是会尝试打破它,是质量驱动式的;为了避免开发人员进行测试所引发的固有问题。独立测试可以消除利益冲突。
(4)软件测试策略-宏观
我们开始于“小范围测试”并且移向“大范围测试”
对于传统的软件:开始集中在模块(构件),之后进行模块集成
对于面向对象的软件:当进行“小范围测试”时,我们的关注点从单个模块(传统意义上的)转变到面向对象的类,类封装了属性和操作,并意味着通信和协作。
策略问题
- 在测试开始之前的很长时间就要以可计量的方式确定产品的需求。
- 明确地阐明测试的目标。
- 了解软件的用户,并给出每一类用户的概况描述。制定测试计划,强调“快速周期测试”。
- 构造“健壮的”软件,设计能对其自身进行测试的软件。
- 使用有效的技术评审作为测试之前的过滤器。
- 进行技术评审对测试策略和测试用例本身进行评估。
- 对测试过程开发可持续的改进方法。
(5)传统测试策略
1)单元测试
l什么是单元测试
测试模块的接口视为了保证被测程序单元的信息能够正常的流入和流出;
检查局部数据结构以确保临时存储的数据在算法的整个执行过程中能维持其完整性;
执行控制结构中的所有独立路径(基本路径)以确保模块中的所有语句至少执行一次;
测试边界条件确保模块在到达边界值的极限或受限处理的情形下仍能正确运行;
对所有的错误处理路径进行测试。
由于构件并不是独立的程序,因此必须为每个测试单元开发驱动程序和桩程序。驱动程序只是一个“主程序”,它接受测试用例数据,将这些数据传递给构件(要进行测试的),并打印结果。桩程序的作用是替换那些从属于被测构件(或被其调用的)模块。使用从属模块的接口,可能做少量的数据操作,提供入口的验证,并将控制返回到被测模块。
单元测试问题
Q: 为什么要进行单元测试?
A: 单元测试有以下几个重要的理由:
确保代码的正确性:通过针对每个单元进行测试,可以提前发现和纠正潜在的错误和缺陷。
提高代码质量:良好的单元测试可以促使开发人员编写更结构化、模块化、可测试和易于维护的代码。
支持重构和修改:单元测试可以帮助开发人员在修改或重构代码时确保不会引入新的问题或破坏原有功能。
加速开发流程:通过快速执行和验证单元测试,可以及早捕获问题并减少调试时间,从而提高开发效率。
Q: 单元测试应该覆盖哪些方面?
A: 单元测试应该尽可能全面地覆盖以下方面:
正常情况下的功能:测试函数或方法按照预期输出正确的结果。
边界条件和特殊情况:测试函数或方法在边界条件和各种异常情况下的行为是否正确。
错误处理:测试函数或方法是否能正确地处理错误输入和异常情况,避免崩溃或不恰当的行为。
辅助功能:测试函数或方法的辅助功能(如日志记录、缓存访问等)是否按预期工作。
单元测试过程
确定测试范围:选择需要进行单元测试的代码模块或函数。
编写测试用例:根据功能和需求编写针对每个功能点的测试用例,包括输入数据、预期输出以及其他必要的条件。
准备测试环境:设置好测试环境,包括所需的测试工具、测试框架和模拟器等。
执行单元测试:运行编写好的测试用例,传入参数并触发被测代码的执行。
检查结果:比对实际输出与预期输出是否一致,检查代码的行为是否符合设计要求。
处理问题与修复缺陷:如果单元测试发现了问题或缺陷,将问题报告给开发人员并跟踪修复过程。
重复执行:对修改后的代码再次执行单元测试,确保问题已被解决且没有引入新的问题。
整理文档:记录测试过程、测试结果和修复情况,并生成相应的文档。
2)集成测试
自顶向下
从主模块开始,沿着控制层逐步向下,以深度优先或者广度优先的方法将从属于主控制模块的模块集成到结构中去。
自顶向上
从原子模块开始进行构建和测试;
三明治模式
回归测试
- 回归测试是重新运行已经进行过的测试子集,以确保变更没有引发非预期的副作用。
- 每次对软件进行修改时,就改变了软件配置的某些方面(软件、文档及支持软件的数据)。
- 回归测试有助于确保变更(由于测试或者其他原因)不会引入非预期的行为或者增加的错误。
- 回归测试可以手动进行,通过重新运行一部分测试用例或者全部测试用例,也可以使用自动的捕获/回放工具。
冒烟测试
是对产品软件进行“每日构造”的一种常见方法。冒烟测试步骤:
- 已经被翻译为代码的软件构件被集成到构造(“build”)中。
- 一个构造包括所有的数据文件、库、可重用的模块、以及工程化的构件,其中一个构件需要实现一项或多项产品功能。
- 设计一系列测试来揭示错误,使得此构造不能正确地执行其功能。
目的是揭示“显示阻塞”错误,这种错误最有可能使软件项目滞后于进度计划。
将此构造与其他构造集成在一起,每天都对整个产品(以其当前的形式)进行冒烟测试。
集成方法可以是自顶向下,也可以是自底向上。
3)确认测试
l确认测试目标
确认测试:重点是软件需求。
lAlpha/Beta测试
Alpha/Beta 测试:重点是客户使用。
4)系统测试
系统测试:重点是系统集成。
- 恢复测试
恢复测试:以各种方式迫使软件失效,并验证恢复能够被正确执行。
- 安全测试
安全性测试:verifies验证内置到系统中的保护机制实际上能够保护系统免于不当的渗透。
- 压力测试
压力测试: 以一种要求资源的异常数量、频率或容量的方式运行系统。
- 性能测试
性能测试:在集成的系统中测试系统的运行时性能。
(6)调试:诊断过程
调试过程
调试工作量
调试与测试的关系
调试策略
- 蛮干法/测试
- 回溯法
- 归纳法
- 演绎法
第十五章-测试传统的应用软件
1.可测试性(理解)
- 可操作性—操作起来干净利索
- 可观察性—每个测试用例的结果都容易观察到
- 可控制性—测试能够被自动执行和优化的程度
- 可分解性—测试可以有针对性
- 简单性—减少复杂的体系结构和逻辑以简化测试
- 稳定性—在测试期间要求的变更很少
- 易理解性—设计易于理解
2.什么是好的测试
- 好的测试具有较高的发现错误的可能性
- 好的测试是不冗余的
- 好的测试应该是“最佳品种”
- 好的测试应该既不太简单也不太复杂
3.测试的内部和外部视角
任何工程化的产品(以及大多数其他东西)都可以采用以下两种方式之一进行测试:
- 了解已设计的产品要完成的指定功能,可以执行测试,以显示每个功能是可操作的,同时,查找在每个功能中的错误;
- 了解产品的内部工作情况,可以执行测试以确保“所有的齿轮吻合”———即内部操作依据规格说明执行,而且对所有的内部构件已进行了充分测试。
内部视角也叫白盒测试﹔外部视角也称为黑盒测试
白盒测试和黑盒测试的区别和理解
黑盒测试暗指在软件接口处执行测试。黑盒测试检查系统的功能方面,而不考虑软件的内部结构。白盒测试是基于过程细节的封闭检查;通过提供检查特定条件集或循环的测试用例,测试将贯穿软件的逻辑路径和构件间的协作。
4.白盒测试
要求:给定特定的例子,知道如何测试
基本路径测试
总结:
- 以设计或者代码作为基础,画出对应的流图
- 确定结果流图的环路复杂性。
- 确定线性独立路径的基本集合。
- 准备测试用例,使得基本集合中的每条路径都执行。
循环测试
最小条件—简单循环
1.跳过整个循环; 2.只有一次通过循环; 3.两次通过循环; 4.m次通过循环,其中m<n; 5. n—1,n,n+1次通过循环。
其中, n是允许通过循环的最大次数。
嵌套循环
(1)从最内层循环开始,将其他循环设置为最小值;
(2)对最内层循环执行简单循环测试,而使外层循环的迭代参数(例如循环计数)值最小,并对范围以外或不包括在内的值增加其他测试;
(3)由内向外构造下一个循环的测试,但使其他外层循环具有最小值,并使其他嵌套循环为“典型”值;
(4)继续上述过程,直到测试完所有的循环。串接循环
若串接循环的每个循环彼此独立,则可以使用简单循环测试方法。若循环不独立,建议使用嵌套循环的测试方法。
例如,若两个循环串接起来,且第一个循环的循环计数为第二个循环的初始值,则这两个循环并不独立。
5.黑盒测试
- 等价类划分
- 边界值分析
第十六章-测试面向对象的应用
(1)扩展测试的视野(理解)
为了充分测试面向对象的系统,必须做3件事情:
- 1.对测试的定义进行扩展,使其包括应用与面向对象分析和设计模型的错误发现技术
- 2.单元测试和集成测试策略必须彻底改变
- 3.测试用例设计必须考虑面向对象软件的独特性质
“测试”OO模型
- OO分析模型和设计模型的评审非常有用,因为在分析、设计和代码级别上所表现的语义结构(例如,类,属性,操作,消息)是相同的。
- 因此,在类属性定义中的一个问题是如果在分析阶段发现就会规避副作用,否则,如果直到设计或者代码(甚至是下一次分析迭代)才被发现,就会产生副作用。
(2)OO模型的正确性
- 在分析和设计阶段,基于模型与真实世界问题域的一致性,对语义正确性进行评估。
- 如果模型准确地反映了现实世界(在适合于开发阶段的详细程度上,对模型进行评审),则就是语义正确的。
- 实际上,为了确定模型是否反映了真是世界的需求,应该将其介绍给问题领域的专家,由专家检查类定义和层次中遗漏和不清楚的地方。
- 对类关系(实例连接)进行评估,确定其是否准确反映现实世界的对象连接。
(3)OO模型的一致性
- 检查CRC模型和对象-关系模型。
- 检查每一张CRC索引卡片的描述以确定委托责任是定义协作者的一部分。
- 反转连接,确保每个提供服务的协作者都从合理的地方收到请求。
- 使用上面步骤中反转后的连接,确定是否真正需要其他类,或者责任在类之间的组织是否合适。
- 确定是否可以将广泛请求的多个责任组合为一个责任。
(4)OO测试策略(理解)
随机测试
- 标识可应用于类的操作
- 定义其使用限制
- 标识最小的测试序列--定义类(对象)最小生命期的操作序列
- 产生不同的随机(但有效的)测试序列--检查其他(更复杂的)类实例的生命历史。
划分测试
- 与传统软件的等价划分基本相似,划分测试减小测试特定类所需的测试用例数量
- 基于状态划分
根据它们改变类状态的能力对类操作进行分类
- 基于属性划分
根据它们所使用的属性对类操作进行分类
- 基于类别划分
根据每个操作所完成的一般功能对类操作进行分类
第十七章-过程度量与项目度量
1.度量的原因
- 评估一个正在进行中的项目的状态
- 跟踪潜在的风险
- 在问题造成不良影响之前发现它们
- 调整工作流程或任务
- 评估项目团队控制软件工作产品质量的能力
2.过程度量
什么是过程度量
过程度量是软件工程中用于衡量和评估软件开发过程的一种方法。它旨在量化和监控软件开发过程中的各种指标和参数,以便识别问题、改进过程和提高项目管理效能。
过程度量指标:
质量相关--专注于工作产品和应交付产品的质量
生产率相关--花费工作量所完成的工作产品的生产
统计SQA数据--错误归类与分析
缺陷排除效率--错误在过程活动之间的传播
复用数据--所开发的构件的数量及其可复用程度
3.项目度量
- 项目度量目标
- 利用度量能够对开发进度进行必要的调整,以避免延迟,并减少潜在的问题和风险,从而使开发时间减到最短。
- 项目度量可用于在项目进行过程中评估产品质量,必要时可调整技术方法以提高质量。
- 常见项目度量指标
- 输入--对完成工作所需的资源(例如,人员、工具)的测量。
- 输出--对在软件工程过程中创建的可交付成果或工作产品的测量。
- 结果--表示所交付产品有效性的测量
- 度量准则
- 解释度量数据时使用常识,并考虑组织的敏感性。
- 向收集测量和度量的个人及团队定期提供反馈。
- 不要使用度量去评价个人。
- 与开发者和团队一起设定清晰的目标,并确定为达到这些目标需要使用的度量。
- 不要用度量去威胁个人或团队。
- 指出问题区域的度量数据不应该被“消极地”看待,这些数据仅仅是过程改进的指标。
- 不要在某一个度量上纠缠,而无暇顾及其他重要的度量。
4.软件测量(理解)
面向规模的度量(LOC)
每千行代码(KLOC)的错误数
每千行代码(KLOC)的缺陷数
每行代码(LOC)的成本
每千行代码(KLOC)的文档页数
每人月错误数
每评审小时错误数
每人月代码行数每页文档的成本
面向功能点的度量(FP)
每个功能点(FP)的错误数
每个功能点(FP)的缺陷数
每个功能点(FP)的成本
每个功能点的文档页数
每人月功能点
LOC和FP的对比
为什么选择FP?
FP与程序设计语言无关
它所依据的是在软件过程早期就很容易计量的特性
不会“惩罚”那些独出心裁的(简短的)、比其他复杂版本使用更少代码行的实现方法。 更容易测量可复用构件的影响
面向对象的度量
场景脚本(用例)的数量
支持类(实现系统所必需的但又不与问题域直接相关的类)的数量
每个关键类(分析类)的平均支持类数量 子系统(类的集合,这些类实现了一个系统最终用户可见的功能)的数量
5.软件质量的度量(会计算)
- 测量质量
正确性
defects per KLOC
正确性(Correctness )—程序按照规格说明运行的程度
可维护性
MTTC
可维护性(Maintainability)—程序能够被修改的容易程度
完整性
Integrity
完整性(Integrity)—程序抵抗外部攻击的能力
可用性
可用性(Usability)—程序容易使用的程度
缺陷排除效率(DRE)
DRE=E/(E+D)
E是软件交付给最终用户之前发现的错误数
D是软件交付之后发现的缺陷数
第十八章-软件项目估算
(1)项目计划过程
项目策划的总体目标是要建立一个用于控制,跟踪和监控复杂技术项目的实用策略。
为什么?---这样,最终结果才会按时高质量地完成!
项目计划任务集
- 规定项目范围
- 确定可行性
- 分析风险
- 确定所需的资源
- 确定需要的人力资源
- 定义可复用的软件资源
- 识别环境资源
- 估算成本和工作量
- 分解问题
- 使用规模、任务点、过程任务或用例等方法进行两种以上的估算
- 调和这些估算
- 使用规模、任务点、过程任务或用例等方法进行两种以上的估算
- 分解问题
- 指定项目进度计划
- 建立一组有意义的任务集合
- 定义任务网络
- 使用进度计划工具来制定时间表
- 定义进度跟踪机制
- 使用进度计划工具来制定时间表
- 定义任务网络
- 建立一组有意义的任务集合
- 估算成本和工作量
- 识别环境资源
- 定义可复用的软件资源
- 确定需要的人力资源
(2)软件项目估算
- 估算准确性取决因素
预测,基于...
- 计划人员估算待开发产品规模的正确程度
- 将规模估算转换成人员工作量、时间及成本的能力(受可靠软件度量的可用性的影响,这些度量数据来自以往的项目)
- 项目计划反映软件团队能力的程度
- 产品需求的稳定性和支持软件工程工作的环境
- 估算方法(可以正确的估算)
利用对信息域值的估算来计算LOC / FP
使用历史数据进行项目估算
基于LOC的估算
基于FP的估算
基于过程的估算
估算经验模型(COCOMOII)
一般形式:工作量=校正系数*规模^指数
其中:工作量得到的一般是所需的工作量,以人月为单位;校正系数是一个常熟,或者是基于项目复杂度导出的一个值;规模一般是代码行,也可以是功能点;指数由经验得到。
COCOMO II实际上是一种层次结构的估算模型,主要应用于以下领域:
- 应用组装模型。在软件工程的前期阶段使用,这时,用户界面的原型开发、对软件和系统交互的考虑、性能的评估以及技术成熟度的评价是最重要的。
- 早期设计阶段模型。在需求已经稳定并且基本的软件体系结构已经建立时使用。
- 后体系结构阶段模型。在软件的构造过程中使用。
面向OO的估算
使用工作量分解、FP分析和任何其他适用于传统应用的方法进行估算。
使用面向对象需求(第10章)建立用例并确定用例数。由需求模型确定关键类(在第10章中称为分析类)的数量。
对应用系统的界面类型进行归类,以确定支持类的乘数.
(3)项目进度安排
为什么项目会延迟?
- 不切实际的项目最后期限,它是由软件开发小组之外的某个人制定的。
- 客户需求发生变更,而这种变更没有在项目变更进度表上反映出来。
- 对完成工作所需的工作量和(或)资源数量估计不足。
- 在项目开始时,没有考虑到可预测的和(或)不可预测的风险。
- 出现了事先无法预计的技术难题。出现了事先无法预计的人力问题。
- 由于项目成员之间的交流不畅而导致的延期。
- 项目管理者未能发现项目进度拖后,也未能采取措施来解决这一问题。
进度安排原则
- 划分(compartmentalization)—定义不同的任务
- 相互依赖性(interdependency>—明确任务的相互关系
- 工作量确认(effort validation)—确保资源是可用的
- 确定责任(defined responsibilities)—指定负责人
- 定义输出结果(defined outcomes)—每一项任务都必须有输出结果
- 确定里程碑(defined milestones)—质量评审
工作量与交付时间的关系
(4)跟踪进度
- 时序图
- 挣值分析(理解含义,会计算)
挣值:是对项目进展的测量;能够让我们采用定量分析的方法,而不是依赖感觉,来评估一个系那一个项目的“完成百分比”
BCWS指工作任务i的计划工作量
BAC是所有BCWS的总和
BCWP是在项目进度表中该时间点已经实际完成的所有工作任务的BCWS值之和
进度表执行指标,SPI=BCWP/BCWS
进度表偏差,SV=BCWP-BCWS