期末(面向及格复习)

软件测试基本概念

简单了解即可 只考选择题

测试用例

image-20260101225419900

测试报告

image-20260101225539497

软件测试分类

image-20260101230046294

灰盒测试通过一些表征性的现象或事件来反映内部运行状态。灰盒测试使用特定方法和工具来提取应用程序的内部

知识和交互信息,进而使用内部间接信息来设计测试,以提高测试效率(比如利用数据库结构这一内部信息来验证系统的内部状态是否正确)

测试分析框架

image-20260101230912687

image-20260101235656427

BUG理论

PIE模型

Bug在程序的不同阶段,分别称为Fault, Error和Failure,定义如下: ➢ Fault-故障:是指静态存在于程序中的缺陷代码; ➢ Error-错误:是指程序运行缺陷代码后导致错误的程序状态; ➢ Failure-失效:是指程序错误状态传播到外部被感知的现象。

错误不一定会传播到输出!即,中间状态的出错不一定导致程序失效

反向定义及特性

image-20260102000832700

多样性测试

随机测试

简单随机测试

针对输入空间 ,随机测试以概率分布 进行随机抽样获得测试集

自适应随机测试(会出一条应用题 考距离如何测量)ART Adaptive Random Testing

自适应随机测试以概率分布 进行随机抽样并结合距离度量反馈信息获得测试集 T

image-20260102122522196

image-20260102122751742

引导性随机测试 了解即可

选择适当的测试生成方法,快速生成测试覆盖程序的各种路径或指定路径。

用符号执行探索程序路径并生成路径约束条件 最后求解这些约束条件得到程序的测试输入范围

等价类测试方法

必出应用题 需要掌握流程

image-20260102131756651

image-20260102132016233

image-20260102132426753

组合测试

image-20260102133028953

故障假设测试

边界故障假设

黑盒故障假设

image-20260102134650507

白盒故障假设

image-20260102134932515

变异缺陷假设

需要知道基本概念和两个假设

image-20260102140651265

变异分析(Mutation Analysis),也称为变异测试,是一种用于评估测试集有效性和充分性的技术。它通过对原程序进行微小的语法修改来生成“变异体”,并检查现有的测试集能否发现这些人为注入的缺陷。

以下是其核心概念:

  1. 变异体 (Mutant)
  • 定义:变异体 $P’$ 是对原程序 $P$ 进行符合语法规则的微小代码修改后生成的程序版本。
  • 特征
    • 微小修改:模拟程序员可能犯的简单错误(基于“熟练程序员假设”)。
    • 符合语法:确保变异体能够通过编译并运行。
    • 预期差异:理论上期待测试 $t$ 在运行变异体 $P’$ 时,其行为(输出)与原程序 $P$ 不一致。
  1. 变异体检测 (Mutant Detection)
  • 定义:也称为“杀死”变异体。如果测试用例 $t$ 使得变异体 $P’$ 的运行结果与原程序 $P$ 不同(即 $P’(t) \neq P(t)$),则称测试 $t$ 检测(杀死)了变异体 $P’$。
  • 存活变异体:如果变异体在测试下通过(即结果与原程序一致),则称该变异体是存活的。
  • 检测分类
    • 弱杀死 (Weak Kill):变异体的中间状态与原程序不同。
    • 强杀死 (Strong Kill):变异体的最终输出结果与原程序不同(这是传统意义上的变异分析)。
  1. 变异分数 (Mutation Score)
  • 定义:变异分数是评估测试集质量的重要度量指标。

  • 计算公式:

    \[变异分数 = \frac{杀死的变异体个数}{变异体总数 (n)}\]
  • 意义:测试集杀死的变异体越多,分值越高,代表测试集的质量越高。

  1. 等价变异体 (Equivalent Mutant)
  • 定义:如果不存在任何测试用例能够杀死变异体 $P’$,则称 $P’$ 是 $P$ 的等价变异体。
  • 特点:它在语法上与原程序不同,但在语义上完全等价(即对于任意输入,输出行为都相同)。
  • 难点:在实践中很难判定一个变异体是否绝对等价,这会影响变异分数的准确性。
  1. 变异算子 (Mutation Operator)
  • 定义:变异算子定义了生成变异体的规则(在符合语法规则的前提下)。
  • 常见类型
    • 值变异:改变常量或参数的值(例如 $x=5$ 变为 $x=10$)。
    • 语句变异:增加、删除、替换语句(例如 $total=x-y$ 变为 $total=x+y$)。
    • 决策变异:改变逻辑或算术运算符(例如 $x>y$ 变为 $x<y$)。
  • 经典算子:如 ABS(绝对值插入)、AOR(算术操作符替换)、ROR(关系运算符替换)等。

变异测试优化技术

变异测试的主要挑战在于生成和执行的变异体数量巨大,导致成本高昂。优化的目标是找到一个较小的变异体集合,使其对测试集的评估能力近似于完整集合。

