软件质量工程 06
软件测试 (Software Testing)
软件测试概述
-
定义: 软件测试是评估软件质量的重要手段,通过验证软件是否满足指定要求并检测错误。
-
目标: 通过系统地在受控环境下执行软件,确认软件质量,发现尚未发现的错误 (Good test focuses on finding as-yet-undiscovered errors, successful test uncovers unknown errors)。
-
重要性:
- 软件测试通常占开发工作量的 40% 至 50%,对于需要高可靠性的软件尤为重要。
- 测试涵盖的方面包括:
- 性能 (Performance)
- 安全性 (Security)
- 可扩展性 (Scalability)
- 合规性 (Compliance)
- 互操作性 (Interoperability)
- 错误处理 (Error Handling)
-
随着软件维护和扩展,测试时间需求增加,需要系统化的测试方法。
软件测试测量
- 测量依据: 根据软件的属性或产品特性(如功能性、可靠性、可用性、效率、可维护性、安全性、可移植性等)进行测量。
- 测试结果的四个层次:
- 是否运行了计划的测试?(Level 1: Did you run the planned tests?)
- 测试结果如何?(Level 2: What are the test results?)
- 是否应用测试结果改进代码?(Level 3: Did you apply the test results to improve the code?)
- 测试投入的回报率如何?(Level 4: What is the return on investment for the amount spent on testing?)
常用软件测试指标 (Common Software Testing Metrics)
指标名称 (Metric Name) | 描述 (Description) |
---|---|
测试用例通过率 (Test Case Pass Rate) | 执行测试用例中通过的百分比 (Percentage of passed test cases over total executed) |
缺陷密度 (Defect Density) | 每千行代码的确认缺陷数量 (Number of confirmed defects per KLOC) |
测试覆盖率 (Test Coverage) | 测试覆盖的代码百分比(语句、分支、路径)(Percentage of code covered by tests: statement, branch, path) |
缺陷移除效率 (Defect Removal Efficiency) | 发布前检测到的缺陷百分比 (% of defects detected before release) |
ISO/IEC/IEEE 29119 软件测试标准
-
适用范围: 适用于软件产品开发和维护的全过程。
-
目标: 解决定义和程序冲突,提供组织测试策略、项目测试管理、系统与验收测试技术及非功能测试的标准。
-
结构:
- 概念与词汇 (Concepts and Vocabulary): 提供软件测试概念和词汇以增强可理解性。
- 测试文档 (Test Documentation): 包括组织测试策略、项目测试计划、测试完成报告等。
- 测试流程 (Test Processes): 包括组织测试流程、测试管理流程和基本测试流程。
- 测试技术与覆盖率 (Testing Techniques and Coverage):
- 静态测试 (Static Testing, e.g., reviews, inspections)
- 动态测试 (Dynamic Testing, e.g., white box and black box)
- 非功能测试 (Non-functional Testing)
- 测试测量 (Test Measurement)
-
验证与确认:
- 验证 (Verification): 确保测试项符合规范、要求或其他文档。
- 确认 (Validation): 确保测试项满足利益相关者的需求。
白盒测试 (White Box Testing)
- 别名: 结构测试 (Structural Testing)
- 特点:
- 关注软件的内部结构。
- 测试用例的选择基于软件实体的实现。
- 根据覆盖标准(如路径覆盖、分支覆盖、语句覆盖)评估预期结果。
- 验证内容:
- 所有测试通过。
- 所有代码语句被执行 (语句覆盖, Statement Coverage)。
- 每个条件的每个分支被执行 (分支覆盖, Branch Coverage)。
- 所有路径被遍历 (路径覆盖, Path Coverage)。
黑盒测试 (Black Box Testing)
- 别名: 基于规格的测试 (Specification-based Testing)、功能测试 (Functional Testing)
- 特点:
- 关注输入域、预期行为、规格和软件知识。
- 不考虑代码内部结构。
- 测试内容:
- 基于特定数据设计测试用例。
- 确定函数或子函数是否按预期工作。
- 识别软件的函数和子函数。
- 识别与测试相关的数据属性和执行条件。
- 测试每个功能是否按预期执行。
黑盒测试与白盒测试比较
特性 | 黑盒测试 (Black Box Testing) | 白盒测试 (White Box Testing) |
---|---|---|
定义 | 基于软件规格和预期行为测试,不考虑内部结构 | 基于软件内部结构和代码测试 |
测试依据 | 输入域(input domain)、功能需求 | 代码实现、程序结构 |
覆盖标准 | 功能覆盖(function coverage) | 语句覆盖(statement coverage)、分支覆盖(branch coverage)、路径覆盖(path coverage) |
适用场景 | 验证功能是否符合要求(verify if meets expected behaviour) | 验证代码逻辑和执行路径 |
圈复杂度 (Cyclomatic Complexity)
-
定义: 圈复杂度是一种衡量程序复杂度的软件指标。
-
计算公式:
$$ \text{Cyclomatic Complexity} = E - N + 2 $$
其中:
- $E$ = 边数 (Number of edges)
- $N$ = 节点数 (Number of nodes)
-
意义:
- 表示程序中独立路径的数量。
- 等于程序中条件的数量。
- 测试所有控制语句所需的测试用例数量等于圈复杂度。
- 但圈复杂度不代表测试的充分性(即使所有路径被执行,路径的所有组合可能未被测试)。
或者也可以使用公式: $\text{Cyclomatic Complexity} = DP + 1$ DP 是决策点
示例代码
以下代码用于计算圈复杂度:
if (c1()) {
f1();
} else {
f2();
}
if (c2()) {
f3();
} else {
f4();
}
flowchart TD A[Start] --> B{c1 ?} B -- 是 --> C[f1] B -- 否 --> D[f2] C --> E{c2 ?} D --> E E -- 是 --> F[f3] E -- 否 --> G[f4] F --> H[End] G --> Hflowchart TD A[Start] --> B{c1 ?} B -- 是 --> C[f1] B -- 否 --> D[f2] C --> E{c2 ?} D --> E E -- 是 --> F[f3] E -- 否 --> G[f4] F --> H[End] G --> H
- 计算:
- 程序流图有 8 条边,7 个节点:
- $E = 8$, $N = 7$
- 圈复杂度 = $8 - 7 + 2 = 3$
- 独立路径数量为 3,需设计 3 个测试用例以覆盖所有路径。
其他示例:
- 条件语句:
int a = 1;
int b = 2;
if (a > b) {
cout << "a is greater";
} else {
cout << "b is greater";
}
- 圈复杂度 = 2(一个条件,两个路径:a > b 和 a ≤ b)。
- 循环语句:
int i = 1;
for (i = 1; i <= 5; i++) {
cout << i << endl;
}
graph TD A[Start] --> B[int i = 1]; B --> C{Is i <= 5?}; C -- Yes --> D[cout << i << endl;]; D --> E[i++]; E --> C; C -- No --> F[End];graph TD A[Start] --> B[int i = 1]; B --> C{Is i <= 5?}; C -- Yes --> D[cout << i << endl;]; D --> E[i++]; E --> C; C -- No --> F[End];
- 圈复杂度 = 2(一个循环条件,两个路径:进入循环和退出循环)。
可能考法与示例考题
可能考法
- 定义与概念:
- 解释软件测试的定义和目标。
- 区分验证 (Verification) 和确认 (Validation)。
- 黑盒测试与白盒测试:
- 比较黑盒测试和白盒测试的区别。
- 描述各自的覆盖标准。
- 圈复杂度:
- 计算给定代码的圈复杂度。
- 列出独立路径。
- 测试指标:
- 解释常见测试指标(如测试用例通过率、缺陷密度)。
- 费根检查:
- 描述费根检查的步骤和应用场景。
示例考题
-
考题: 解释黑盒测试和白盒测试的区别,并列出各自的优缺点。
- 参考答案 (中文):
- 黑盒测试 (Black Box Testing):
- 定义:基于软件规格和功能需求测试,不考虑内部代码结构。
- 优点:专注于用户需求,测试用例设计简单,适合验收测试。
- 缺点:无法发现代码内部逻辑错误,覆盖率可能不足。
- 白盒测试 (White Box Testing):
- 定义:基于代码内部结构测试,关注语句、分支和路径覆盖。
- 优点:能发现代码逻辑错误,覆盖率高。
- 缺点:需要了解代码结构,测试用例设计复杂。
- 黑盒测试 (Black Box Testing):
- Reference Answer (English):
- Black Box Testing:
- Definition: Testing based on software specifications and functional requirements without considering internal code structure.
- Advantages: Focuses on user requirements, simple test case design, suitable for acceptance testing.
- Disadvantages: Cannot detect internal logic errors, coverage may be insufficient.
- White Box Testing:
- Definition: Testing based on internal code structure, focusing on statement, branch, and path coverage.
- Advantages: Can detect logic errors in code, high coverage.
- Disadvantages: Requires understanding of code structure, complex test case design.
- Black Box Testing:
- 参考答案 (中文):
-
考题: 给定以下代码,计算其圈复杂度并列出独立路径:
if (x > 0) {
y = x * 2;
} else {
y = x + 1;
}
if (y > 10) {
z = y - 10;
} else {
z = y;
}
- 参考答案 (中文):
- 圈复杂度计算:
- 程序流图:2 个条件 (x > 0 和 y > 10),每个条件有 2 个分支。
- 圈复杂度 = 条件数 + 1 = 2 + 1 = 3。
- 独立路径:
- x > 0, y > 10: 执行 y = x * 2, z = y - 10。
- x > 0, y ≤ 10: 执行 y = x * 2, z = y。
- x ≤ 0: 执行 y = x + 1, z = y。
- 圈复杂度计算:
- Reference Answer (English):
- Cyclomatic Complexity Calculation:
- Program flow graph: 2 conditions (x > 0 and y > 10), each with 2 branches.
- Cyclomatic Complexity = Number of conditions + 1 = 2 + 1 = 3.
- Independent Paths:
- x > 0, y > 10: Execute y = x * 2, z = y - 10.
- x > 0, y ≤ 10: Execute y = x * 2, z = y.
- x ≤ 0: Execute y = x + 1, z = y.
- Cyclomatic Complexity Calculation: