name: 组件感知测试缺口分析 description: 基于组件类型智能识别缺失的测试覆盖
组件感知测试缺口分析技能
这个技能自动检测组件类型(网络、存储、API等),并提供基于上下文的缺口分析。它分析端到端测试文件,以识别针对被测试组件的缺失测试覆盖。
何时使用此技能
在以下情况下使用此技能:
- 自动检测组件类型,从测试文件路径和内容中检测
- 组件特定的缺口分析:
- 网络组件:识别缺失的协议测试(TCP、UDP、SCTP)、服务类型覆盖、IP栈测试
- 存储组件:找出存储类覆盖的缺口、卷模式测试、提供程序测试
- 通用组件:分析其他组件的平台覆盖和常见场景
- 始终分析:云平台覆盖(AWS、Azure、GCP等)和场景测试(错误处理、升级、RBAC、规模)
- 基于组件特定的生产重要性,优先排序测试工作
- 生成全面的组件感知缺口分析报告
⚠️ 关键要求
此技能必须在运行时生成所有三种报告格式(HTML、JSON和文本)。
缺口分析脚本(在运行时生成到.work/test-coverage/gaps/gap_analyzer.py)执行分析并返回结构化数据。Claude Code负责基于此数据生成所有三种报告格式。
必需操作:
- ✅ 执行:
python3 .work/test-coverage/gaps/gap_analyzer.py <test-file> --output-json(输出结构化JSON到标准输出) - ✅ 生成:在运行时创建所有三种报告文件(HTML、JSON、文本)
- ✅ 验证:所有三种报告成功生成
- ✅ 显示:向用户显示报告位置和摘要
如果未能生成任何三种报告格式,应视为技能执行失败。
前提条件
必需工具
- Python 3.8+ 用于测试结构分析
- Go工具链 用于目标项目
安装
# Python依赖(仅标准库,无需外部包)
# 确保安装了Python 3.8+
# 可选的Go分析工具
go install golang.org/x/tools/cmd/guru@latest
go install golang.org/x/tools/cmd/goimports@latest
工作原理
注意:此技能目前支持用Go(Ginkgo框架)编写的OpenShift/Kubernetes组件的E2E/集成测试文件。
当前实现
分析器执行单测试文件分析,包含两个分析层:
-
通用覆盖分析(基于关键字)
- 平台、协议、IP栈、服务类型
- 使用正则表达式模式匹配文件内容
-
基于特征的分析(运行时提取)
- 从测试名称中动态提取特征
- 基于模式推断缺失特征
- 无需硬编码特征矩阵——适用于任何组件
它不执行存储库遍历、Go AST解析或测试到源代码映射。
分析流程
步骤1:组件类型检测
分析器自动检测组件类型,基于:
-
文件路径模式:
/networking/→ 网络组件/storage/→ 存储组件/kapi/、/api/→ kube-api组件/etcd/→ etcd组件/auth/、/rbac/→ 认证组件
-
文件内容模式:
- 关键字如
sig-networking、networkpolicy、egressip→ 网络 - 关键字如
sig-storage、persistentvolume→ 存储 - 关键字如
sig-api、apiserver→ kube-api
- 关键字如
步骤2:提取测试用例
使用正则表达式解析测试文件,提取:
- 测试名称,从Ginkgo
g.It("测试名称")模式中提取 - 行号,定义测试的位置
- 测试标签,如
[Serial]、[Disruptive]、[NonPreRelease] - 测试ID,从测试名称中的模式如
-12345-提取
示例:
g.It("egressip-12345-should work on AWS [Serial]", func() {
// 测试实现
})
提取:
- 名称:
egressip-12345-should work on AWS [Serial] - ID:
12345 - 标签:
[Serial] - 行:42
步骤3:使用正则分析覆盖
对于每种组件类型,分析器搜索文件内容中的特定关键字,以确定已测试的内容:
网络组件:
- 平台:
vsphere、AWS、azure、GCP、baremetal - 协议:
TCP、UDP、SCTP - 服务类型:
NodePort、LoadBalancer、ClusterIP - 场景:
invalid、upgrade、concurrent、performance、rbac
存储组件:
- 平台:
vsphere、AWS、azure、GCP、baremetal - 存储类:
gp2、gp3、csi - 卷模式:
ReadWriteOnce、ReadWriteMany、ReadOnlyMany - 场景:
invalid、upgrade、concurrent、performance、rbac
其他组件:
- 平台:
vsphere、AWS、azure、GCP、baremetal - 场景:
invalid、upgrade、concurrent、performance、rbac
步骤4:识别缺口
对于每个覆盖维度,如果关键字在文件中未找到,则标记为缺口:
示例:
# 如果文件内容不包含"azure"(不区分大小写)
gaps.append({
'platform': 'Azure',
'priority': 'high',
'impact': '主要云提供商——生产阻塞项',
'recommendation': '添加Azure平台特定测试'
})
步骤5:计算组件感知覆盖分数
分数是组件特定的,以避免因不相关指标惩罚组件:
网络组件:
- 总体 = 平均(平台分数、协议分数、服务类型分数、场景分数)
存储组件:
- 总体 = 平均(平台分数、存储类分数、卷模式分数、场景分数)
其他组件:
- 总体 = 平均(平台分数、场景分数)
每个维度分数 = (找到的项目 / 总项目) × 100
步骤5a:动态特征提取(运行时分析)
除了上述基于关键字的覆盖分析外,分析器还执行动态特征提取,以从测试名称中在运行时识别组件特定特征,无需任何硬编码特征矩阵。
运行时特征提取如何工作:
-
从测试名称中提取特征
解析测试名称以识别被测试的特征:
示例测试名称:
"Validate egressIP with mixed of multiple non-overlapping UDNs and default network(layer3/2 and IPv4 only)"提取的特征:
- ✓ 非重叠配置
- ✓ 多资源配置
- ✓ 混合配置
- ✓ 用户定义网络(UDN)
- ✓ 默认网络
- ✓ 第3层网络
-
将特征分组到类别中
特征自动分类:
- 配置模式:重叠、非重叠、单一、多个、混合
- 网络拓扑:UDN、默认网络、层2、层3、网关模式
- 生命周期操作:创建、删除、重建、分配
- 网络特性:故障转移、负载均衡、隔离
- 恢复力与恢复:重启、重新启动、节点删除
-
推断缺失特征
基于模式,推断缺失内容:
- 相反模式:如果测试了“重叠”→建议“非重叠”
- 单一与多个:如果测试了“单一资源”→建议“多资源”
- 完整性:如果测试了“删除”→建议“重建”
- 层覆盖:如果测试了“层2”→建议“层3”
运行时特征提取的好处:
✅ 无硬编码——无需配置即可适用于任何组件 ✅ 智能缺口检测——基于模式推断缺失特征 ✅ 组件无关——自动适应任何组件类型 ✅ 始终最新——从实际测试名称中提取,而非假设特征
示例:EgressIP测试分析
输入(测试名称):
1. Validate egressIP with mixed of multiple non-overlapping UDNs
2. Validate egressIP with mixed of multiple overlapping UDNs
3. Validate egressIP Failover with UDNs
4. egressIP after UDN deleted then recreated
5. egressIP after OVNK restarted
6. Traffic is load balanced between egress nodes
输出(提取的特征):
配置模式:
✓ 非重叠配置
✓ 重叠配置
✓ 多资源配置
✓ 混合配置
网络拓扑:
✓ 用户定义网络(UDN)
生命周期操作:
✓ 资源删除
✓ 资源重建
网络特性:
✓ 故障转移
✓ 负载均衡
恢复力与恢复:
✓ OVN-Kubernetes重启
输出(推断的特征缺口):
[高] 单一资源配置
- 模式显示测试了“多个”但未测试“单一”
- 建议:添加单一资源基线测试
[高] 第2层网络
- 测试了第3层但缺失第2层
- 建议:添加第2层网络拓扑测试
[中] 本地网关模式
- 提到了网关模式但本地与共享不明确
- 建议:添加显式网关模式测试
在gap_analyzer.py中的集成:
动态特征提取器内置在分析器中(无需单独导入):
# 提取测试用例后
feature_analysis = extract_features_from_tests(test_cases)
# 结果包含在分析输出中
tested_features = feature_analysis['tested_features']
# {'配置模式': ['重叠', '非重叠', ...],
# '网络拓扑': ['UDN', '第3层', ...]}
feature_gaps = feature_analysis['feature_gaps']
# [{'feature': '多资源', 'priority': 'high', ...}]
coverage_stats = feature_analysis['coverage_stats']
# {'features_tested': 14, 'features_missing': 5}
报告集成:
特征分析包含在所有三种报告格式中:
- HTML报告:带有已测试/缺失特征的特征部分
- 文本报告:按类别分组特征列表
- JSON报告:用于CI/CD集成的结构化特征数据
限制
当前实现有以下限制:
❌ 无存储库遍历——仅分析作为输入提供的单测试文件 ❌ 无Go AST解析——使用正则表达式模式匹配而非解析Go语法树 ❌ 无测试到源代码映射——无法映射测试函数到源代码函数 ❌ 无函数级覆盖——无法确定哪些源函数被测试 ❌ 无项目范围分析——无法分析多个测试文件或聚合结果 ❌ 仅基于关键字检测——缺口检测依赖于测试文件中关键字的存在 ❌ 单文件焦点——报告仅覆盖被分析的测试文件,而非整个代码库
这些限制意味着分析器为单E2E测试文件提供场景和平台覆盖分析,而非跨代码库的结构化代码覆盖。
步骤6:生成报告
分析器生成三种报告格式。您应在运行时生成Python代码来创建这些报告。
1. HTML缺口报告(test-gaps-report.html)
目的: 用于可视化缺口分析的交互式、可过滤HTML报告,带有专业样式
HTML文档结构:
生成完整的HTML5文档,结构如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test Coverage Gap Analysis - {filename}</title>
<style>
/* 在此处内联所有CSS样式——见下面的CSS样式部分 */
</style>
</head>
<body>
<div class="container">
<!-- 内容部分 -->
</div>
<script>
/* 用于缺口过滤的JavaScript——见下面的JavaScript部分 */
</script>
</body>
</html>
CSS样式(内联在<style>标签中):
生成全面的CSS,包含以下样式规则:
-
重置和基础样式:
*:box-sizing: border-box, margin: 0, padding: 0body:font-family: -apple-system, BlinkMacSystemFont, ‘Segoe UI’, Roboto, sans-serif; line-height: 1.6; color: #333; background: #f5f5f5; padding: 20px
-
容器和布局:
.container:max-width: 1400px, margin: 0 auto, background: white, padding: 30px, border-radius: 8px, box-shadow: 0 2px 10px rgba(0,0,0,0.1)h1:color: #2c3e50, margin-bottom: 10px, font-size: 2emh2:color: #34495e, margin-top: 30px, margin-bottom: 15px, padding-bottom: 10px, border-bottom: 2px solid #e74c3c, font-size: 1.5emh3:color: #34495e, margin-top: 20px, margin-bottom: 10px, font-size: 1.2em
-
元数据部分:
.metadata:background: #ecf0f1, padding: 15px, border-radius: 5px, margin-bottom: 25px.metadata p:margin: 5px 0
-
分数卡片:
.score-grid:display: grid, grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)), gap: 15px, margin: 20px 0.score-card:padding: 20px, border-radius: 8px, text-align: center, color: white.score-card.excellent:background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%)(分数 >= 80).score-card.good:background: linear-gradient(135deg, #3498db 0%, #2980b9 100%)(分数 >= 60).score-card.fair:background: linear-gradient(135deg, #f39c12 0%, #e67e22 100%)(分数 >= 40).score-card.poor:background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%)(分数 < 40).score-card .number:font-size: 2.5em, font-weight: bold, margin: 10px 0.score-card .label:font-size: 0.9em, opacity: 0.9
-
缺口卡片:
.gap-card:background: #fff, border-left: 4px solid #e74c3c, padding: 20px, margin: 15px 0, border-radius: 5px, box-shadow: 0 2px 5px rgba(0,0,0,0.1).gap-card.high:border-left-color: #e74c3c.gap-card.medium:border-left-color: #f39c12.gap-card.low:border-left-color: #3498db.gap-card h4:color: #2c3e50, margin-bottom: 10px, font-size: 1.1em.gap-card .gap-id:font-family: “Courier New”, monospace, font-size: 0.85em, color: #7f8c8d, margin-bottom: 5px.priority:display: inline-block, padding: 4px 12px, border-radius: 12px, font-size: 0.75em, font-weight: bold, margin-right: 8px.priority.high:background: #e74c3c, color: white.priority.medium:background: #f39c12, color: white.priority.low:background: #3498db, color: white.gap-card .impact:background: #fff3cd, border-left: 3px solid #ffc107, padding: 10px, margin: 10px 0, border-radius: 3px.gap-card .recommendation:background: #d4edda, border-left: 3px solid #28a745, padding: 10px, margin: 10px 0, border-radius: 3px
-
表格:
table:width: 100%, border-collapse: collapse, margin: 20px 0th, td:padding: 12px, text-align: left, border-bottom: 1px solid #dddth:background: #34495e, color: white, font-weight: 600tr:hover:background: #f5f5f5.tested:background: #d4edda, color: #155724, font-weight: bold, text-align: center.not-tested:background: #f8d7da, color: #721c24, font-weight: bold, text-align: center
-
摘要框:
.summary-box:background: #e3f2fd, border-left: 4px solid #2196f3, padding: 15px, margin: 20px 0, border-radius: 5px.warning-box:background: #fff3cd, border-left: 4px solid #ffc107, padding: 15px, margin: 20px 0, border-radius: 5px.success-box:background: #d4edda, border-left: 4px solid #28a745, padding: 15px, margin: 20px 0, border-radius: 5px
-
过滤按钮:
.filter-buttons:margin: 20px 0.filter-btn:padding: 10px 20px, margin-right: 10px, border: none, border-radius: 5px, cursor: pointer, font-weight: bold.filter-btn.active:box-shadow: 0 0 0 3px rgba(0,0,0,0.2).filter-btn.all:background: #95a5a6, color: white.filter-btn.high:background: #e74c3c, color: white.filter-btn.medium:background: #f39c12, color: white.filter-btn.low:background: #3498db, color: white
HTML内容部分:
-
元数据部分:
<div class="metadata"> <p><strong>文件:</strong> <code>{转义文件名}</code></p> <p><strong>路径:</strong> <code>{转义文件路径}</code></p> <p><strong>组件:</strong> {转义组件标题}</p> <p><strong>分析日期:</strong> {YYYY-MM-DD}</p> <p><strong>总测试用例:</strong> {计数}</p> </div> -
覆盖分数部分:
- 在网格中显示分数卡片
- 动态显示基于组件计算的分数
- 分数显示顺序和标签:
SCORE_DISPLAY = { 'overall': {'order': 1, 'label': '总体覆盖'}, 'platform_coverage': {'order': 2, 'label': '平台覆盖'}, 'ip_stack_coverage': {'order': 3, 'label': 'IP栈覆盖'}, 'topology_coverage': {'order': 4, 'label': '拓扑覆盖'}, 'network_layer_coverage': {'order': 5, 'label': '网络层覆盖'}, 'gateway_mode_coverage': {'order': 6, 'label': '网关模式覆盖'}, 'protocol_coverage': {'order': 5, 'label': '协议覆盖'}, 'service_type_coverage': {'order': 6, 'label': '服务类型覆盖'}, 'storage_class_coverage': {'order': 7, 'label': '存储类覆盖'}, 'volume_mode_coverage': {'order': 8, 'label': '卷模式覆盖'}, 'scenario_coverage': {'order': 99, 'label': '场景覆盖'}, } - 按顺序排序分数,仅渲染非零/非空分数
- 基于分数值应用CSS类:
get_score_class(score) - 如果总体<60%,添加警告框显示关键发现
-
已测试内容部分:
- 生成表格显示已测试与未测试项目
- 对于网络组件:平台、协议、服务类型、IP栈、拓扑、场景
- 对于存储组件:平台、存储类、卷模式、场景
- 对于其他组件:仅平台、场景
- 表格格式:
<table> <tr> <th>项目</th> <th>状态</th> </tr> <tr> <td>AWS</td> <td class="tested">✓ 已测试</td> </tr> </table>
-
覆盖缺口部分:
- 摘要框显示按优先级计数的缺口
- 过滤按钮用于所有/高/中/低优先级
- 缺口卡片带有data-priority属性用于过滤:
<div class="gap-card {优先级}" data-priority="{优先级}"> <div class="gap-id">GAP-{001}</div> <h4> <span class="priority {优先级}">{优先级} 优先级</span> <span class="category">{类别}</span> {缺口名称} </h4> <div class="impact"><strong>影响:</strong> {影响描述}</div> <div class="recommendation"><strong>建议:</strong> {建议文本}</div> </div> - 分配顺序GAP ID:GAP-001、GAP-002等
- 按优先级排序缺口(高、中、低)
-
建议部分:
- 成功框列出前5个高优先级缺口
- 立即行动的要点列表
用于过滤的JavaScript(内联在<script>标签中):
function filterGaps(priority) {
const cards = document.querySelectorAll('.gap-card');
const buttons = document.querySelectorAll('.filter-btn');
buttons.forEach(btn => btn.classList.remove('active'));
document.querySelector(`.filter-btn.${priority}`).classList.add('active');
cards.forEach(card => {
if (priority === 'all' || card.dataset.priority === priority) {
card.style.display = 'block';
} else {
card.style.display = 'none';
}
});
}
安全要求:
- 对所有用户提供的内容(文件名、测试名称、缺口描述)使用
html.escape() - 净化优先级值,仅允许:‘high’、‘medium’、‘low’
- 切勿从分析数据中注入原始HTML
需要实现的辅助函数:
-
get_score_class(score):- score >= 80:返回’excellent’
- score >= 60:返回’good’
- score >= 40:返回’fair’
- 其他:返回’poor’
-
使用
from html import escape转义所有字符串
组件特定行为:
-
网络组件(网络、路由器、DNS、网络可观测性):
- 显示:平台、协议、服务类型、IP栈、拓扑、网络层、网关模式、场景
-
存储组件(存储、CSI):
- 显示:平台、存储类、卷模式、卷、CSI驱动、快照、场景
-
其他组件:
- 显示:仅平台、场景
2. JSON报告(test-gaps-report.json)
生成者: Claude Code在运行时基于分析器输出生成
目的: 用于CI/CD集成的机器可读格式
结构:
{
"analysis": {
"file": "path/to/test/file.go",
"component_type": "networking",
"test_count": 15,
"test_cases": [
{
"name": "test name",
"line": 42,
"id": "12345",
"tags": ["Serial", "Disruptive"]
}
],
"coverage": {
"platforms": {
"tested": ["AWS", "GCP"],
"not_tested": ["Azure", "vSphere", "Bare Metal"]
},
"protocols": {
"tested": ["TCP"],
"not_tested": ["UDP", "SCTP"]
}
},
"gaps": {
"platforms": [
{
"platform": "Azure",
"priority": "high",
"impact": "主要云提供商",
"recommendation": "添加Azure测试"
}
],
"protocols": [],
"scenarios": []
}
},
"scores": {
"overall": 45.0,
"platform_coverage": 33.3,
"protocol_coverage": 33.3,
"scenario_coverage": 40.0
},
"generated_at": "2025-11-10T10:00:00Z"
}
实现: 使用json.dump(),indent=2可读输出
3. 文本摘要(test-gaps-summary.txt)
生成者: Claude Code在运行时基于分析器输出生成
目的: 终端友好摘要,用于快速查看
格式结构:
============================================================
测试覆盖缺口分析
============================================================
文件:{文件名}
组件:{组件类型}
测试用例:{计数}
分析日期:{时间戳}
============================================================
覆盖分数
============================================================
总体覆盖: {分数}%
平台覆盖: {分数}%
[基于组件类型的特定分数]
场景覆盖: {分数}%
============================================================
已测试内容
============================================================
平台:
✓ {平台1}
✓ {平台2}
[基于组件类型的其他已测试项目]
============================================================
识别的缺口
============================================================
平台缺口:
[优先级] {平台}
影响:{影响}
建议:{建议}
[基于组件类型的其他缺口部分]
============================================================
建议
============================================================
当前覆盖:{当前}%
目标覆盖:{目标}%
首先专注于解决高优先级缺口,以最大化测试覆盖并确保生产就绪性。
组件特定部分:
- 网络组件:包括协议、服务类型、IP栈、拓扑缺口
- 存储组件:包括存储类、卷模式缺口
- 其他组件:仅包括平台和场景缺口
实现: 使用' '.join(lines)构建文本内容
实施步骤
在命令中实施此技能时:
步骤0:在运行时生成分析器脚本
关键: 在运行任何分析之前,从参考实现生成分析器脚本。
# 创建输出目录
mkdir -p .work/test-coverage/gaps/
# 根据下面的分析器规范生成分析器脚本
# Claude Code将基于分析器规范部分编写gap_analyzer.py
分析器规范:
生成Python脚本(gap_analyzer.py),执行组件感知E2E测试缺口分析:
输入: Go测试文件(Ginkgo框架)的路径或URL 输出: 标准输出中的JSON,包含分析结果和覆盖分数
核心算法:
-
输入处理(处理URL和本地路径):
- 检查输入是否以
http://或https://开头 - 如果是URL:使用
urllib.request.urlopen()获取内容,保存到临时文件 - 如果是本地路径:直接使用
- 分析后:清理创建的临时文件(如果存在)
- 检查输入是否以
-
组件检测(从文件路径/内容自动检测):
- 网络:
/networking/、egressip、networkpolicy→ component_type=‘networking’ - 存储:
/storage/、persistentvolume→ component_type=‘storage’ - 其他组件:etcd、apiserver、mco、operators等
- 网络:
-
测试提取(基于正则表达式):
- 模式:
(?:g\.|o\.)?It\(\s*["']([^"']+)["'] - 提取:测试名称、行号、标签([Serial]、[Disruptive])、测试ID(模式:
-\d+-)
- 模式:
-
覆盖分析(在文件内容中搜索关键字):
- 平台:搜索
aws|azure|gcp|vsphere|baremetal|rosa(不区分大小写) - 协议:搜索
\bTCP\b、\bUDP\b、\bSCTP\b、curl|wget|http(通过HTTP的TCP) - IP栈:搜索
ipv4、ipv6、dualstack - 服务类型:搜索
NodePort、LoadBalancer、ClusterIP - 网络层(仅网络):
layer2|l2、layer3|l3、default network - 网关模式(仅网络):
- 搜索
local.gateway|lgw→ 如果找到,本地网关已测试 - 共享网关是OVN-K的默认:如果测试存在但未找到本地网关模式 → 共享网关已测试
- 如果无测试存在 → 均未测试
- 搜索
- 拓扑:
sno|single-node、multi-node|HA cluster、hypershift|hcp,检查NonHyperShiftHOST标签 - 场景:
failover、reboot、restart、delete、invalid、upgrade、concurrent、performance、rbac、traffic disruption
- 平台:搜索
-
缺口识别:
- 对于每个类别,未找到的项目 = 缺口
- 分配优先级:高(生产关键)、中(重要)、低(锦上添花)
- 平台缺口:Azure/GCP/AWS = 高,vSphere/裸金属 = 中
- 协议缺口:UDP = 高,SCTP = 中,TCP非HTTP = 低
- 服务类型缺口:LoadBalancer = 高,其他 = 中
- 场景缺口:错误处理 = 高,流量中断 = 高(仅网络)
-
覆盖评分(组件感知):
- 网络:平均(平台、协议、服务类型、IP栈、网络层、网关模式、拓扑、场景)
- 存储:平均(平台、存储类、卷模式、场景)
- 其他:平均(平台、场景)
- 每个维度:(测试计数 / 总计数) × 100
-
输出格式(标准输出JSON):
{
"analysis": {
"file": "/path/to/test.go",
"component_type": "networking",
"test_count": 15,
"test_cases": [...],
"coverage": {
"platforms": {"tested": [...], "not_tested": [...]},
"protocols": {"tested": [...], "not_tested": [...]},
...
},
"gaps": {
"platforms": [{"platform": "Azure", "priority": "high", "impact": "...", "recommendation": "..."}],
...
}
},
"scores": {
"overall": 62.0,
"platform_coverage": 100.0,
...
}
}
为什么运行时生成:
- Claude Code从此规范生成分析器
- 无需维护单独的
.py文件 - SKILL.md是单一事实来源
- Claude Code擅长从规范生成代码
步骤1:执行缺口分析器脚本(必选)
执行缺口分析器脚本以执行分析并返回结构化数据:
# 运行缺口分析器(输出结构化JSON到标准输出)
python3 .work/test-coverage/gaps/gap_analyzer.py <test-file-path> --output-json
分析器将输出结构化JSON到标准输出,包含:
- 组件类型检测
- 测试用例提取
- 覆盖分析
- 缺口识别
- 优先级评分
- 组件特定建议
重要: 不要跳过此步骤。不要尝试手动分析。脚本是权威实现。
步骤2:捕获和解析分析器输出
import json
import subprocess
# 运行分析器并捕获JSON输出
result = subprocess.run(
['python3', '.work/test-coverage/gaps/gap_analyzer.py', test_file, '--output-json'],
capture_output=True,
text=True
)
# 解析结构化数据
analysis_data = json.loads(result.stdout)
步骤3:在运行时生成所有三种报告格式(必选)
重要: Claude Code基于分析器的结构化输出生成所有三种报告格式。
3.1:生成JSON报告
json_path = '.work/test-coverage/gaps/test-gaps-report.json'
with open(json_path, 'w') as f:
json.dump(analysis_data, f, indent=2)
3.2:生成文本摘要报告
遵循步骤6中的文本格式规范生成终端友好摘要。
text_path = '.work/test-coverage/gaps/test-gaps-summary.txt'
# 生成文本内容,遵循步骤6中的格式
with open(text_path, 'w') as f:
f.write(text_content)
3.3:生成HTML报告
遵循步骤6中的HTML规范生成交互式报告。
html_path = '.work/test-coverage/gaps/test-gaps-report.html'
# 生成HTML内容,遵循步骤6中的规范
# 包括所有CSS样式、JavaScript过滤和组件特定部分
with open(html_path, 'w') as f:
f.write(html_content)
关键要求:
- 生成HTML,遵循上面“步骤6:生成报告”中的确切结构
- 在
<style>标签中内联所有CSS样式 - 在
<script>标签中包括JavaScript过滤函数 - 使用
html.escape()转义所有用户提供的内容 - 基于组件类型应用组件特定部分
步骤4:显示结果
生成所有三种报告后,向用户显示结果:
# 显示摘要(从文本报告或analysis_data)
print(f"检测到的组件:{analysis_data['analysis']['component_type']}")
print(f"总体覆盖:{analysis_data['scores']['overall']}%")
print(f"高优先级缺口:{high_priority_count}")
# 提供报告位置
print("
生成的报告:")
print(" ✓ HTML: .work/test-coverage/gaps/test-gaps-report.html")
print(" ✓ JSON: .work/test-coverage/gaps/test-gaps-report.json")
print(" ✓ 文本: .work/test-coverage/gaps/test-gaps-summary.txt")
步骤5:解析分析数据(可选)
对于以编程方式访问缺口数据,使用步骤2中的analysis_data:
# 访问分析结果(从步骤2中捕获的analysis_data)
component_type = analysis_data['analysis']['component_type']
test_count = analysis_data['analysis']['test_count']
overall_score = analysis_data['scores']['overall']
# 访问缺口
platform_gaps = analysis_data['analysis']['gaps']['platforms']
protocol_gaps = analysis_data['analysis']['gaps'].get('protocols', [])
scenario_gaps = analysis_data['analysis']['gaps']['scenarios']
# 过滤高优先级缺口
high_priority_gaps = [
gap for category in analysis_data['analysis']['gaps'].values()
for gap in category if gap.get('priority') == 'high'
]
⚠️ 必选完成前验证
关键: 在声明此技能完成之前,必须执行所有以下验证检查。未能验证视为不完整执行。
验证清单
按顺序执行这些验证步骤。所有必须通过:
1. 文件存在检查
# 验证所有三种报告存在
test -f .work/test-coverage/gaps/test-gaps-report.html && echo "✓ HTML存在" || echo "✗ HTML缺失"
test -f .work/test-coverage/gaps/test-gaps-report.json && echo "✓ JSON存在" || echo "✗ JSON缺失"
test -f .work/test-coverage/gaps/test-gaps-summary.txt && echo "✓ 文本存在" || echo "✗ 文本缺失"
必需: 所有三种文件必须存在。如果任何缺失,重新生成它们。
2. 动态特征提取验证
# 验证HTML有“已测试特征(动态特征提取)”部分
grep -q "已测试特征(动态特征提取)" .work/test-coverage/gaps/test-gaps-report.html && \
echo "✓ 特征提取部分存在" || \
echo "✗ 缺失:动态特征提取部分"
# 验证JSON有特征数据
grep -q '"tested_features"' .work/test-coverage/gaps/test-gaps-report.json && \
grep -q '"feature_gaps"' .work/test-coverage/gaps/test-gaps-report.json && \
echo "✓ JSON中的特征数据" || \
echo "✗ 缺失:JSON中的特征数据"
# 验证文本有特征部分
grep -q "已测试特征" .work/test-coverage/gaps/test-gaps-summary.txt && \
echo "✓ 文本中的特征部分" || \
echo "✗ 缺失:文本中的特征部分"
必需: 动态特征提取必须存在于所有三种报告中。这是步骤5a(第163-280行)中的关键要求。
3. HTML覆盖维度验证
关键: HTML报告必须基于组件类型显示所有覆盖维度表格。
# 对于网络组件,验证所有8个维度表格存在
grep -c "<h3>平台</h3>" .work/test-coverage/gaps/test-gaps-report.html
grep -c "<h3>协议</h3>" .work/test-coverage/gaps/test-gaps-report.html
grep -c "<h3>服务类型</h3>" .work/test-coverage/gaps/test-gaps-report.html
grep -c "<h3>IP栈</h3>" .work/test-coverage/gaps/test-gaps-report.html
grep -c "<h3>网络层</h3>" .work/test-coverage/gaps/test-gaps-report.html
grep -c "<h3>网关模式</h3>" .work/test-coverage/gaps/test-gaps-report.html
grep -c "<h3>拓扑</h3>" .work/test-coverage/gaps/test-gaps-report.html
grep -c "<h3>场景</h3>" .work/test-coverage/gaps/test-gaps-report.html
预期结果:
- 网络组件: 8个维度表格(平台、协议、服务类型、IP栈、网络层、网关模式、拓扑、场景)
- 存储组件: 5个维度表格(平台、存储类、卷模式、提供程序、场景)
- 其他组件: 2个维度表格(平台、场景)
验证命令:
# 统计总覆盖维度表格
TABLE_COUNT=$(grep -E "<h3>(平台|协议|服务类型|IP栈|网络层|网关模式|拓扑|场景|存储类|卷模式|提供程序)</h3>" .work/test-coverage/gaps/test-gaps-report.html | wc -l)
echo "找到的覆盖维度表格:$TABLE_COUNT"
# 基于组件类型验证
COMPONENT=$(grep -oP '组件:</strong> \K[^<]+' .work/test-coverage/gaps/test-gaps-report.html | head -1 | tr -d '</p>')
echo "组件类型:$COMPONENT"
case "$COMPONENT" in
网络)
[ "$TABLE_COUNT" -eq 8 ] && echo "✓ 所有8个网络维度存在" || echo "✗ 不完整:预期8个表格,找到$TABLE_COUNT"
;;
存储)
[ "$TABLE_COUNT" -eq 5 ] && echo "✓ 所有5个存储维度存在" || echo "✗ 不完整:预期5个表格,找到$TABLE_COUNT"
;;
*)
[ "$TABLE_COUNT" -eq 2 ] && echo "✓ 所有2个通用维度存在" || echo "✗ 不完整:预期2个表格,找到$TABLE_COUNT"
;;
esac
必需: 所有组件特定维度表格必须存在。缺失表格表示HTML生成不完整。
4. 努力估计验证
# 验证缺口包括努力估计
grep -q "所需努力" .work/test-coverage/gaps/test-gaps-report.html && \
echo "✓ HTML中的努力估计" || \
echo "✗ 缺失:努力估计"
必需: 缺口必须包括努力估计(低、中、高),如步骤5a中指定。
5. 缺口分析器实现验证
# 验证分析器有特征提取函数
grep -q "def extract_features_from_tests" .work/test-coverage/gaps/gap_analyzer.py && \
echo "✓ 特征提取函数存在" || \
echo "✗ 缺失:extract_features_from_tests()函数"
# 验证所有5个特征类别已定义
grep -q "配置模式" .work/test-coverage/gaps/gap_analyzer.py && \
grep -q "网络拓扑" .work/test-coverage/gaps/gap_analyzer.py && \
grep -q "生命周期操作" .work/test-coverage/gaps/gap_analyzer.py && \
grep -q "网络特性" .work/test-coverage/gaps/gap_analyzer.py && \
grep -q "恢复力与恢复" .work/test-coverage/gaps/gap_analyzer.py && \
echo "✓ 所有5个特征类别已定义" || \
echo "✗ 缺失:某些特征类别未实施"
必需: 缺口分析器必须实施动态特征提取,包括所有5个类别。
6. JSON结构验证
# 验证JSON有所有必需字段
python3 << 'EOF'
import json
try:
with open('.work/test-coverage/gaps/test-gaps-report.json', 'r') as f:
data = json.load(f)
required_fields = [
('analysis.file', lambda d: d['analysis']['file']),
('analysis.component_type', lambda d: d['analysis']['component_type']),
('analysis.test_count', lambda d: d['analysis']['test_count']),
('analysis.tested_features', lambda d: d['analysis']['tested_features']),
('analysis.feature_gaps', lambda d: d['analysis']['feature_gaps']),
('scores.overall', lambda d: d['scores']['overall']),
]
missing = []
for name, getter in required_fields:
try:
getter(data)
print(f"✓ {name}")
except (KeyError, TypeError):
print(f"✗ 缺失:{name}")
missing.append(name)
if not missing:
print("
✓ 所有必需JSON字段存在")
else:
print(f"
✗ 不完整:缺失{len(missing)}个必需字段")
exit(1)
except Exception as e:
print(f"✗ 错误:{e}")
exit(1)
EOF
必需: 所有必需JSON字段必须存在。
验证摘要
在声明此技能完成之前:
- ✓ 所有三种报告文件存在
- ✓ 动态特征提取存在于所有报告中
- ✓ HTML显示所有组件特定覆盖维度表格
- ✓ 努力估计包括在缺口中
- ✓ 缺口分析器实施特征提取函数
- ✓ JSON包含所有必需字段
如果任何检查失败: 修复问题并重新运行所有验证检查。在所有检查通过之前,不要声明技能完成。
错误处理
常见问题和解决方案
-
文件未找到:
- 验证测试文件路径正确
- 检查文件是否存在且可读
-
无效文件格式:
- 确保文件是Go测试文件(
.go) - 检查文件是否使用Ginkgo框架(
g.It、g.Describe)
- 确保文件是Go测试文件(
-
未找到测试用例:
- 验证文件包含Ginkgo测试用例
- 检查
g.It("...")模式
示例
示例1:分析网络测试文件
# 在网络测试文件上运行缺口分析器
cd /home/anusaxen/git/ai-helpers/plugins/test-coverage
python3 .work/test-coverage/gaps/gap_analyzer.py \
/path/to/test/extended/networking/egressip_test.go \
--output .work/gaps/
# 输出:
# 检测到的组件:networking
# 找到的测试用例:25
# 总体覆盖:45.0%
# 高优先级缺口:Azure平台、UDP协议、错误处理场景
#
# 生成的报告:
# HTML: .work/gaps/test-gaps-report.html
# JSON: .work/gaps/test-gaps-report.json
# 文本: .work/gaps/test-gaps-summary.txt
示例2:分析存储测试文件
# 在存储测试文件上运行缺口分析器
python3 .work/test-coverage/gaps/gap_analyzer.py \
/path/to/test/extended/storage/persistent_volumes_test.go \
--output .work/gaps/
# 输出:
# 检测到的组件:storage
# 找到的测试用例:18
# 总体覆盖:52.0%
# 高优先级缺口:ReadWriteMany卷、CSI存储类、快照场景
示例3:从GitHub URL分析
# 从GitHub原始URL分析文件
python3 .work/test-coverage/gaps/gap_analyzer.py \
https://raw.githubusercontent.com/openshift/origin/master/test/extended/networking/egressip.go \
--output .work/gaps/
分析器自动检测URL并下载文件进行分析。
与Claude Code命令集成
此技能由以下命令使用:
/test-coverage:gaps <test-file-or-url>- 分析E2E测试场景缺口
该命令调用此技能对指定测试文件执行组件感知缺口分析。
另请参见
- 测试覆盖插件README - 用户指南和安装