主要有以下三种优化方法:

  1. 变异算子选择 (Mutation Operator Selection)
  • 策略:不使用所有可能的算子,而是从经验上相似的算子中选择具有代表性的变异算子。
  • 强变异算子:基于“强弱”关系进行选择。如果杀死算子 $O_1$ 生成的变异体必然能杀死算子 $O_2$ 生成的变异体,则认为 $O_1$ 强于 $O_2$,应优先选择强变异算子。
  1. 变异体随机选择 (Mutant Random Selection)
  • 策略:从生成的变异体池中,基于经验进行均匀随机抽样,仅执行抽取到的样本。
  • 原理:通过统计学原理,用一部分变异体的得分来估算整体的变异分数。
  1. 变异体聚类抽样 (Mutant Cluster Sampling)
  • 策略:先对变异体进行聚类分析,然后从每个类中进行随机抽样。
  • 原理
    • 相似性:如果两个变异体对于大多数测试的被杀死情况是相同的,则认为它们是相似的(冗余的)。
    • 通过聚类识别相似变异体,去除冗余,只保留代表性变异体,从而在降低成本的同时保持评估的准确性。

逻辑故障假设

软件逻辑故障是指在程序代码中存在的逻辑错误或不当的设计,导致程序无法按照预期执行或出现异常行为

我们不盲目地乱测,而是假设程序里的错误就是“把AND写成OR”、“写错变量名”、“条件永远为真/假”这几种。并且利用“擒贼先擒王”的策略(故障强弱关系),优先检测最复杂的逻辑错误,从而用最少的测试次数,揪出最多Bug

图分析测试

image-20260102142522875

控制流图 必考

image-20260103132734511

image-20260102142745885

image-20260102143016712

数据流图 选择题

image-20260102143516621

事件流图 选择题

image-20260102143711821

图结构测试方法

主路径测试

image-20260102145031708

image-20260102145041784

image-20260102145735331

基本路径测试

image-20260102150221638

图元素测试

数据流测试

image-20260102150439015

逻辑测试 重点需要掌握

image-20260102150610944

image-20260102150624431

image-20260102150705700image-20260102150750065

开发者测试

单元测试

image-20260102152244637

接口测试

接口测试是指针对软件系统中的接口进行的测试,以验证接口是否能够按照预期进行通信和数据交换

集成测试

集成测试旨在验证软件组件的协同工作能力,并检测系统功能性和性能问题

多样性开发者测试 需要知道使用覆盖的原因 为什么使用覆盖而非错误率

也称为变异测试,通过修改源代码生成变异体,然后运行测试集,观察测试集是否能够检测到变异体中的缺陷

代码多样性:也就是常说的代码覆盖测试,通过遍历程序的逻辑结构,评估测试用例对代码的覆盖程度。它要求测试满足特定的覆盖标准,如语句覆盖、分支覆盖等

image-20260102152710232

故障假设开发者测试

测试粒度、测试优势

测试类型 测试粒度 (测试范围) 测试优势
单元测试 (Unit Testing) 最细粒度 (组件/代码块) 针对应用程序代码分解后的最小单元(如函数、类、方法)进行测试。 1. 尽早发现问题:在开发周期早期进行,大幅降低修复成本。 2. 提高代码质量:验证代码的正确性、清晰性、规范性和高效性。 3. 确保可测试性:辅助 TDD 开发,帮助设计可测试的代码结构。 4. 作为代码审查:提供额外视角,确保代码在首次编写时就是健壮的。
接口测试 (Interface/API Testing) 中等粒度 (通信/数据交换) 位于单元测试和 GUI 测试之间,针对软件系统中的接口,验证通信和数据交换。 1. 反馈及时:提供即时反馈,适合敏捷开发和快速迭代。 2. 效率高:测试速度快于系统级 GUI 测试,且业务覆盖率高。 3. 保障稳定性:确保组件间数据传输的正确性和安全性,修复缺陷以保障软件可靠性。
集成测试 (Integration Testing) 较大粒度 (组件组装/协作) 在单元测试之后,验证模块组装后的协同工作能力。 1. 发现接口缺陷:检测单元测试无法发现的模块间接口调用错误。 2. 解决数据问题:发现跨模块传输中的数据丢失、阻塞或格式错误。 3. 检测并发问题:发现模块同步运行时的死锁、资源竞争等问题。
多样性开发者测试 (Diversity Testing) 逻辑结构粒度 (路径/覆盖率) 基于代码覆盖(如语句、分支),遍历程序的逻辑结构和执行路径。 1. 评估测试完备性:通过覆盖率标准评估测试用例对代码的遍历程度。 2. 深入理解逻辑:结合路径分析和路径谓词,帮助开发者更好地理解程序逻辑。 3. 提高测试质量:利用约束求解生成特定路径的输入,发现深层缺陷。
故障假设开发者测试 (Fault Hypothesis Testing) 故障模拟粒度 (变异体/缺陷) 基于假设的故障(如人工注入的变异体),在源码级别进行微小修改以模拟缺陷。 1. 评估测试集有效性:通过能否检测到变异体(杀死变异体),验证测试集发现缺陷的能力。 2. 暴露测试不足:主动暴露测试集的盲区,指导优化测试数据集。 3. 模拟潜在故障:模拟逻辑错误或程序崩溃等场景,提升测试覆盖率。

