名称: 测试用例设计 描述: 应用系统性的测试用例设计技术,包括等价类划分、边界值分析、决策表测试和状态转移测试。 允许工具: Read, Write, Glob, Grep, Task, WebSearch, WebFetch
测试用例设计技术
何时使用此技能
使用此技能当:
- 测试用例设计任务 - 处理应用系统性的测试用例设计技术,包括等价类划分、边界值分析、决策表测试和状态转移测试
- 计划或设计 - 需要关于测试用例设计方法的指导
- 最佳实践 - 希望遵循建立的模式和标准
概述
系统性的测试用例设计技术确保全面覆盖同时最小化测试用例数量。这些黑盒技术从规范中推导测试用例,无需了解内部实现。
等价类划分
将输入数据划分为等价类,其中任何值都应产生相同行为。
过程
- 识别输入条件
- 划分为有效和无效分区
- 从每个分区选择一个代表值
- 为每个分区创建测试用例
示例:年龄验证(18-65)
| 分区 | 范围 | 代表值 | 预期 |
|---|---|---|---|
| 无效(低于) | < 18 | 10 | 拒绝 |
| 有效 | 18-65 | 30 | 接受 |
| 无效(高于) | > 65 | 70 | 拒绝 |
测试用例:
- TC1: 年龄 = 10 → 拒绝(无效低于)
- TC2: 年龄 = 30 → 接受(有效)
- TC3: 年龄 = 70 → 拒绝(无效高于)
多输入分区
系统地组合分区:
输入 A: {有效, 无效}
输入 B: {有效, 无效}
组合:
1. A-有效, B-有效 → 预期: 成功
2. A-有效, B-无效 → 预期: B错误
3. A-无效, B-有效 → 预期: A错误
4. A-无效, B-无效 → 预期: 两者错误
边界值分析
测试分区边界处及周围,缺陷常发生的地方。
过程
- 从等价分区识别边界
- 测试最小值、略低于、略高于和最大值
- 包括特殊值(0、空、null)
示例:年龄验证(18-65)
| 边界 | 测试值 | 预期 |
|---|---|---|
| 低于最小值 | 17 | 拒绝 |
| 在最小值 | 18 | 接受 |
| 高于最小值 | 19 | 接受 |
| 正常 | 40 | 接受 |
| 低于最大值 | 64 | 接受 |
| 在最大值 | 65 | 接受 |
| 高于最大值 | 66 | 拒绝 |
扩展边界:
- 0(边缘情况)
- -1(负值)
- MAX_INT(溢出)
- null(缺失)
.NET 示例
public class AgeValidationTests
{
[Theory]
[InlineData(17, false)] // 低于最小值
[InlineData(18, true)] // 在最小值
[InlineData(19, true)] // 高于最小值
[InlineData(40, true)] // 正常
[InlineData(64, true)] // 低于最大值
[InlineData(65, true)] // 在最大值
[InlineData(66, false)] // 高于最大值
[InlineData(0, false)] // 零
[InlineData(-1, false)] // 负值
public void ValidateAge_ReturnsExpected(int age, bool expected)
{
var result = _validator.IsValidAge(age);
Assert.Equal(expected, result);
}
}
决策表测试
用多条件系统测试复杂的业务规则。
过程
- 识别条件(输入)
- 识别动作(输出)
- 创建包含所有条件组合的表格
- 使用“无关”条件简化
示例:折扣计算
条件:
- 是会员? (Y/N)
- 订单 > $100? (Y/N)
- 有优惠券? (Y/N)
动作:
- 应用会员折扣(10%)
- 应用批量折扣(5%)
- 应用优惠券折扣(15%)
| 规则 | 会员 | 订单>$100 | 优惠券 | 会员% | 批量% | 优惠券% |
|---|---|---|---|---|---|---|
| R1 | Y | Y | Y | X | X | X |
| R2 | Y | Y | N | X | X | - |
| R3 | Y | N | Y | X | - | X |
| R4 | Y | N | N | X | - | - |
| R5 | N | Y | Y | - | X | X |
| R6 | N | Y | N | - | X | - |
| R7 | N | N | Y | - | - | X |
| R8 | N | N | N | - | - | - |
.NET 示例
public class DiscountCalculationTests
{
public static TheoryData<bool, decimal, bool, decimal> DiscountScenarios => new()
{
{ true, 150m, true, 0.30m }, // R1: 会员 + 批量 + 优惠券
{ true, 150m, false, 0.15m }, // R2: 会员 + 批量
{ true, 50m, true, 0.25m }, // R3: 会员 + 优惠券
{ true, 50m, false, 0.10m }, // R4: 仅会员
{ false, 150m, true, 0.20m }, // R5: 批量 + 优惠券
{ false, 150m, false, 0.05m }, // R6: 仅批量
{ false, 50m, true, 0.15m }, // R7: 仅优惠券
{ false, 50m, false, 0.00m }, // R8: 无折扣
};
[Theory]
[MemberData(nameof(DiscountScenarios))]
public void CalculateDiscount_ReturnsExpected(
bool isMember, decimal orderTotal, bool hasCoupon, decimal expectedDiscount)
{
var discount = _calculator.Calculate(isMember, orderTotal, hasCoupon);
Assert.Equal(expectedDiscount, discount);
}
}
状态转移测试
测试具有不同状态和状态间转移的系统。
过程
- 识别状态
- 识别有效转移
- 创建状态转移表/图
- 为每个转移设计测试
- 包括无效转移测试
示例:订单状态机
┌──────────┐
│ 草稿 │
└────┬─────┘
│ submit()
▼
┌──────────┐
┌────│ 待处理 │────┐
│ └────┬─────┘ │
│ │ approve()│ reject()
│ ▼ ▼
│ ┌──────────┐ ┌──────────┐
│ │ 已批准 │ │ 已拒绝 │
│ └────┬─────┘ └──────────┘
│ │ ship()
│ ▼
│ ┌──────────┐
└────│ 已发货 │
└────┬─────┘
│ deliver()
▼
┌──────────┐
│ 已交付 │
└──────────┘
状态转移表
| 当前状态 | 事件 | 下一状态 | 有效 |
|---|---|---|---|
| 草稿 | submit | 待处理 | ✓ |
| 草稿 | approve | - | ✗ |
| 待处理 | approve | 已批准 | ✓ |
| 待处理 | reject | 已拒绝 | ✓ |
| 已批准 | ship | 已发货 | ✓ |
| 已发货 | deliver | 已交付 | ✓ |
| 已交付 | * | - | ✗ |
.NET 示例
public class OrderStateTests
{
[Fact]
public void Draft_Submit_TransitionsToPending()
{
var order = new Order { Status = OrderStatus.Draft };
order.Submit();
Assert.Equal(OrderStatus.Pending, order.Status);
}
[Fact]
public void Draft_Approve_ThrowsInvalidStateException()
{
var order = new Order { Status = OrderStatus.Draft };
Assert.Throws<InvalidOperationException>(() => order.Approve());
}
[Fact]
public void Delivered_AnyAction_ThrowsFinalStateException()
{
var order = new Order { Status = OrderStatus.Delivered };
Assert.Throws<InvalidOperationException>(() => order.Cancel());
}
}
配对测试
当完全组合测试不切实际时,高效测试组合。
概念
大多数缺陷是由2个参数之间的相互作用引起的。测试所有对覆盖大多数风险,使用较少测试。
示例:浏览器兼容性
参数:
- 浏览器: Chrome, Firefox, Safari, Edge
- 操作系统: Windows, macOS, Linux
- 版本: 最新, 上一个
完全组合: 4 × 3 × 2 = 24 测试 配对覆盖: 8-12 测试 (覆盖所有对)
配对测试集
| 测试 | 浏览器 | 操作系统 | 版本 |
|---|---|---|---|
| 1 | Chrome | Windows | 最新 |
| 2 | Firefox | macOS | 上一个 |
| 3 | Safari | macOS | 最新 |
| 4 | Edge | Windows | 上一个 |
| 5 | Chrome | Linux | 上一个 |
| 6 | Firefox | Windows | 最新 |
| 7 | Chrome | macOS | 最新 |
| 8 | Edge | Linux | 最新 |
使用工具如 PICT, AllPairs, 或在线生成器。
错误猜测
基于经验的技术,识别可能的缺陷区域。
常见错误模式
| 类别 | 示例 |
|---|---|
| 空/空值 | null 输入, 空字符串, 空集合 |
| 边界 | 差一错误, 溢出, 下溢 |
| 格式 | 无效日期, 格式错误的电子邮件, 错误编码 |
| 状态 | 竞态条件, 陈旧数据, 并发 |
| 资源 | 内存耗尽, 连接限制, 超时 |
| 安全 | SQL注入, XSS, 路径遍历 |
错误猜测检查清单
- [ ] 如果输入为 null?
- [ ] 如果输入为空?
- [ ] 如果输入包含特殊字符?
- [ ] 如果输入超过最大长度?
- [ ] 如果并发请求发生?
- [ ] 如果外部服务失败?
- [ ] 如果数据库连接中断?
- [ ] 如果输入为负值?
- [ ] 如果列表有重复项?
技术选择指南
| 场景 | 推荐技术 |
|---|---|
| 范围验证 | 边界值分析 + 等价类划分 |
| 复杂业务规则 | 决策表测试 |
| 状态依赖行为 | 状态转移测试 |
| 多参数输入 | 配对测试 |
| 错误处理 | 错误猜测 |
| 关键计算 | 所有技术组合 |
集成点
输入来源:
- 需求 → 测试条件
test-strategy-planning技能 → 覆盖目标
输出到:
acceptance-criteria-authoring技能 → 场景覆盖- 测试自动化 → 测试数据