软件测试Skill testing

这个技能专注于编写和执行高效软件测试,包括单元测试、集成测试和端到端测试。它提供了测试设计原则、模拟规则、调试方法以及不稳定测试管理策略。适用于开发人员、测试工程师和质量保证团队,以提高代码质量和可靠性。关键词:软件测试、测试策略、模拟、调试、测试覆盖、不稳定测试。

测试 0 次安装 0 次浏览 更新于 3/19/2026

name: 测试 description: 编写有效测试并成功运行。涵盖特定层的模拟规则、测试设计原则、调试失败和不稳定测试管理。在编写测试、审查测试质量或调试测试失败时使用。

身份

您是一个测试专家,设计有效的测试策略,在适当层编写测试,并使用系统方法调试测试失败。

约束

约束 {
  要求 {
    遵循 Arrange-Act-Assert 结构
    使用描述性测试名称来描述被验证的行为
    测试边界情况:null、空、边界、负值、错误条件
    在测试前运行 lint/类型检查以获取最快反馈
  }
  从不 {
    模拟内部应用程序代码 — 仅模拟外部边界(数据库、API、文件系统)
    测试实现细节 — 通过公共接口测试可观察行为
    在测试之间共享可变状态 — 每个测试必须独立
    忽略不稳定测试 — 立即隔离,一周内修复,或删除
  }
}

愿景

在编写测试前,阅读并内化:

  1. 项目 CLAUDE.md — 架构、约定、测试要求
  2. docs/specs/ 中的相关规范文档 — 驱动测试设计的验收标准
  3. 项目根目录的 CONSTITUTION.md — 如果存在,约束测试方法
  4. 现有测试模式 — 与已建立的测试约定保持一致

使用时机

  • 编写单元、集成或端到端测试
  • 调试测试失败
  • 审查测试质量
  • 决定模拟与使用真实实现

层分布

  • 单元测试 (60-70%): 仅模拟边界
  • 集成测试 (20-30%): 真实依赖,仅模拟外部服务
  • 端到端测试 (5-10%): 无模拟 - 真实用户旅程

按层编写测试

单元测试

目的: 验证隔离的业务逻辑。

模拟规则:

  • 仅模拟边缘(数据库、API、文件系统、时间)
  • 使用实际实现测试真实被测系统
  • 使用真实内部协作者 - 仅模拟外部边界
// 正确: 仅模拟外部依赖
const service = new OrderService(mockRepository)  // 仓库是边缘
const total = service.calculateTotal(order)
expect(total).toBe(90)

// 错误: 模拟内部方法
vi.spyOn(service, 'applyDiscount')  // 现在你在测试模拟

特征: < 100ms,无 I/O,确定性

在此测试: 业务逻辑、验证、转换、边界情况


集成测试

目的: 验证组件与真实依赖一起工作。

模拟规则:

  • 使用真实数据库
  • 使用真实缓存
  • 仅模拟外部第三方服务(Stripe、SendGrid)
// 正确: 真实数据库,模拟外部支付API
const db = await createTestDatabase()
const paymentApi = vi.mocked(PaymentGateway)
const service = new CheckoutService(db, paymentApi)

await service.checkout(cart)

expect(await db.orders.find(orderId)).toBeDefined()  // 真实数据库
expect(paymentApi.charge).toHaveBeenCalledOnce()     // 模拟外部

特征: < 5 秒,容器化依赖,测试间清洁状态

在此测试: 数据库查询、API 合同、服务通信、缓存


端到端测试

目的: 在真实系统中验证关键用户旅程。

模拟规则:

  • 无模拟 - 这就是整个点
  • 使用真实服务(沙盒/测试模式)
  • 真实浏览器自动化
// 真实浏览器,真实系统(Playwright 示例)
await page.goto('/checkout')
await page.fill('#card', '4242424242424242')
await page.click('[data-testid="pay"]')

await expect(page.locator('.confirmation')).toContainText('订单已确认')

特征: < 30 秒,仅关键路径,立即修复不稳定性

在此测试: 注册、结账、认证流程、冒烟测试


核心原则

测试行为,而非实现

// 正确: 可观察行为
expect(order.total).toBe(108)

// 错误: 实现细节
expect(order._calculateTax).toHaveBeenCalled()

Arrange-Act-Assert

// 安排
const mockEmail = vi.mocked(EmailService)
const service = new UserService(mockEmail)

// 行动
await service.register(userData)

// 断言
expect(mockEmail.sendTo).toHaveBeenCalledWith('user@example.com')

每个测试一个行为

如果验证相同逻辑结果,多个断言可以。

描述性名称

// 好
it('当库存不足时拒绝订单', ...)

// 坏
it('测试订单', ...)

测试隔离

测试之间无共享可变状态。


运行测试

执行顺序

  1. Lint/类型检查 - 最快反馈
  2. 单元测试 - 快速,高容量
  3. 集成测试 - 真实依赖
  4. 端到端测试 - 最高置信度

调试失败

单元测试失败:

  1. 仔细阅读断言消息
  2. 检查测试设置(安排部分)
  3. 隔离运行以排除状态泄漏
  4. 添加日志以跟踪执行路径

集成测试失败:

  1. 检查数据库前后状态
  2. 验证模拟配置正确
  3. 查找竞争条件或定时问题
  4. 检查事务/回滚行为

端到端测试失败:

  1. 检查截图/视频(大多数框架捕获这些)
  2. 验证选择器是否仍匹配 UI
  3. 为异步操作添加显式等待
  4. 在本地运行可见浏览器以观察
  5. 比较 CI 环境与本地

不稳定测试

积极处理 - 它们侵蚀信任:

  1. 隔离 - 立即移动到单独套件
  2. 一周内修复 - 或删除
  3. 常见原因:
    • 测试之间共享状态
    • 时间依赖逻辑
    • 竞争条件
    • 非确定性排序

覆盖率

质量优于数量 - 80% 有意义的覆盖率优于 100% 琐碎覆盖率。

专注于业务关键路径(支付、认证、核心领域逻辑)的测试工作。跳过生成代码。


边界情况

始终测试:

边界: 最小-1、最小、最小+1、最大-1、最大、最大+1、零、一、多

特殊值: null、空、负、MAX_INT、NaN、Unicode、闰年、时区

错误: 网络失败、超时、无效输入、未授权


反模式

模式 问题
过度模拟 测试模拟而非代码
实现测试 重构时中断
共享状态 测试顺序影响结果
测试重复 使用参数化测试替代

参考