功能测试

确定功能需求-设计测试用例-执行测试与验证

多样性功能测试 和前面结合考

  • 等价类划分
  • 因果图分析

image-20260102153618082

  • 类别划分

image-20260102153702731

故障假设功能测试

  1. 测试规划与分析 2. 测试实施方法 3. 测试评估与改进

性能测试

性能测试是一种评估软件或系统在实际运行环境中表现的方法,通过模拟真实用户行为,评估系统在响应时间、吞吐量和资源利用率等指标的表现,确保其满足预定的性能需求。利用负载模拟和压力测试,分析系统在不同负载下的表现,发现并解决性能瓶颈,优化资源使用效率,保障系统高效运行

image-20260102153826186

image-20260102153915097

image-20260102153938051

适配测试

image-20260102154031478

image-20260102154052615

image-20260102154124393

image-20260102154141196

模糊测试

image-20260102154254638

image-20260102154301911

image-20260102154308814

image-20260102154315726

image-20260102154344268

设计变异算子 重点

变异算子的设计决定了如何从旧种子产生新输入,目标是保持输入结构的有效性同时探索边界情况。

变异策略分类

  • 基于变异 (Mutation-based): 对比特流进行随机或启发式的修改。
  • 基于生成 (Generation-based): 利用文法规则 (Grammar) 或数据模型 (Data Model) 生成结构化输入。

常见变异算子 (以AFL为例)

AFL (American Fuzzy Lop) 使用了一套经典的确定性和随机性变异算子:

  • Bitflip (位翻转):
    • bitflip L/S: 以步长 S 翻转 L 个比特位(如翻转 1bit, 2bits, 4bits)。
  • Arithmetic (算术运算):
    • arith L/8: 对字节进行加减小整数的操作(如 8bit, 16bit, 32bit 整数加减)。
  • Interest (有趣值替换):
    • interest L/8: 将字节替换为已知的“有趣数”(如溢出边界值 -1, 0, MAX_INT 等)。
  • Havoc (大肆破坏):
    • 对输入进行大量随机的综合变异(堆叠多种算子),产生较大的破坏。
  • Splice (拼接):
    • 随机拼接两个不同种子的一部分,试图组合出新的路径。

高级设计思路

  • 语义感知 (Semantics-Aware): 分析程序中的语义检查(如 Magic Number 检查、Checksum 校验),识别影响语义的字段,针对性地设计变异策略以通过检查 (例如 SLF 工具)。
  • 基于文法 (Grammar-based): 使用概率文法 (Probabilistic Grammar) 描述输入分布,甚至通过学习现有输入的分布来进行“反向”生成(互补文法),以生成能够触发异常的边缘输入。

设计有效反馈

反馈机制是模糊测试的“眼睛”,用于引导测试向更有价值的方向探索。

反馈类型 (根据运行时信息)

  1. 黑盒 (Blackbox):
    • 反馈: 仅依赖输入/输出状态(如是否崩溃、响应时间)。
    • 特点: 效率高但引导性弱,无法感知内部执行状态。
  2. 白盒 (Whitebox):
    • 反馈: 利用污点分析 (Taint Analysis) 或符号执行 (Symbolic Execution) 获取精确的程序约束。
    • 特点: 引导极强,能通过复杂检查,但开销巨大,扩展性差。
  3. 灰盒 (Greybox) - 主流方向:
    • 反馈: 轻量级代码插桩 (Instrumentation)。
    • 核心指标: 代码覆盖率 (Code Coverage)(如边覆盖、基本块覆盖)。
    • 其他指标: 线程状态、堆内存状态等。

如何设计有效的反馈机制

  • 覆盖率引导 (Coverage-guided):
    • 如果一个输入触发了新的路径(New Edge/Path),则认为该输入是“有趣的” (Interesting/Valuable),将其保存为新种子。
    • 马太效应: 好的种子能演化出更好的后代。
  • 种子优先级排序 (Seed Prioritization):
    • 距离计算 (Distance): 在定向模糊测试 (Directed Fuzzing) 中,计算种子执行路径与目标漏洞代码的距离。距离越近,优先级越高。
    • 离群点优先: 优先选择覆盖率分布上独特的、偏离常规的种子。
  • 能量调度 (Power Schedule):
    • 根据反馈动态调整每个种子的变异次数。覆盖率高、执行路径罕见或距离目标近的种子,获得更多变异机会。
  • 程序平滑 (Program Smoothing):
    • 在基于梯度的模糊测试中(如 Neuzz),利用神经网络拟合程序行为,解决覆盖率反馈不连续的问题,利用梯度下降来指导变异方向。

测试用例优先级

image-20260102155833406

image-20260102155921309

image-20260102155949514

image-20260102160102708

image-20260102160112580

image-20260102160130570

image-20260102160144113

image-20260102160206309