名称:特性测试生成器 描述:在迁移前生成特性测试以捕获和验证现有行为 允许工具:[“Bash”, “Read”, “Write”, “Grep”, “Glob”, “Edit”]
特性测试生成器技能
生成特性测试(也称为黄金主测试或批准测试),在迁移前捕获现有系统行为,确保更改后的功能等效性。
目的
通过以下方式实现迁移期间的行为保留:
- 黄金主测试创建
- 批准测试生成
- 边界情况发现
- 输入/输出记录
- 行为快照捕获
- 回归基线建立
能力
1. 黄金主测试创建
- 捕获给定输入的当前系统输出
- 将输出存储为参考“黄金”文件
- 生成比较测试基础设施
- 支持多种输出格式
- 支持基线版本控制
2. 批准测试生成
- 创建可人工审查的测试输出
- 生成基于差异的比较测试
- 支持批准工作流
- 支持增量批准
- 跟踪批准历史
3. 边界情况发现
- 分析边界条件的代码路径
- 生成边界值输入
- 识别错误处理场景
- 映射异常路径
- 创建全面的测试覆盖
4. 输入/输出记录
- 为I/O捕获检测代码
- 记录API请求/响应对
- 捕获数据库交互
- 记录外部服务调用
- 存储时序和序列数据
5. 行为快照
- 在关键点捕获状态
- 记录副作用
- 记录非确定性行为
- 识别环境依赖
- 映射配置影响
6. 回归基线建立
- 创建基线测试套件
- 定义验收阈值
- 配置容差级别
- 设置CI/CD集成
- 生成覆盖率报告
工具集成
当可用时,此技能可以利用以下外部工具:
| 工具 | 目的 | 集成方法 |
|---|---|---|
| ApprovalTests | 批准测试框架 | 库 |
| Jest snapshots | JavaScript快照测试 | 框架 |
| pytest-snapshot | Python快照测试 | 插件 |
| TextTest | 黄金主测试 | CLI |
| Verify | .NET批准测试 | 库 |
| Scientist | 安全重构库 | 库 |
| AI Testing MCP | AI驱动的测试生成 | MCP服务器 |
使用方法
基本测试生成
# 调用技能进行特性测试生成
# 技能将分析代码并生成测试
# 预期输入:
# - targetPath:要特性化的代码路径
# - testFramework:'jest' | 'pytest' | 'junit' | 'nunit' | 'auto'
# - outputDir:生成测试的目录
# - captureMode:'snapshot' | 'approval' | 'recording'
生成工作流
-
分析阶段
- 识别可测试单元(函数、方法、端点)
- 映射输入参数和类型
- 检测输出格式
- 查找外部依赖
-
输入发现阶段
- 提取现有测试输入
- 生成边界值
- 识别代表性案例
- 创建组合输入
-
捕获阶段
- 使用输入执行代码
- 记录输出和副作用
- 捕获状态变化
- 记录外部交互
-
测试生成阶段
- 生成测试代码结构
- 创建黄金主文件
- 设置比较逻辑
- 配置CI集成
输出模式
{
"generationId": "字符串",
"timestamp": "ISO8601",
"target": {
"path": "字符串",
"language": "字符串",
"framework": "字符串",
"unitsAnalyzed": "数字"
},
"testsGenerated": {
"total": "数字",
"byType": {
"snapshot": "数字",
"approval": "数字",
"recording": "数字"
},
"coverage": {
"functions": "数字",
"branches": "数字",
"lines": "数字"
}
},
"characterizations": [
{
"unit": "字符串",
"type": "function|method|endpoint|class",
"inputs": [
{
"name": "字符串",
"type": "字符串",
"values": ["任意"],
"source": "existing|generated|boundary"
}
],
"outputs": {
"type": "字符串",
"goldenMasterPath": "字符串",
"checksum": "字符串"
},
"testFile": "字符串",
"baselineApproved": "布尔值"
}
],
"edgeCases": [
{
"unit": "字符串",
"case": "字符串",
"input": "任意",
"expectedBehavior": "字符串",
"covered": "布尔值"
}
],
"dependencies": {
"external": ["字符串"],
"mocked": ["字符串"],
"recorded": ["字符串"]
},
"artifacts": {
"testSuite": "字符串",
"goldenMasters": "字符串",
"recordings": "字符串",
"coverageReport": "字符串"
}
}
与迁移过程的集成
此技能与以下代码迁移/现代化过程集成:
- migration-testing-strategy:测试基线创建的主要工具
- code-refactoring:确保重构期间的行为保留
- framework-upgrade:升级后验证功能
- monolith-to-microservices:验证服务提取
配置
技能配置文件
在项目根目录创建.characterization-tests.json:
{
"testFramework": "auto",
"outputDir": "./tests/characterization",
"captureMode": "snapshot",
"goldenMasterDir": "./tests/golden-masters",
"inputGeneration": {
"boundary": true,
"combinatorial": true,
"maxCombinations": 100,
"includeNulls": true,
"includeEmpty": true
},
"outputCapture": {
"format": "json",
"normalizeWhitespace": true,
"ignorePaths": ["$.timestamp", "$.requestId"],
"tolerance": {
"numeric": 0.001,
"dateTime": "1s"
}
},
"dependencies": {
"mockExternal": true,
"recordMode": false,
"replayMode": true
},
"approval": {
"requireApproval": true,
"approvalDir": "./tests/approvals",
"reportFormat": "markdown"
},
"ci": {
"failOnNewTests": false,
"updateGoldenOnPass": false,
"generateCoverageReport": true
}
}
MCP服务器集成
当AI测试MCP服务器可用时:
// AI驱动的测试生成示例
{
"tool": "ai_testing_generate",
"arguments": {
"target": "./src/services/user.ts",
"framework": "jest",
"style": "characterization"
}
}
测试模式
快照测试(Jest)
// 生成的特性测试
describe('UserService', () => {
describe('calculateDiscount', () => {
it('应为标准客户匹配快照', () => {
const result = userService.calculateDiscount({
customerId: 'C001',
purchaseAmount: 100,
loyaltyPoints: 500
});
expect(result).toMatchSnapshot();
});
it('应为高级客户匹配快照', () => {
const result = userService.calculateDiscount({
customerId: 'C002',
purchaseAmount: 100,
loyaltyPoints: 5000,
isPremium: true
});
expect(result).toMatchSnapshot();
});
// 边界情况
it('应为零金额匹配快照', () => {
const result = userService.calculateDiscount({
customerId: 'C001',
purchaseAmount: 0,
loyaltyPoints: 0
});
expect(result).toMatchSnapshot();
});
});
});
批准测试(ApprovalTests)
// 生成的批准测试
public class UserServiceCharacterizationTest {
@Test
public void calculateDiscount_standardCustomer() {
UserService service = new UserService();
DiscountResult result = service.calculateDiscount(
new DiscountRequest("C001", 100.0, 500)
);
Approvals.verify(result);
}
@Test
public void calculateDiscount_boundaryValues() {
UserService service = new UserService();
// 边界:最小值
Approvals.verify(service.calculateDiscount(
new DiscountRequest("C001", 0.01, 0)
), "minimum");
// 边界:最大值
Approvals.verify(service.calculateDiscount(
new DiscountRequest("C001", 999999.99, 999999)
), "maximum");
}
}
记录测试(Python)
# 生成的基于记录的测试
import pytest
from tests.recordings import PlaybackRecorder
class TestUserServiceCharacterization:
@pytest.fixture
def recorder(self):
return PlaybackRecorder('tests/recordings/user_service')
def test_get_user_profile_recorded(self, recorder):
"""重放记录的外部API交互"""
with recorder.playback('get_user_profile_c001'):
service = UserService()
result = service.get_user_profile('C001')
assert result == recorder.expected_output()
def test_update_user_settings_recorded(self, recorder):
"""验证数据库交互是否匹配记录"""
with recorder.playback('update_settings_c001'):
service = UserService()
result = service.update_settings('C001', {'theme': 'dark'})
recorder.verify_database_calls()
assert result == recorder.expected_output()
边界情况类别
边界值
- 最小/最大值
- 零值
- 空字符串/数组
- Null/undefined值
- 类型边界(INT_MAX等)
错误条件
- 无效输入
- 缺少必填字段
- 类型不匹配
- 约束违规
- 身份验证失败
并发场景
- 竞争条件
- 死锁
- 超时场景
- 部分失败
- 重试行为
环境相关
- 配置变化
- 时区差异
- 区域设置变化
- 功能标志状态
- 权限级别
最佳实践
- 在更改前开始:在任何迁移工作之前生成特性测试
- 捕获所有内容:记录所有输出、副作用和状态变化
- 版本化黄金主文件:在版本控制中存储黄金主文件
- 审查批准:初始黄金主文件的人工审查至关重要
- 处理非确定性:规范化时间戳、ID和随机值
- 增量更新:随着更改被批准,增量更新基线
- CI集成:在意外行为变化时使构建失败
相关技能
test-coverage-analyzer:分析覆盖差距migration-validator:验证迁移结果static-code-analyzer:识别可测试代码路径
相关代理
migration-testing-strategist:使用此技能进行测试策略regression-detector:使用此技能进行回归检测parallel-run-validator:使用此技能进行比较测试