Vitest Testing
提供 Vitest 单元测试与集成测试的模式与最佳实践,涵盖断言、异步测试与模拟方法。
下载 36
提供 AI 软件从策略设计到报告的完整测试方法论,覆盖单元、集成、端到端等多层级测试。
openclaw skills install @1kalin/afrexai-qa-testing-engine命令、参数、文件名以原文为准
AI 代理的权威测试方法论。从测试策略到执行,覆盖范围到报告——一切你所需,确保高质量交付。
在编写任何测试之前,先设计测试策略。
project:
name: ""
type: web-app | api | mobile | library | cli | data-pipeline
languages: [typescript, python, go, java]
frameworks: [react, express, django, spring]
risk_profile:
data_sensitivity: low | medium | high | critical # PII、金融、健康数据
user_impact: internal | b2b | b2c | life-safety
deployment_frequency: daily | weekly | monthly
regulatory: [none, SOC2, HIPAA, PCI-DSS, GDPR]
test_scope:
in_scope: [] # 功能、服务、组件
out_of_scope: [] # 明确排除项(附原因)
environments:
dev: { url: "", db: "local" }
staging: { url: "", db: "seeded" }
prod: { url: "", smoke_only: true }| 风险等级 | 单元测试 | 集成测试 | 端到端测试 | 性能测试 | 安全测试 | 可访问性测试 |
|---|---|---|---|---|---|---|
| 内部工具 | ✅ 核心 | ✅ API | ⚠️ 正常流程 | ❌ | ⚠️ 基础 | ❌ |
| B2B SaaS | ✅ 全面 | ✅ 全面 | ✅ 关键流程 | ✅ 负载测试 | ✅ OWASP Top 10 | ✅ WCAG AA |
| B2C 高流量应用 | ✅ 全面 | ✅ 全面 | ✅ 全面 | ✅ 压力+持续测试 | ✅ 全面 | ✅ WCAG AA |
| 金融/医疗系统 | ✅ 全面 + 变异测试 | ✅ 全面 + 合同测试 | ✅ 全面 + 混沌测试 | ✅ 全套测试 | ✅ 渗透测试 | ✅ WCAG AAA |
/ E2E \ 5-10% — 仅关键用户旅程
/ Integration \ 20-30% — API 合同、服务边界
/ Unit Tests \ 60-70% — 业务逻辑、纯函数反模式:冰淇淋锥形 — 端到端测试远多于单元测试。运行慢、易出错、成本高。应通过将测试覆盖率向下推至金字塔底层来修复。
反模式:沙漏形 — 单元测试和端到端测试多,但缺少集成测试。会遗漏服务间接口缺陷。
每个单元测试都遵循此结构:
describe('PricingCalculator', () => {
// 按行为分组,而非按方法
describe('当客户享有批量折扣时', () => {
it('在数量超过阈值时应用分级定价', () => {
// 准备 — 设置测试场景
const calculator = new PricingCalculator();
const customer = createCustomer({ tier: 'enterprise', units: 150 });
// 执行 — 执行待测行为
const price = calculator.calculate(customer);
// 断言 — 验证结果(单一逻辑断言)
expect(price).toEqual({
subtotal: 12000,
discount: 1800, // 15% 批量折扣
total: 10200,
});
});
});
});**格式:[被测单元] [场景描述] [预期行为]
✅ 优秀示例:
PricingCalculator 在数量超过 100 时应用 15% 折扣UserService 在用户 ID 无效时抛出 NotFoundErrorparseDate 对格式错误的 ISO 字符串返回 null❌ 不佳示例:
test1、should work、calculates pricecatch 块、每条验证路径| 依赖类型 | 策略 | 示例 |
|---|---|---|
| 数据库 | Mock Repository/DAO | jest.mock('./userRepo') |
| HTTP API | Mock 客户端或使用 MSW | msw.http.get('/api/users', ...) |
| 文件系统 | Mock fs 或使用临时目录 | jest.mock('fs/promises') |
| 时间/日期 | 使用虚假时间 | jest.useFakeTimers() |
| 随机性 | 固定种子或 mock | jest.spyOn(Math, 'random') |
| 环境变量 | 覆盖环境变量 | process.env.NODE_ENV = 'test' |
原则:在边界处 mock,而非内部。 如果你需要 mock 自己拥有的类,说明设计可能需要重构。
| 指标 | 最低要求 | 良好 | 优秀 |
|---|---|---|---|
| 行覆盖率 | 70% | 85% | 95%+ |
| 分支覆盖率 | 60% | 80% | 90%+ |
| 函数覆盖率 | 75% | 90% | 95%+ |
| 关键路径覆盖率 | 100% | 100% | 100% |
警告:100% 覆盖率 ≠ 质量。 覆盖率仅衡量代码执行了多少,不反映验证是否充分。没有断言的测试虽有覆盖率,但无实际价值。
对每个 API 接口,需测试:
endpoint: POST /api/orders
tests:
happy_path:
- 有效请求返回 201 状态码及订单 ID
- 响应符合 schema 定义
- 数据库记录正确创建
- 事件/消息队列已触发
validation:
- 缺少必填字段 → 返回 400 并附带字段错误信息
- 数据类型错误 → 返回 400 并附带类型错误信息
- 业务规则违反 → 返回 422 并附解释说明
authentication:
- 无 token → 返回 401
- token 过期 → 返回 401
- 权限不足 → 返回 403
- 有效 token → 继续执行
edge_cases:
- 重复请求(幂等性)→ 返回相同响应
- 并发请求 → 无竞态条件
- 请求体过大 → 返回 413 或优雅处理
- 输入含特殊字符 → 无注入风险
error_handling:
- 数据库宕机 → 返回 503 并提示重试建议
- 外部服务超时 → 返回 504 或启用降级方案
- 速率限制超限 → 返回 429 并附 retry-after 建议当服务之间通信时,应测试其合同一致性:
contract:
consumer: order-service
provider: payment-service
interactions:
- description: "处理支付"
request:
method: POST
path: /payments
body:
amount: 99.99
currency: USD
order_id: "ord_123"
response:
status: 200
body:
payment_id: "pay_xxx" # string, not null
status: "completed" # enum: completed|pending|failed
breaking_changes: # 永远不要在不版本化的情况下进行这些操作
- 从响应中移除字段
- 改变字段类型
- 在请求中添加必填字段
- 修改 URL 路径
- 改变错误响应格式createUser({ role: 'admin' }) 优于硬编码的 SQL 块识别并测试产生收入或阻碍用户的流程:
critical_journeys:
- name: "注册 → 首次价值体验"
steps:
- 访问首页
- 点击注册
- 填写注册表单
- 验证邮箱
- 完成引导流程
- 执行首次关键操作
max_duration: 3分钟
- name: "购买流程"
steps:
- 浏览商品
- 加入购物车
- 填写配送信息
- 填写支付信息
- 确认订单
- 接收确认邮件
max_duration: 2分钟
- name: "登录 → 核心任务 → 退出"
steps:
- 登录(密码 + SSO + MFA 变体)
- 导航至核心功能
- 完成主要工作流
- 验证结果
- 退出登录
max_duration: 1分钟waitFor(element) 而非 sleep(3000)getByRole('button', { name: '提交' }) — 可访问性强,稳定getByLabelText('邮箱') — 表单专用,可访问getByText('欢迎回来') — 内容驱动getByTestId('submit-btn') — 显式测试标记querySelector('.btn-primary') — ❌ 脆弱,易受样式变更影响| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 本地通过,CI 失败 | 时间或竞争条件 | 添加显式等待,检查 CI 资源限制 |
| 间歇性失败 | 测试间共享状态 | 隔离测试数据,重置状态 |
| 部署后失败 | 环境差异 | 检查环境变量、API 版本、功能开关 |
| 特定时间失败 | 依赖时间逻辑 | 模拟日期/时间,避免时间敏感断言 |
| 并行执行时失败 | 资源争用 | 每个测试工作进程使用独立端口/数据库 |
规则:24 小时内隔离不稳定测试。 一个被所有人忽视的不稳定测试套件,比没有测试更糟糕。
performance_tests:
smoke:
vus: 5
duration: 1m
purpose: "验证测试是否正常运行"
load:
vus: 100 # 预期并发用户数
duration: 10m
ramp_up: 2m
purpose: "模拟正常流量行为"
thresholds:
p95_response: <500ms
error_rate: <1%
stress:
vus: 300 # 预期负载的 3 倍
duration: 15m
ramp_up: 5m
purpose: "找出系统崩溃点"
soak:
vus: 80
duration: 2h
purpose: "检测内存泄漏、连接耗尽"
spike:
stages:
- { vus: 50, duration: 2m }
- { vus: 500, duration: 30s } # 突发流量
- { vus: 50, duration: 2m }
purpose: "评估系统恢复能力"| 指标 | Web 应用 | API | 后台任务 |
|---|---|---|---|
| 响应时间 (p50) | <200ms | <100ms | N/A |
| 响应时间 (p95) | <1s | <500ms | N/A |
| 响应时间 (p99) | <3s | <1s | N/A |
| 吞吐量 | >100 rps | >500 rps | >1000/min |
| 错误率 | <0.1% | <0.1% | <0.5% |
| CPU 使用率 | <70% | <70% | <90% |
| 内存增长 | <5%/小时 | <2%/小时 | <10%/小时 |
db_performance:
query_tests:
- name: "仪表盘聚合查询"
baseline: 50ms
max_acceptable: 200ms
with_1M_rows: measure
with_10M_rows: measure
index_verification:
- 对所有关键查询执行 EXPLAIN ANALYZE
- 确保表数据量 >10K 时无全表扫描
- 每周检查索引使用统计
connection_pool:
- 在最大连接数下测试
- 验证连接池耗尽时的优雅处理
- 监控连接等待时间security_tests:
A01_权限控制缺陷:
- [ ] 横向权限提升(访问其他用户的数据)
- [ ] 纵向权限提升(访问管理员功能)
- [ ] IDOR(不安全的直接对象引用)
- [ ] 缺失功能级访问控制
- [ ] CORS 配置错误
A02_加密失败:
- [ ] 传输中的敏感数据(需使用 TLS 1.2+)
- [ ] 静态存储的敏感数据(需加密)
- [ ] 密码哈希(应使用 bcrypt/argon2,而非 MD5/SHA)
- [ ] 代码、日志或 URL 中未泄露密钥
A03_注入攻击:
- [ ] SQL 注入(使用参数化查询)
- [ ] NoSQL 注入
- [ ] 命令注入(操作系统命令)
- [ ] XSS(存储型、反射型、DOM 基于)
- [ ] 模板注入(SSTI)
A04_不安全设计:
- [ ] 认证接口限流
- [ ] 多次失败后账户锁定
- [ ] 公共表单添加 CAPTCHA
- [ ] 业务逻辑滥用场景测试
A05_安全配置错误:
- [ ] 移除默认凭证
- [ ] 错误信息不泄露堆栈跟踪
- [ ] 设置安全头(CSP、HSTS、X-Frame-Options)
- [ ] 禁用目录列表
- [ ] 禁用不必要的 HTTP 方法
A07_认证失败:
- [ ] 防止暴力破解
- [ ] 会话固定漏洞
- [ ] 会话超时机制
- [ ] JWT 验证(签名、过期时间、签发者)
- [ ] 多因素认证绕过尝试对所有用户输入进行测试:
injection_payloads:
sql: ["' OR 1=1--", "'; DROP TABLE users;--", "1 UNION SELECT * FROM users"]
xss: ["<script>alert(1)</script>", "<img onerror=alert(1) src=x>", "javascript:alert(1)"]
path_traversal: ["../../etc/passwd", "..\\..\\windows\\system32", "%2e%2e%2f"]
command: ["; ls -la", "| cat /etc/passwd", "$(whoami)", "`id`"]
boundary_values:
strings: ["", " ", "a"*10000, null, undefined, "emoji: 🎯", "unicode: é à ü", "rtl: مرحبا"]
numbers: [0, -1, 2147483647, -2147483648, NaN, Infinity, 0.1+0.2]
arrays: [[], [null], Array(10000)]
dates: ["1970-01-01", "2099-12-31", "invalid-date", "2024-02-29", "2023-02-29"]| 需求 | JavaScript/TS | Python | Go | Java |
|---|---|---|---|---|
| 单元测试 | Vitest / Jest | pytest | testing + testify | JUnit 5 |
| API 测试 | Supertest | httpx + pytest | net/http/httptest | RestAssured |
| 端到端(浏览器) | Playwright | Playwright | chromedp | Selenium |
| 性能测试 | k6 | Locust | vegeta | Gatling |
| 合同测试 | Pact | Pact | Pact | Pact |
| 安全测试 | ZAP + 自定义 | Bandit + 自定义 | gosec | SpotBugs |
pipeline:
stage_1_fast: # <2 分钟,阻塞 PR
- 代码检查 + 类型检查
- 单元测试
- 安全:依赖扫描(npm audit / safety)
stage_2_thorough: # <10 分钟,阻塞合并
- 集成测试
- 合同测试
- 安全:SAST 扫描
- 覆盖率报告 + 阈值检查
stage_3_confidence: # <30 分钟,阻塞部署
- 关键流程端到端测试
- 视觉回归测试(如适用)
- 安全:容器扫描
stage_4_post_deploy: # 部署至预发布环境后
- 对预发布环境执行冒烟测试
- 性能基线检查
- 安全:DAST 扫描(ZAP)
stage_5_production: # 生产环境部署后
- 冒烟测试(仅关键路径)
- 启用合成监控
- 监控灰度发布指标test_data_strategy:
unit_tests:
approach: factories # 使用构建模式,仅创建所需数据
example: "createUser({ role: 'admin', plan: 'enterprise' })"
integration_tests:
approach: seeded_database
reset: per_test_suite # 通过事务回滚或清空表重置
sensitive_data: anonymized # 永远不要使用真实个人身份信息
e2e_tests:
approach: api_setup # 通过 API 创建测试数据
cleanup: after_each # 每次测试后删除创建的数据
isolation: unique_identifiers # 使用时间戳或 UUID 区分测试数据
performance_tests:
approach: representative_dataset
volume: 10x_production # 测试数据量为生产环境的 10 倍
generation: faker_libraries # 生成真实但虚构的数据metrics:
test_suite_health:
total_tests: 0
passing: 0
failing: 0
skipped: 0 # 跳过比例 >5% = 技术债务警报
flaky: 0 # 不稳定测试比例 >2% = 立即隔离处理
coverage:
line: "0%"
branch: "0%"
critical_paths: "0%" # 必须达到 100%
execution:
unit_duration: "0s" # 目标:<30 秒
integration_duration: "0s" # 目标:<5 分钟
e2e_duration: "0s" # 目标:<15 分钟
total_ci_time: "0s" # 目标:<20 分钟
defect_metrics:
bugs_found_in_test: 0
bugs_escaped_to_prod: 0
escape_rate: "0%" # 目标:<5%
mttr: "0h" # 平均修复时间
trends: # 按周追踪
new_tests_added: 0
tests_deleted: 0 # 健康的删除 = 移除冗余测试
coverage_delta: "+0%"
flake_rate_delta: "+0%"# 测试报告 — [功能/冲刺/发布]
## 概要
- **状态:** ✅ 通过 / ⚠️ 有风险通过 / ❌ 失败
- **测试数量:** X | **通过:** X | **失败:** X | **跳过:** X
- **覆盖率:** 行 X% | 分支 X% | 关键路径 100%
- **执行耗时:** Xm Xs
## 主要发现
### 🔴 严重(阻塞发布)
1. [发现问题] — [影响] — [修复建议]
### 🟡 高优先级(下个版本前修复)
1. [发现问题] — [影响] — [修复建议]
### 🟢 中等/低优先级(放入待办清单)
1. [发现问题] — [影响]
## 风险评估
- **未覆盖区域:** [列出]
- **已知不稳定测试:** [列出并附工单编号]
- **性能问题:** [如有]
## 建议
[发布 / 发布并监控 / 暂缓发布,等待修复]| 维度 | 权重 | 评分标准 |
|---|---|---|
| 测试覆盖率 | 20% | <60%=0,60-70%=5,70-80%=10,80-90%=15,90%+=20 |
| 关键路径覆盖率 | 20% | <100%=0,100%=20 |
| 缺陷逃逸率 | 15% | >10%=0,5-10%=5,2-5%=10,<2%=15 |
| 测试套件执行速度 | 10% | >30分钟=0,20-30分钟=3,10-20分钟=7,<10分钟=10 |
| 不稳定测试率(Flake Rate) | 10% | >5%=0,2-5%=3,1-2%=7,<1%=10 |
| 安全测试覆盖率 | 10% | 无=0,基础=3,OWASP Top 10=7,完整=10 |
| 文档完整性 | 5% | 无=0,基础=2,完整=5 |
| 自动化比率 | 10% | <50%=0,50-70%=3,70-90%=7,90%+=10 |
评分等级:
0-40 = 🔴 严重问题 | 41-60 = 🟡 需改进 | 61-80 = 🟢 良好 | 81-100 = 💎 优秀
accessibility_checklist:
level_a: # 最低合规要求
- [ ] 所有图片均有替代文本
- [ ] 所有表单输入项均有标签
- [ ] 颜色不是唯一的视觉提示方式
- [ ] 页面具备正确的标题层级(h1→h2→h3)
- [ ] 所有功能可通过键盘操作
- [ ] 焦点状态可见且逻辑清晰
- [ ] 无内容闪烁超过每秒3次
level_aa: # 标准合规(推荐)
- [ ] 文本颜色对比度 ≥4.5:1(普通文本)
- [ ] 文本颜色对比度 ≥3:1(大字号文本)
- [ ] 文本可缩放至200%而不会丢失内容
- [ ] 提供跳过导航链接
- [ ] 各页面间导航保持一致
- [ ] 错误提示提供建议
- [ ] 使用 ARIA 标记定义页面区域
tools:
- axe-core(自动化工具,可发现约30%的问题)
- Lighthouse 可访问性审计
- 手动键盘导航测试
- 屏幕阅读器测试(VoiceOver / NVDA)compatibility_tests:
when_updating_api:
- [ ] 所有原有字段在响应中仍存在
- [ ] 无字段类型变更(如 string → number)
- [ ] 新增必填请求字段需有默认值
- [ ] 已弃用字段仍可使用(附带警告头)
- [ ] 错误格式保持不变
- [ ] 分页行为保持一致
- [ ] 速率限制未降低
versioning_strategy:
- URL 版本控制:/v1/users,/v2/users
- Header 版本控制:Accept: application/vnd.api+json;version=2
- 使用 Sunset Header 标记已弃用版本
- 至少提前6个月发布弃用通知chaos_tests:
network:
- 服务依赖中断 → 是否实现优雅降级?
- 网络延迟增加10倍 → 超时处理是否正常?
- DNS 解析失败 → 是否具备备用行为?
infrastructure:
- 数据库主节点故障 → 是否成功提升从节点?
- 缓存(Redis)失效 → 是否能正确回退到数据库?
- 磁盘空间满 → 是否触发告警并支持优雅失败?
application:
- 内存压力 → 是否正确处理 OOM 情况?
- CPU 过载 → 是否启用请求排队机制?
- 证书过期 → 是否触发监控告警?
data:
- 消息队列中出现损坏消息 → 死信队列是否生效并发出告警?
- 模式迁移中途失败 → 回滚机制是否有效?
- 服务间时钟偏差 → 幂等性是否仍然成立?weekly_review:
monday:
- 审查不稳定测试隔离区 — 修复或删除
- 检查覆盖率趋势 — 下降表示技术债积累
- 审查已逃逸缺陷 — 更新测试策略
friday:
- 更新测试健康仪表盘
- 清理过时测试用例
- 记录本周发现的新测试模式
- 规划下周测试重点"为[项目/功能]创建测试策略" → 生成完整策略文档"为[函数/类]编写单元测试" → 使用 AAA 模式编写包含边界情况的测试"测试此 API 接口:[方法] [路径]" → 生成完整的 API 测试检查清单"评审这些测试的质量" → 提供测试代码审查及评分"生成性能测试计划" → 输出 k6/Locust 测试设计方案"对[功能/接口]进行安全测试" → 基于 OWASP 的测试检查清单"为[发布版本]生成测试报告" → 输出格式化的测试报告"我们当前的测试健康状况如何?" → 返回包含指标与改进建议的仪表盘"找出我们测试覆盖中的盲点" → 分析并提供优先级排序的改进建议"帮助调试这个不稳定的测试" → 根因分析并提供修复建议"设置 CI 测试流水线" → 输出分阶段的流水线配置方案"对[页面/组件]进行可访问性审计" → 输出 WCAG 检查清单及发现结果已收录 14 个 Skill