Component-Aware Test Gap Analysis Skill
This skill automatically detects component type (networking, storage, API, etc.) and provides context-aware gap analysis. It analyzes e2e test files to identify missing test coverage specific to the component being tested.
When to Use This Skill
Use this skill when you need to:
- Automatically detect component type from test file path and content
- Component-specific gap analysis:
- Networking: Identify missing protocol tests (TCP, UDP, SCTP), service type coverage, IP stack testing
- Storage: Find gaps in storage class coverage, volume mode testing, provisioner tests
- Generic: Analyze platform coverage and common scenarios for other components
- Always analyze: Cloud platform coverage (AWS, Azure, GCP, etc.) and scenario testing (error handling, upgrades, RBAC, scale)
- Prioritize testing efforts based on component-specific production importance
- Generate comprehensive component-aware gap analysis reports
⚠️ CRITICAL REQUIREMENT
This skill MUST ALWAYS generate all three report formats (HTML, JSON, and Text) at runtime.
The gap analyzer script (generated at runtime to .work/test-coverage/gaps/gap_analyzer.py) performs the analysis and returns structured data. Claude Code is responsible for generating all three report formats based on this data.
Required Actions:
- ✅ Execute:
python3 .work/test-coverage/gaps/gap_analyzer.py <test-file> --output-json (outputs structured JSON to stdout)
- ✅ Generate: Create all three report files (HTML, JSON, Text) at runtime
- ✅ Verify: All three reports are generated successfully
- ✅ Display: Show report locations and summary to the user
Failure to generate any of the three report formats should be treated as a skill execution failure.
Prerequisites
Required Tools
- Python 3.8+ for test structure analysis
- Go toolchain for the target project
Installation
# Python dependencies (standard library only, no external packages required)
# Ensure Python 3.8+ is installed
# Optional Go analysis tools
go install golang.org/x/tools/cmd/guru@latest
go install golang.org/x/tools/cmd/goimports@latest
How It Works
Note: This skill currently supports E2E/integration test files for OpenShift/Kubernetes components written in Go (Ginkgo framework).
Current Implementation
The analyzer performs single test file analysis with two analysis layers:
Generic Coverage Analysis (keyword-based)
- Platforms, protocols, IP stacks, service types
- Uses regex pattern matching on file content
Feature-Based Analysis (runtime extraction)
- Dynamically extracts features from test names
- Infers missing features based on patterns
- No hardcoded feature matrices - works for ANY component
It does not perform repository traversal, Go AST parsing, or test-to-source mapping.
Analysis Flow
Step 1: Component Type Detection
The analyzer automatically detects the component type from:
File path patterns:
/networking/ → networking component
/storage/ → storage component
/kapi/, /api/ → kube-api component
/etcd/ → etcd component
/auth/, /rbac/ → auth component
File content patterns:
- Keywords like
sig-networking, networkpolicy, egressip → networking
- Keywords like
sig-storage, persistentvolume → storage
- Keywords like
sig-api, apiserver → kube-api
Step 2: Extract Test Cases
Parses the test file using regex to extract:
- Test names from Ginkgo
g.It("test name") patterns
- Line numbers where tests are defined
- Test tags like
[Serial], [Disruptive], [NonPreRelease]
- Test IDs from patterns like
-12345- in test names
Example:
g.It("egressip-12345-should work on AWS [Serial]", func() {
// Test implementation
})
Extracted:
- Name:
egressip-12345-should work on AWS [Serial]
- ID:
12345
- Tags:
[Serial]
- Line: 42
Step 3: Analyze Coverage Using Regex
For each component type, the analyzer searches the file content for specific keywords to determine what is tested:
Networking components:
- Platforms:
vsphere, AWS, azure, GCP, baremetal
- Protocols:
TCP, UDP, SCTP
- Service types:
NodePort, LoadBalancer, ClusterIP
- Scenarios:
invalid, upgrade, concurrent, performance, rbac
Storage components:
- Platforms:
vsphere, AWS, azure, GCP, baremetal
- Storage classes:
gp2, gp3, csi
- Volume modes:
ReadWriteOnce, ReadWriteMany, ReadOnlyMany
- Scenarios:
invalid, upgrade, concurrent, performance, rbac
Other components:
- Platforms:
vsphere, AWS, azure, GCP, baremetal
- Scenarios:
invalid, upgrade, concurrent, performance, rbac
Step 4: Identify Gaps
For each coverage dimension, if a keyword is not found in the file, it's flagged as a gap:
Example:
# If file content doesn't contain "azure" (case-insensitive)
gaps.append({
'platform': 'Azure',
'priority': 'high',
'impact': 'Major cloud provider - production blocker',
'recommendation': 'Add Azure platform-specific tests'
})
Step 5: Calculate Component-Aware Coverage Scores
Scoring is component-specific to avoid penalizing components for irrelevant metrics:
Networking components:
- Overall = avg(platform_score, protocol_score, service_type_score, scenario_score)
Storage components:
- Overall = avg(platform_score, storage_class_score, volume_mode_score, scenario_score)
Other components:
- Overall = avg(platform_score, scenario_score)
Each dimension score = (items_found / total_items) × 100
Step 5a: Dynamic Feature Extraction (Runtime Analysis)
In addition to the keyword-based coverage analysis above, the analyzer performs dynamic feature extraction to identify component-specific features from test names at runtime, without any hardcoded feature matrices.
How Runtime Feature Extraction Works:
Extract Features from Test Names
Parse test names to identify features being tested:
Example Test Name:
"Validate egressIP with mixed of multiple non-overlapping UDNs and default network(layer3/2 and IPv4 only)"
Extracted Features:
- ✓ Non-overlapping configuration
- ✓ Multiple resource configuration
- ✓ Mixed configuration
- ✓ User Defined Networks (UDN)
- ✓ Default network
- ✓ Layer 3 networking
Group Features into Categories
Features are automatically categorized:
- Configuration Patterns: overlapping, non-overlapping, single, multiple, mixed
- Network Topology: UDN, default network, layer2, layer3, gateway modes
- Lifecycle Operations: creation, deletion, recreation, assignment
- Network Features: failover, load balancing, isolation
- Resilience & Recovery: reboot, restart, node deletion
Infer Missing Features
Based on patterns, infer what's missing:
- Opposite patterns: If "overlapping" tested → suggest "non-overlapping"
- Single vs Multiple: If "single resource" tested → suggest "multiple resources"
- Completeness: If "deletion" tested → suggest "recreation"
- Layer coverage: If "layer2" tested → suggest "layer3"
Benefits of Runtime Feature Extraction:
✅ No Hardcoding - Works for ANY component without configuration
✅ Intelligent Gap Detection - Infers missing features based on patterns
✅ Component-Agnostic - Automatically adapts to any component type
✅ Always Current - Extracts from actual test names, not assumed features
Example: EgressIP Test Analysis
Input (Test Names):
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
Output (Extracted Features):
Configuration Patterns:
✓ Non-overlapping configuration
✓ Overlapping configuration
✓ Multiple resource configuration
✓ Mixed configuration
Network Topology:
✓ User Defined Networks (UDN)
Lifecycle Operations:
✓ Resource deletion
✓ Resource recreation
Network Features:
✓ Failover
✓ Load balancing
Resilience & Recovery:
✓ OVN-Kubernetes restart
Output (Inferred Feature Gaps):
[HIGH] Single resource configuration
- Pattern suggests "multiple" tested but not "single"
- Recommendation: Add single resource baseline tests
[HIGH] Layer 2 networking
- Layer 3 tested but Layer 2 missing
- Recommendation: Add Layer 2 network topology tests
[MEDIUM] Local gateway mode
- Gateway mode mentioned but local vs shared not clear
- Recommendation: Add explicit gateway mode tests
Integration in gap_analyzer.py:
The dynamic feature extractor is built into the analyzer (no separate import needed):
# After extracting test cases
feature_analysis = extract_features_from_tests(test_cases)
# Results included in analysis output
tested_features = feature_analysis['tested_features']
# {'Configuration Patterns': ['Overlapping', 'Non-overlapping', ...],
# 'Network Topology': ['UDN', 'Layer3', ...]}
feature_gaps = feature_analysis['feature_gaps']
# [{'feature': 'Multiple resources', 'priority': 'high', ...}]
coverage_stats = feature_analysis['coverage_stats']
# {'features_tested': 14, 'features_missing': 5}
Report Integration:
Feature analysis is included in all three report formats:
- HTML Reports: Feature sections with tested/missing features
- Text Reports: Feature lists grouped by category
- JSON Reports: Structured feature data for CI/CD integration
Limitations
The current implementation has the following limitations:
❌ No repository traversal - Analyzes only the single test file provided as input
❌ No Go AST parsing - Uses regex pattern matching instead of parsing Go syntax trees
❌ No test-to-source mapping - Cannot map test functions to source code functions
❌ No function-level coverage - Cannot determine which source functions are tested
❌ No project-wide analysis - Cannot analyze multiple test files or aggregate results
❌ Keyword-based detection only - Gap detection relies on keyword presence in test file
❌ Single file focus - Reports cover only the analyzed test file, not the entire codebase
These limitations mean the analyzer provides scenario and platform coverage analysis for a single E2E test file, not structural code coverage across a codebase.
Step 6: Generate Reports
The analyzer generates three report formats. You should generate Python code at runtime to create these reports.
1. HTML Gap Report (test-gaps-report.html)
Purpose: Interactive, filterable HTML report for visual gap analysis with professional styling
HTML Document Structure:
Generate a complete HTML5 document with the following structure:
<!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>
/* Inline all CSS styles here - see CSS Styles section below */
</style>
</head>
<body>
<div class="container">
<!-- Content sections -->
</div>
<script>
/* JavaScript for gap filtering - see JavaScript section below */
</script>
</body>
</html>
CSS Styles (Inline in <style> tag):
Generate comprehensive CSS with the following style rules:
Reset and Base Styles:
*: box-sizing: border-box, margin: 0, padding: 0
body: font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; line-height: 1.6; color: #333; background: #f5f5f5; padding: 20px
Container and Layout:
.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: 2em
h2: color: #34495e, margin-top: 30px, margin-bottom: 15px, padding-bottom: 10px, border-bottom: 2px solid #e74c3c, font-size: 1.5em
h3: color: #34495e, margin-top: 20px, margin-bottom: 10px, font-size: 1.2em
Metadata Section:
.metadata: background: #ecf0f1, padding: 15px, border-radius: 5px, margin-bottom: 25px
.metadata p: margin: 5px 0
Score Cards:
.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%) (score >= 80)
.score-card.good: background: linear-gradient(135deg, #3498db 0%, #2980b9 100%) (score >= 60)
.score-card.fair: background: linear-gradient(135deg, #f39c12 0%, #e67e22 100%) (score >= 40)
.score-card.poor: background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%) (score < 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 Cards:
.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
Tables:
table: width: 100%, border-collapse: collapse, margin: 20px 0
th, td: padding: 12px, text-align: left, border-bottom: 1px solid #ddd
th: background: #34495e, color: white, font-weight: 600
tr: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 Boxes:
.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:
.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 Content Sections:
Metadata Section:
<div class="metadata">
<p><strong>File:</strong> <code>{escaped_filename}</code></p>
<p><strong>Path:</strong> <code>{escaped_filepath}</code></p>
<p><strong>Component:</strong> {escaped_component_title}</p>
<p><strong>Analysis Date:</strong> {YYYY-MM-DD}</p>
<p><strong>Total Test Cases:</strong> {count}</p>
</div>
Coverage Scores Section:
- Display score cards in a grid
- Show scores dynamically based on what's calculated for the component
- Score display order and labels:
SCORE_DISPLAY = {
'overall': {'order': 1, 'label': 'Overall Coverage'},
'platform_coverage': {'order': 2, 'label': 'Platform Coverage'},
'ip_stack_coverage': {'order': 3, 'label': 'IP Stack Coverage'},
'topology_coverage': {'order': 4, 'label': 'Topology Coverage'},
'network_layer_coverage': {'order': 5, 'label': 'Network Layer Coverage'},
'gateway_mode_coverage': {'order': 6, 'label': 'Gateway Mode Coverage'},
'protocol_coverage': {'order': 5, 'label': 'Protocol Coverage'},
'service_type_coverage': {'order': 6, 'label': 'Service Type Coverage'},
'storage_class_coverage': {'order': 7, 'label': 'Storage Class Coverage'},
'volume_mode_coverage': {'order': 8, 'label': 'Volume Mode Coverage'},
'scenario_coverage': {'order': 99, 'label': 'Scenario Coverage'},
}
- Sort scores by order, render only non-zero/non-None scores
- Apply CSS class based on score value:
get_score_class(score)
- If overall < 60%, add a warning box with key findings
What's Tested Section:
Coverage Gaps Section:
Recommendations Section:
- Success box with top 5 high-priority gaps listed
- Bulleted list of immediate actions
JavaScript for Filtering (Inline in <script> tag):
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';
}
});
}
Security Requirements:
- Use
html.escape() for all user-provided content (filenames, test names, gap descriptions)
- Sanitize priority values to only allow: 'high', 'medium', 'low'
- Never inject raw HTML from analysis data
Helper Functions to Implement:
get_score_class(score):
- score >= 80: return 'excellent'
- score >= 60: return 'good'
- score >= 40: return 'fair'
- else: return 'poor'
Escape all strings using from html import escape
Component-Specific Behavior:
Networking components (networking, router, dns, network-observability):
- Show: platforms, protocols, service types, IP stacks, topologies, network layers, gateway modes, scenarios
Storage components (storage, csi):
- Show: platforms, storage classes, volume modes, volumes, CSI drivers, snapshots, scenarios
Other components:
- Show: platforms, scenarios only
2. JSON Report (test-gaps-report.json)
Generated by: Claude Code at runtime based on analyzer output
Purpose: Machine-readable format for CI/CD integration
Structure:
{
"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": "Major cloud provider",
"recommendation": "Add Azure tests"
}
],
"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"
}
Implementation: Use json.dump() with indent=2 for readable output
3. Text Summary (test-gaps-summary.txt)
Generated by: Claude Code at runtime based on analyzer output
Purpose: Terminal-friendly summary for quick review
Format Structure:
============================================================
Test Coverage Gap Analysis
============================================================
File: {filename}
Component: {component_type}
Test Cases: {count}
Analysis Date: {timestamp}
============================================================
Coverage Scores
============================================================
Overall Coverage: {score}%
Platform Coverage: {score}%
[Component-specific scores based on type]
Scenario Coverage: {score}%
============================================================
What's Tested
============================================================
Platforms:
✓ {platform1}
✓ {platform2}
[Additional tested items based on component type]
============================================================
Identified Gaps
============================================================
PLATFORM GAPS:
[PRIORITY] {platform}
Impact: {impact}
Recommendation: {recommendation}
[Additional gap sections based on component type]
============================================================
Recommendations
============================================================
Current Coverage: {current}%
Target Coverage: {target}%
Focus on addressing HIGH priority gaps first to maximize
test coverage and ensure production readiness.
Component-Specific Sections:
- Networking components: Include protocol, service type, IP stack, topology gaps
- Storage components: Include storage class, volume mode gaps
- Other components: Only include platform and scenario gaps
Implementation: Use '\n'.join(lines) to build the text content
Implementation Steps
When implementing this skill in a command:
Step 0: Generate Analyzer Script at Runtime
CRITICAL: Before running any analysis, generate the analyzer script from the reference implementation.
# Create output directory
mkdir -p .work/test-coverage/gaps/
# Generate the analyzer script from the specification below
# Claude Code will write gap_analyzer.py based on the Analyzer Specification section
Analyzer Specification:
Generate a Python script (gap_analyzer.py) that performs component-aware E2E test gap analysis:
Input: Path or URL to a Go test file (Ginkgo framework)
Output: JSON to stdout with analysis results and coverage scores
Core Algorithm:
Input Processing (handle URLs and local paths):
- Check if input starts with
http:// or https://
- If URL: Use
urllib.request.urlopen() to fetch content, save to temp file
- If local path: Use directly
- After analysis: Clean up temp file if created
Component Detection (auto-detect from file path/content):
- Networking:
/networking/, egressip, networkpolicy → component_type='networking'
- Storage:
/storage/, persistentvolume → component_type='storage'
- Other components: etcd, apiserver, mco, operators, etc.
Test Extraction (regex-based):
- Pattern:
(?:g\.|o\.)?It\(\s*["']([^"']+)["']
- Extract: test name, line number, tags ([Serial], [Disruptive]), test ID (pattern:
-\d+-)
Coverage Analysis (keyword search in file content):
- Platforms: Search for
aws|azure|gcp|vsphere|baremetal|rosa (case-insensitive)
- Protocols: Search for
\bTCP\b, \bUDP\b, \bSCTP\b, curl|wget|http (TCP via HTTP)
- IP Stacks: Search for
ipv4, ipv6, dualstack
- Service Types: Search for
NodePort, LoadBalancer, ClusterIP
- Network Layers (networking only):
layer2|l2, layer3|l3, default network
- Gateway Modes (networking only):
- Search for
local.gateway|lgw → if found, Local Gateway is tested
- Shared Gateway is DEFAULT in OVN-K: if tests exist but no local gateway pattern found → Shared Gateway is tested
- If no tests exist → neither is tested
- Topologies:
sno|single-node, multi-node|HA cluster, hypershift|hcp, check NonHyperShiftHOST tag
- Scenarios:
failover, reboot, restart, delete, invalid, upgrade, concurrent, performance, rbac, traffic disruption
Gap Identification:
- For each category, items NOT found = gaps
- Assign priority: high (production-critical), medium (important), low (nice-to-have)
- Platform gaps: Azure/GCP/AWS = high, vSphere/Bare Metal = medium
- Protocol gaps: UDP = high, SCTP = medium, TCP non-HTTP = low
- Service type gaps: LoadBalancer = high, others = medium
- Scenario gaps: Error Handling = high, Traffic Disruption = high (networking only)
Coverage Scoring (component-aware):
- Networking: avg(platform, protocol, service_type, ip_stack, network_layer, gateway_mode, topology, scenario)
- Storage: avg(platform, storage_class, volume_mode, scenario)
- Other: avg(platform, scenario)
- Each dimension: (tested_count / total_count) × 100
Output Format (JSON to stdout):
{
"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,
...
}
}
Why Runtime Generation:
- Claude Code generates the analyzer from this specification
- No separate
.py file to maintain
- SKILL.md is the single source of truth
- Claude Code is excellent at generating code from specifications
Step 1: Execute Gap Analyzer Script (MANDATORY)
Execute the gap analyzer script to perform analysis and return structured data:
# Run gap analyzer (outputs structured JSON to stdout)
python3 .work/test-coverage/gaps/gap_analyzer.py <test-file-path> --output-json
The analyzer will output structured JSON to stdout containing:
- Component type detection
- Test case extraction
- Coverage analysis
- Gap identification
- Priority scoring
- Component-specific recommendations
IMPORTANT: Do not skip this step. Do not attempt manual analysis. The script is the authoritative implementation.
Step 2: Capture and Parse Analyzer Output
import json
import subprocess
# Run analyzer and capture JSON output
result = subprocess.run(
['python3', '.work/test-coverage/gaps/gap_analyzer.py', test_file, '--output-json'],
capture_output=True,
text=True
)
# Parse structured data
analysis_data = json.loads(result.stdout)
Step 3: Generate All Three Report Formats at Runtime (MANDATORY)
IMPORTANT: Claude Code generates all three report formats based on the analyzer's structured output.
3.1: Generate JSON Report
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: Generate Text Summary Report
Follow the text format specification in Step 6 to generate a terminal-friendly summary.
text_path = '.work/test-coverage/gaps/test-gaps-summary.txt'
# Generate text content following format in Step 6
with open(text_path, 'w') as f:
f.write(text_content)
3.3: Generate HTML Report
Follow the HTML specification in Step 6 to generate an interactive report.
html_path = '.work/test-coverage/gaps/test-gaps-report.html'
# Generate HTML content following specification in Step 6
# Include all CSS styles, JavaScript filtering, and component-specific sections
with open(html_path, 'w') as f:
f.write(html_content)
Key Requirements:
- Generate HTML following the exact structure in "Step 6: Generate Reports" above
- Include all CSS styles inline in
<style> tag
- Include JavaScript filtering function in
<script> tag
- Escape all user-provided content with
html.escape()
- Apply component-specific sections based on component type
Step 4: Display Results
After generating all three reports, display the results to the user:
# Display summary (from text report or analysis_data)
print(f"Component detected: {analysis_data['analysis']['component_type']}")
print(f"Overall coverage: {analysis_data['scores']['overall']}%")
print(f"High-priority gaps: {high_priority_count}")
# Provide report locations
print("\nReports Generated:")
print(" ✓ HTML: .work/test-coverage/gaps/test-gaps-report.html")
print(" ✓ JSON: .work/test-coverage/gaps/test-gaps-report.json")
print(" ✓ Text: .work/test-coverage/gaps/test-gaps-summary.txt")
Step 5: Parse Analysis Data (Optional)
For programmatic access to gap data, use the analysis_data from Step 2:
# Access analysis results (from analysis_data captured in Step 2)
component_type = analysis_data['analysis']['component_type']
test_count = analysis_data['analysis']['test_count']
overall_score = analysis_data['scores']['overall']
# Access gaps
platform_gaps = analysis_data['analysis']['gaps']['platforms']
protocol_gaps = analysis_data['analysis']['gaps'].get('protocols', [])
scenario_gaps = analysis_data['analysis']['gaps']['scenarios']
# Filter high-priority gaps
high_priority_gaps = [
gap for category in analysis_data['analysis']['gaps'].values()
for gap in category if gap.get('priority') == 'high'
]
⚠️ MANDATORY PRE-COMPLETION VALIDATION
CRITICAL: Before declaring this skill complete, you MUST execute ALL validation checks below. Failure to validate is considered incomplete execution.
Validation Checklist
Execute these verification steps in order. ALL must pass:
1. File Existence Check
# Verify all three reports exist
test -f .work/test-coverage/gaps/test-gaps-report.html && echo "✓ HTML exists" || echo "✗ HTML MISSING"
test -f .work/test-coverage/gaps/test-gaps-report.json && echo "✓ JSON exists" || echo "✗ JSON MISSING"
test -f .work/test-coverage/gaps/test-gaps-summary.txt && echo "✓ Text exists" || echo "✗ Text MISSING"
Required: All three files must exist. If any are missing, regenerate them.
2. Dynamic Feature Extraction Verification
# Verify HTML has "Tested Features (Dynamic Feature Extraction)" section
grep -q "Tested Features (Dynamic Feature Extraction)" .work/test-coverage/gaps/test-gaps-report.html && \
echo "✓ Feature extraction section present" || \
echo "✗ MISSING: Dynamic Feature Extraction section"
# Verify JSON has feature data
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 "✓ Feature data in JSON" || \
echo "✗ MISSING: Feature data in JSON"
# Verify Text has feature section
grep -q "Tested Features" .work/test-coverage/gaps/test-gaps-summary.txt && \
echo "✓ Feature section in Text" || \
echo "✗ MISSING: Feature section in Text"
Required: Dynamic Feature Extraction must be present in all three reports. This is a critical requirement from Step 5a (lines 163-280).
3. HTML Coverage Dimension Verification
CRITICAL: The HTML report must display ALL coverage dimension tables based on component type.
# For networking components, verify ALL 8 dimension tables exist
grep -c "<h3>Platforms</h3>" .work/test-coverage/gaps/test-gaps-report.html
grep -c "<h3>Protocols</h3>" .work/test-coverage/gaps/test-gaps-report.html
grep -c "<h3>Service Types</h3>" .work/test-coverage/gaps/test-gaps-report.html
grep -c "<h3>IP Stacks</h3>" .work/test-coverage/gaps/test-gaps-report.html
grep -c "<h3>Network Layers</h3>" .work/test-coverage/gaps/test-gaps-report.html
grep -c "<h3>Gateway Modes</h3>" .work/test-coverage/gaps/test-gaps-report.html
grep -c "<h3>Topologies</h3>" .work/test-coverage/gaps/test-gaps-report.html
grep -c "<h3>Scenarios</h3>" .work/test-coverage/gaps/test-gaps-report.html
Expected Results:
- Networking components: 8 dimension tables (Platforms, Protocols, Service Types, IP Stacks, Network Layers, Gateway Modes, Topologies, Scenarios)
- Storage components: 5 dimension tables (Platforms, Storage Classes, Volume Modes, Provisioners, Scenarios)
- Other components: 2 dimension tables (Platforms, Scenarios)
Verification Command:
# Count total coverage dimension tables
TABLE_COUNT=$(grep -E "<h3>(Platforms|Protocols|Service Types|IP Stacks|Network Layers|Gateway Modes|Topologies|Scenarios|Storage Classes|Volume Modes|Provisioners)</h3>" .work/test-coverage/gaps/test-gaps-report.html | wc -l)
echo "Coverage dimension tables found: $TABLE_COUNT"
# Verify based on component type
COMPONENT=$(grep -oP 'Component:</strong> \K[^<]+' .work/test-coverage/gaps/test-gaps-report.html | head -1 | tr -d '</p>')
echo "Component type: $COMPONENT"
case "$COMPONENT" in
Networking)
[ "$TABLE_COUNT" -eq 8 ] && echo "✓ All 8 networking dimensions present" || echo "✗ INCOMPLETE: Expected 8 tables, found $TABLE_COUNT"
;;
Storage)
[ "$TABLE_COUNT" -eq 5 ] && echo "✓ All 5 storage dimensions present" || echo "✗ INCOMPLETE: Expected 5 tables, found $TABLE_COUNT"
;;
*)
[ "$TABLE_COUNT" -eq 2 ] && echo "✓ All 2 generic dimensions present" || echo "✗ INCOMPLETE: Expected 2 tables, found $TABLE_COUNT"
;;
esac
Required: All component-specific dimension tables must be present. Missing tables indicate incomplete HTML generation.
4. Effort Estimates Verification
# Verify gaps include effort estimates
grep -q "Effort Required" .work/test-coverage/gaps/test-gaps-report.html && \
echo "✓ Effort estimates in HTML" || \
echo "✗ MISSING: Effort estimates"
Required: Gaps must include effort estimates (Low, Medium, High) as specified in Step 5a.
5. Gap Analyzer Implementation Verification
# Verify analyzer has feature extraction function
grep -q "def extract_features_from_tests" .work/test-coverage/gaps/gap_analyzer.py && \
echo "✓ Feature extraction function exists" || \
echo "✗ MISSING: extract_features_from_tests() function"
# Verify all 5 feature categories are defined
grep -q "Configuration Patterns" .work/test-coverage/gaps/gap_analyzer.py && \
grep -q "Network Topology" .work/test-coverage/gaps/gap_analyzer.py && \
grep -q "Lifecycle Operations" .work/test-coverage/gaps/gap_analyzer.py && \
grep -q "Network Features" .work/test-coverage/gaps/gap_analyzer.py && \
grep -q "Resilience & Recovery" .work/test-coverage/gaps/gap_analyzer.py && \
echo "✓ All 5 feature categories defined" || \
echo "✗ MISSING: Some feature categories not implemented"
Required: The gap analyzer must implement Dynamic Feature Extraction with all 5 categories.
6. JSON Structure Verification
# Verify JSON has all required fields
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"✗ MISSING: {name}")
missing.append(name)
if not missing:
print("\n✓ All required JSON fields present")
else:
print(f"\n✗ INCOMPLETE: Missing {len(missing)} required fields")
exit(1)
except Exception as e:
print(f"✗ ERROR: {e}")
exit(1)
EOF
Required: All required JSON fields must be present.
Validation Summary
Before declaring this skill complete:
- ✓ All three report files exist
- ✓ Dynamic Feature Extraction present in all reports
- ✓ HTML shows ALL component-specific coverage dimension tables
- ✓ Effort estimates included in gaps
- ✓ Gap analyzer implements feature extraction function
- ✓ JSON contains all required fields
If ANY check fails: Fix the issue and re-run all validation checks. Do NOT declare the skill complete until ALL checks pass.
Error Handling
Common Issues and Solutions
File not found:
- Verify the test file path is correct
- Check that the file exists and is readable
Invalid file format:
- Ensure the file is a Go test file (
.go)
- Check that the file uses Ginkgo framework (
g.It, g.Describe)
No test cases found:
- Verify the file contains Ginkgo test cases
- Check for
g.It("...") patterns
Examples
Example 1: Analyze Networking Test File
# Run gap analyzer on a networking test file
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/
# Output:
# Component detected: networking
# Test cases found: 25
# Overall coverage: 45.0%
# High-priority gaps: Azure platform, UDP protocol, Error handling scenarios
#
# Reports generated:
# HTML: .work/gaps/test-gaps-report.html
# JSON: .work/gaps/test-gaps-report.json
# Text: .work/gaps/test-gaps-summary.txt
Example 2: Analyze Storage Test File
# Run gap analyzer on a storage test file
python3 .work/test-coverage/gaps/gap_analyzer.py \
/path/to/test/extended/storage/persistent_volumes_test.go \
--output .work/gaps/
# Output:
# Component detected: storage
# Test cases found: 18
# Overall coverage: 52.0%
# High-priority gaps: ReadWriteMany volumes, CSI storage class, Snapshot scenarios
Example 3: Analyze from GitHub URL
# Analyze file from GitHub raw URL
python3 .work/test-cove
…(truncated)
1---2name: component-aware-test-gap-analysis3description: Intelligently identify missing test coverage based on component type4---5
6# Component-Aware Test Gap Analysis Skill
7
8This skill **automatically detects component type** (networking, storage, API, etc.) and provides **context-aware gap analysis**. It analyzes e2e test files to identify missing test coverage specific to the component being tested.
9
10## When to Use This Skill
11
12Use this skill when you need to:
13- **Automatically detect component type** from test file path and content
14- **Component-specific gap analysis**:
15 - **Networking**: Identify missing protocol tests (TCP, UDP, SCTP), service type coverage, IP stack testing
16 - **Storage**: Find gaps in storage class coverage, volume mode testing, provisioner tests
17 - **Generic**: Analyze platform coverage and common scenarios for other components
18- **Always analyze**: Cloud platform coverage (AWS, Azure, GCP, etc.) and scenario testing (error handling, upgrades, RBAC, scale)
19- Prioritize testing efforts based on component-specific production importance
20- Generate comprehensive component-aware gap analysis reports
21
22## ⚠️ CRITICAL REQUIREMENT
23
24**This skill MUST ALWAYS generate all three report formats (HTML, JSON, and Text) at runtime.**
25
26The gap analyzer script (generated at runtime to `.work/test-coverage/gaps/gap_analyzer.py`) performs the analysis and returns structured data. Claude Code is responsible for generating all three report formats based on this data.
27
28**Required Actions:**
291. ✅ **Execute**: `python3 .work/test-coverage/gaps/gap_analyzer.py <test-file> --output-json` (outputs structured JSON to stdout)
302. ✅ **Generate**: Create all three report files (HTML, JSON, Text) at runtime
313. ✅ **Verify**: All three reports are generated successfully
324. ✅ **Display**: Show report locations and summary to the user
33
34**Failure to generate any of the three report formats** should be treated as a skill execution failure.
35
36## Prerequisites
37
38### Required Tools
39
40- **Python 3.8+** for test structure analysis
41- **Go toolchain** for the target project
42
43### Installation
44
45```bash
46# Python dependencies (standard library only, no external packages required)
47# Ensure Python 3.8+ is installed
48
49# Optional Go analysis tools
50go install golang.org/x/tools/cmd/guru@latest
51go install golang.org/x/tools/cmd/goimports@latest
52```
53
54## How It Works
55
56**Note: This skill currently supports E2E/integration test files for OpenShift/Kubernetes components written in Go (Ginkgo framework).**
57
58### Current Implementation
59
60The analyzer performs **single test file analysis** with two analysis layers:
61
621. **Generic Coverage Analysis** (keyword-based)
63 - Platforms, protocols, IP stacks, service types
64 - Uses regex pattern matching on file content
65
662. **Feature-Based Analysis** (runtime extraction)
67 - Dynamically extracts features from test names
68 - Infers missing features based on patterns
69 - No hardcoded feature matrices - works for ANY component
70
71It does **not** perform repository traversal, Go AST parsing, or test-to-source mapping.
72
73### Analysis Flow
74
75#### Step 1: Component Type Detection
76
77The analyzer automatically detects the component type from:
78
791. **File path patterns**:
80 - `/networking/` → networking component
81 - `/storage/` → storage component
82 - `/kapi/`, `/api/` → kube-api component
83 - `/etcd/` → etcd component
84 - `/auth/`, `/rbac/` → auth component
85
862. **File content patterns**:
87 - Keywords like `sig-networking`, `networkpolicy`, `egressip` → networking
88 - Keywords like `sig-storage`, `persistentvolume` → storage
89 - Keywords like `sig-api`, `apiserver` → kube-api
90
91#### Step 2: Extract Test Cases
92
93Parses the test file using regex to extract:
94
95- **Test names** from Ginkgo `g.It("test name")` patterns
96- **Line numbers** where tests are defined
97- **Test tags** like `[Serial]`, `[Disruptive]`, `[NonPreRelease]`
98- **Test IDs** from patterns like `-12345-` in test names
99
100**Example:**
101```go
102g.It("egressip-12345-should work on AWS [Serial]", func() {
103 // Test implementation
104})
105```
106
107Extracted:
108- Name: `egressip-12345-should work on AWS [Serial]`
109- ID: `12345`
110- Tags: `[Serial]`
111- Line: 42
112
113#### Step 3: Analyze Coverage Using Regex
114
115For each component type, the analyzer searches the file content for specific keywords to determine what is tested:
116
117**Networking components:**
118- **Platforms**: `vsphere`, `AWS`, `azure`, `GCP`, `baremetal`
119- **Protocols**: `TCP`, `UDP`, `SCTP`
120- **Service types**: `NodePort`, `LoadBalancer`, `ClusterIP`
121- **Scenarios**: `invalid`, `upgrade`, `concurrent`, `performance`, `rbac`
122
123**Storage components:**
124- **Platforms**: `vsphere`, `AWS`, `azure`, `GCP`, `baremetal`
125- **Storage classes**: `gp2`, `gp3`, `csi`
126- **Volume modes**: `ReadWriteOnce`, `ReadWriteMany`, `ReadOnlyMany`
127- **Scenarios**: `invalid`, `upgrade`, `concurrent`, `performance`, `rbac`
128
129**Other components:**
130- **Platforms**: `vsphere`, `AWS`, `azure`, `GCP`, `baremetal`
131- **Scenarios**: `invalid`, `upgrade`, `concurrent`, `performance`, `rbac`
132
133#### Step 4: Identify Gaps
134
135For each coverage dimension, if a keyword is **not found** in the file, it's flagged as a gap:
136
137**Example:**
138```python
139# If file content doesn't contain "azure" (case-insensitive)
140gaps.append({
141 'platform': 'Azure',
142 'priority': 'high',
143 'impact': 'Major cloud provider - production blocker',
144 'recommendation': 'Add Azure platform-specific tests'
145})
146```
147
148#### Step 5: Calculate Component-Aware Coverage Scores
149
150Scoring is component-specific to avoid penalizing components for irrelevant metrics:
151
152**Networking components:**
153- Overall = avg(platform_score, protocol_score, service_type_score, scenario_score)
154
155**Storage components:**
156- Overall = avg(platform_score, storage_class_score, volume_mode_score, scenario_score)
157
158**Other components:**
159- Overall = avg(platform_score, scenario_score)
160
161Each dimension score = (items_found / total_items) × 100
162
163#### Step 5a: Dynamic Feature Extraction (Runtime Analysis)
164
165In addition to the keyword-based coverage analysis above, the analyzer performs **dynamic feature extraction** to identify component-specific features from test names at runtime, without any hardcoded feature matrices.
166
167**How Runtime Feature Extraction Works:**
168
1691. **Extract Features from Test Names**
170
171 Parse test names to identify features being tested:
172
173 **Example Test Name:**
174 ```
175 "Validate egressIP with mixed of multiple non-overlapping UDNs and default network(layer3/2 and IPv4 only)"
176 ```
177
178 **Extracted Features:**
179 - ✓ Non-overlapping configuration
180 - ✓ Multiple resource configuration
181 - ✓ Mixed configuration
182 - ✓ User Defined Networks (UDN)
183 - ✓ Default network
184 - ✓ Layer 3 networking
185
1862. **Group Features into Categories**
187
188 Features are automatically categorized:
189
190 - **Configuration Patterns**: overlapping, non-overlapping, single, multiple, mixed
191 - **Network Topology**: UDN, default network, layer2, layer3, gateway modes
192 - **Lifecycle Operations**: creation, deletion, recreation, assignment
193 - **Network Features**: failover, load balancing, isolation
194 - **Resilience & Recovery**: reboot, restart, node deletion
195
1963. **Infer Missing Features**
197
198 Based on patterns, infer what's missing:
199
200 - **Opposite patterns**: If "overlapping" tested → suggest "non-overlapping"
201 - **Single vs Multiple**: If "single resource" tested → suggest "multiple resources"
202 - **Completeness**: If "deletion" tested → suggest "recreation"
203 - **Layer coverage**: If "layer2" tested → suggest "layer3"
204
205**Benefits of Runtime Feature Extraction:**
206
207✅ **No Hardcoding** - Works for ANY component without configuration
208✅ **Intelligent Gap Detection** - Infers missing features based on patterns
209✅ **Component-Agnostic** - Automatically adapts to any component type
210✅ **Always Current** - Extracts from actual test names, not assumed features
211
212**Example: EgressIP Test Analysis**
213
214**Input (Test Names):**
215```
2161. Validate egressIP with mixed of multiple non-overlapping UDNs
2172. Validate egressIP with mixed of multiple overlapping UDNs
2183. Validate egressIP Failover with UDNs
2194. egressIP after UDN deleted then recreated
2205. egressIP after OVNK restarted
2216. Traffic is load balanced between egress nodes
222```
223
224**Output (Extracted Features):**
225```
226Configuration Patterns:
227 ✓ Non-overlapping configuration
228 ✓ Overlapping configuration
229 ✓ Multiple resource configuration
230 ✓ Mixed configuration
231
232Network Topology:
233 ✓ User Defined Networks (UDN)
234
235Lifecycle Operations:
236 ✓ Resource deletion
237 ✓ Resource recreation
238
239Network Features:
240 ✓ Failover
241 ✓ Load balancing
242
243Resilience & Recovery:
244 ✓ OVN-Kubernetes restart
245```
246
247**Output (Inferred Feature Gaps):**
248```
249[HIGH] Single resource configuration
250 - Pattern suggests "multiple" tested but not "single"
251 - Recommendation: Add single resource baseline tests
252
253[HIGH] Layer 2 networking
254 - Layer 3 tested but Layer 2 missing
255 - Recommendation: Add Layer 2 network topology tests
256
257[MEDIUM] Local gateway mode
258 - Gateway mode mentioned but local vs shared not clear
259 - Recommendation: Add explicit gateway mode tests
260```
261
262**Integration in gap_analyzer.py:**
263
264The dynamic feature extractor is built into the analyzer (no separate import needed):
265
266```python
267# After extracting test cases
268feature_analysis = extract_features_from_tests(test_cases)
269
270# Results included in analysis output
271tested_features = feature_analysis['tested_features']
272# {'Configuration Patterns': ['Overlapping', 'Non-overlapping', ...],
273# 'Network Topology': ['UDN', 'Layer3', ...]}
274
275feature_gaps = feature_analysis['feature_gaps']
276# [{'feature': 'Multiple resources', 'priority': 'high', ...}]
277
278coverage_stats = feature_analysis['coverage_stats']
279# {'features_tested': 14, 'features_missing': 5}
280```
281
282**Report Integration:**
283
284Feature analysis is included in all three report formats:
285
286- **HTML Reports**: Feature sections with tested/missing features
287- **Text Reports**: Feature lists grouped by category
288- **JSON Reports**: Structured feature data for CI/CD integration
289
290### Limitations
291
292The current implementation has the following limitations:
293
294❌ **No repository traversal** - Analyzes only the single test file provided as input
295❌ **No Go AST parsing** - Uses regex pattern matching instead of parsing Go syntax trees
296❌ **No test-to-source mapping** - Cannot map test functions to source code functions
297❌ **No function-level coverage** - Cannot determine which source functions are tested
298❌ **No project-wide analysis** - Cannot analyze multiple test files or aggregate results
299❌ **Keyword-based detection only** - Gap detection relies on keyword presence in test file
300❌ **Single file focus** - Reports cover only the analyzed test file, not the entire codebase
301
302These limitations mean the analyzer provides **scenario and platform coverage analysis** for a single E2E test file, not structural code coverage across a codebase.
303
304#### Step 6: Generate Reports
305
306The analyzer generates three report formats. You should generate Python code at runtime to create these reports.
307
308#### 1. HTML Gap Report (`test-gaps-report.html`)
309
310**Purpose:** Interactive, filterable HTML report for visual gap analysis with professional styling
311
312**HTML Document Structure:**
313
314Generate a complete HTML5 document with the following structure:
315
316```html
317<!DOCTYPE html>
318<html lang="en">
319<head>
320 <meta charset="UTF-8">
321 <meta name="viewport" content="width=device-width, initial-scale=1.0">
322 <title>Test Coverage Gap Analysis - {filename}</title>
323 <style>
324 /* Inline all CSS styles here - see CSS Styles section below */
325 </style>
326</head>
327<body>
328 <div class="container">
329 <!-- Content sections -->
330 </div>
331 <script>
332 /* JavaScript for gap filtering - see JavaScript section below */
333 </script>
334</body>
335</html>
336```
337
338**CSS Styles (Inline in `<style>` tag):**
339
340Generate comprehensive CSS with the following style rules:
341
3421. **Reset and Base Styles:**
343 - `*`: box-sizing: border-box, margin: 0, padding: 0
344 - `body`: font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; line-height: 1.6; color: #333; background: #f5f5f5; padding: 20px
345
3462. **Container and Layout:**
347 - `.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)
348 - `h1`: color: #2c3e50, margin-bottom: 10px, font-size: 2em
349 - `h2`: color: #34495e, margin-top: 30px, margin-bottom: 15px, padding-bottom: 10px, border-bottom: 2px solid #e74c3c, font-size: 1.5em
350 - `h3`: color: #34495e, margin-top: 20px, margin-bottom: 10px, font-size: 1.2em
351
3523. **Metadata Section:**
353 - `.metadata`: background: #ecf0f1, padding: 15px, border-radius: 5px, margin-bottom: 25px
354 - `.metadata p`: margin: 5px 0
355
3564. **Score Cards:**
357 - `.score-grid`: display: grid, grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)), gap: 15px, margin: 20px 0
358 - `.score-card`: padding: 20px, border-radius: 8px, text-align: center, color: white
359 - `.score-card.excellent`: background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%) (score >= 80)
360 - `.score-card.good`: background: linear-gradient(135deg, #3498db 0%, #2980b9 100%) (score >= 60)
361 - `.score-card.fair`: background: linear-gradient(135deg, #f39c12 0%, #e67e22 100%) (score >= 40)
362 - `.score-card.poor`: background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%) (score < 40)
363 - `.score-card .number`: font-size: 2.5em, font-weight: bold, margin: 10px 0
364 - `.score-card .label`: font-size: 0.9em, opacity: 0.9
365
3665. **Gap Cards:**
367 - `.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)
368 - `.gap-card.high`: border-left-color: #e74c3c
369 - `.gap-card.medium`: border-left-color: #f39c12
370 - `.gap-card.low`: border-left-color: #3498db
371 - `.gap-card h4`: color: #2c3e50, margin-bottom: 10px, font-size: 1.1em
372 - `.gap-card .gap-id`: font-family: "Courier New", monospace, font-size: 0.85em, color: #7f8c8d, margin-bottom: 5px
373 - `.priority`: display: inline-block, padding: 4px 12px, border-radius: 12px, font-size: 0.75em, font-weight: bold, margin-right: 8px
374 - `.priority.high`: background: #e74c3c, color: white
375 - `.priority.medium`: background: #f39c12, color: white
376 - `.priority.low`: background: #3498db, color: white
377 - `.gap-card .impact`: background: #fff3cd, border-left: 3px solid #ffc107, padding: 10px, margin: 10px 0, border-radius: 3px
378 - `.gap-card .recommendation`: background: #d4edda, border-left: 3px solid #28a745, padding: 10px, margin: 10px 0, border-radius: 3px
379
3806. **Tables:**
381 - `table`: width: 100%, border-collapse: collapse, margin: 20px 0
382 - `th, td`: padding: 12px, text-align: left, border-bottom: 1px solid #ddd
383 - `th`: background: #34495e, color: white, font-weight: 600
384 - `tr:hover`: background: #f5f5f5
385 - `.tested`: background: #d4edda, color: #155724, font-weight: bold, text-align: center
386 - `.not-tested`: background: #f8d7da, color: #721c24, font-weight: bold, text-align: center
387
3887. **Summary Boxes:**
389 - `.summary-box`: background: #e3f2fd, border-left: 4px solid #2196f3, padding: 15px, margin: 20px 0, border-radius: 5px
390 - `.warning-box`: background: #fff3cd, border-left: 4px solid #ffc107, padding: 15px, margin: 20px 0, border-radius: 5px
391 - `.success-box`: background: #d4edda, border-left: 4px solid #28a745, padding: 15px, margin: 20px 0, border-radius: 5px
392
3938. **Filter Buttons:**
394 - `.filter-buttons`: margin: 20px 0
395 - `.filter-btn`: padding: 10px 20px, margin-right: 10px, border: none, border-radius: 5px, cursor: pointer, font-weight: bold
396 - `.filter-btn.active`: box-shadow: 0 0 0 3px rgba(0,0,0,0.2)
397 - `.filter-btn.all`: background: #95a5a6, color: white
398 - `.filter-btn.high`: background: #e74c3c, color: white
399 - `.filter-btn.medium`: background: #f39c12, color: white
400 - `.filter-btn.low`: background: #3498db, color: white
401
402**HTML Content Sections:**
403
4041. **Metadata Section:**
405 ```html
406 <div class="metadata">
407 <p><strong>File:</strong> <code>{escaped_filename}</code></p>
408 <p><strong>Path:</strong> <code>{escaped_filepath}</code></p>
409 <p><strong>Component:</strong> {escaped_component_title}</p>
410 <p><strong>Analysis Date:</strong> {YYYY-MM-DD}</p>
411 <p><strong>Total Test Cases:</strong> {count}</p>
412 </div>
413 ```
414
4152. **Coverage Scores Section:**
416 - Display score cards in a grid
417 - Show scores dynamically based on what's calculated for the component
418 - Score display order and labels:
419 ```python
420 SCORE_DISPLAY = {
421 'overall': {'order': 1, 'label': 'Overall Coverage'},
422 'platform_coverage': {'order': 2, 'label': 'Platform Coverage'},
423 'ip_stack_coverage': {'order': 3, 'label': 'IP Stack Coverage'},
424 'topology_coverage': {'order': 4, 'label': 'Topology Coverage'},
425 'network_layer_coverage': {'order': 5, 'label': 'Network Layer Coverage'},
426 'gateway_mode_coverage': {'order': 6, 'label': 'Gateway Mode Coverage'},
427 'protocol_coverage': {'order': 5, 'label': 'Protocol Coverage'},
428 'service_type_coverage': {'order': 6, 'label': 'Service Type Coverage'},
429 'storage_class_coverage': {'order': 7, 'label': 'Storage Class Coverage'},
430 'volume_mode_coverage': {'order': 8, 'label': 'Volume Mode Coverage'},
431 'scenario_coverage': {'order': 99, 'label': 'Scenario Coverage'},
432 }
433 ```
434 - Sort scores by order, render only non-zero/non-None scores
435 - Apply CSS class based on score value: `get_score_class(score)`
436 - If overall < 60%, add a warning box with key findings
437
4383. **What's Tested Section:**
439 - Generate tables showing tested vs not-tested items
440 - For networking components: platforms, protocols, service types, IP stacks, topologies, scenarios
441 - For storage components: platforms, storage classes, volume modes, scenarios
442 - For other components: platforms, scenarios only
443 - Table format:
444 ```html
445 <table>
446 <tr>
447 <th>Item</th>
448 <th>Status</th>
449 </tr>
450 <tr>
451 <td>AWS</td>
452 <td class="tested">✓ Tested</td>
453 </tr>
454 </table>
455 ```
456
4574. **Coverage Gaps Section:**
458 - Summary box with gap counts by priority
459 - Filter buttons for All/High/Medium/Low priority
460 - Gap cards with data-priority attribute for filtering:
461 ```html
462 <div class="gap-card {priority}" data-priority="{priority}">
463 <div class="gap-id">GAP-{001}</div>
464 <h4>
465 <span class="priority {priority}">{PRIORITY} PRIORITY</span>
466 <span class="category">{Category}</span>
467 {gap_name}
468 </h4>
469 <div class="impact"><strong>Impact:</strong> {impact_description}</div>
470 <div class="recommendation"><strong>Recommendation:</strong> {recommendation_text}</div>
471 </div>
472 ```
473 - Assign sequential GAP IDs: GAP-001, GAP-002, etc.
474 - Sort gaps by priority (high, medium, low)
475
4765. **Recommendations Section:**
477 - Success box with top 5 high-priority gaps listed
478 - Bulleted list of immediate actions
479
480**JavaScript for Filtering (Inline in `<script>` tag):**
481
482```javascript
483function filterGaps(priority) {
484 const cards = document.querySelectorAll('.gap-card');
485 const buttons = document.querySelectorAll('.filter-btn');
486
487 buttons.forEach(btn => btn.classList.remove('active'));
488 document.querySelector(`.filter-btn.${priority}`).classList.add('active');
489
490 cards.forEach(card => {
491 if (priority === 'all' || card.dataset.priority === priority) {
492 card.style.display = 'block';
493 } else {
494 card.style.display = 'none';
495 }
496 });
497}
498```
499
500**Security Requirements:**
501- Use `html.escape()` for all user-provided content (filenames, test names, gap descriptions)
502- Sanitize priority values to only allow: 'high', 'medium', 'low'
503- Never inject raw HTML from analysis data
504
505**Helper Functions to Implement:**
506
5071. `get_score_class(score)`:
508 - score >= 80: return 'excellent'
509 - score >= 60: return 'good'
510 - score >= 40: return 'fair'
511 - else: return 'poor'
512
5132. Escape all strings using `from html import escape`
514
515**Component-Specific Behavior:**
516
517- **Networking components** (networking, router, dns, network-observability):
518 - Show: platforms, protocols, service types, IP stacks, topologies, network layers, gateway modes, scenarios
519
520- **Storage components** (storage, csi):
521 - Show: platforms, storage classes, volume modes, volumes, CSI drivers, snapshots, scenarios
522
523- **Other components**:
524 - Show: platforms, scenarios only
525
526#### 2. JSON Report (`test-gaps-report.json`)
527
528**Generated by:** Claude Code at runtime based on analyzer output
529
530**Purpose:** Machine-readable format for CI/CD integration
531
532**Structure:**
533```json
534{
535 "analysis": {
536 "file": "path/to/test/file.go",
537 "component_type": "networking",
538 "test_count": 15,
539 "test_cases": [
540 {
541 "name": "test name",
542 "line": 42,
543 "id": "12345",
544 "tags": ["Serial", "Disruptive"]
545 }
546 ],
547 "coverage": {
548 "platforms": {
549 "tested": ["AWS", "GCP"],
550 "not_tested": ["Azure", "vSphere", "Bare Metal"]
551 },
552 "protocols": {
553 "tested": ["TCP"],
554 "not_tested": ["UDP", "SCTP"]
555 }
556 },
557 "gaps": {
558 "platforms": [
559 {
560 "platform": "Azure",
561 "priority": "high",
562 "impact": "Major cloud provider",
563 "recommendation": "Add Azure tests"
564 }
565 ],
566 "protocols": [],
567 "scenarios": []
568 }
569 },
570 "scores": {
571 "overall": 45.0,
572 "platform_coverage": 33.3,
573 "protocol_coverage": 33.3,
574 "scenario_coverage": 40.0
575 },
576 "generated_at": "2025-11-10T10:00:00Z"
577}
578```
579
580**Implementation:** Use `json.dump()` with `indent=2` for readable output
581
582#### 3. Text Summary (`test-gaps-summary.txt`)
583
584**Generated by:** Claude Code at runtime based on analyzer output
585
586**Purpose:** Terminal-friendly summary for quick review
587
588**Format Structure:**
589```text
590============================================================
591Test Coverage Gap Analysis
592============================================================
593
594File: {filename}
595Component: {component_type}
596Test Cases: {count}
597Analysis Date: {timestamp}
598
599============================================================
600Coverage Scores
601============================================================
602
603Overall Coverage: {score}%
604Platform Coverage: {score}%
605[Component-specific scores based on type]
606Scenario Coverage: {score}%
607
608============================================================
609What's Tested
610============================================================
611
612Platforms:
613 ✓ {platform1}
614 ✓ {platform2}
615
616[Additional tested items based on component type]
617
618============================================================
619Identified Gaps
620============================================================
621
622PLATFORM GAPS:
623 [PRIORITY] {platform}
624 Impact: {impact}
625 Recommendation: {recommendation}
626
627[Additional gap sections based on component type]
628
629============================================================
630Recommendations
631============================================================
632
633Current Coverage: {current}%
634Target Coverage: {target}%
635
636Focus on addressing HIGH priority gaps first to maximize
637test coverage and ensure production readiness.
638```
639
640**Component-Specific Sections:**
641- **Networking components**: Include protocol, service type, IP stack, topology gaps
642- **Storage components**: Include storage class, volume mode gaps
643- **Other components**: Only include platform and scenario gaps
644
645**Implementation:** Use `'\n'.join(lines)` to build the text content
646
647## Implementation Steps
648
649When implementing this skill in a command:
650
651### Step 0: Generate Analyzer Script at Runtime
652
653**CRITICAL:** Before running any analysis, generate the analyzer script from the reference implementation.
654
655```bash
656# Create output directory
657mkdir -p .work/test-coverage/gaps/
658
659# Generate the analyzer script from the specification below
660# Claude Code will write gap_analyzer.py based on the Analyzer Specification section
661```
662
663**Analyzer Specification:**
664
665Generate a Python script (`gap_analyzer.py`) that performs component-aware E2E test gap analysis:
666
667**Input:** Path or URL to a Go test file (Ginkgo framework)
668**Output:** JSON to stdout with analysis results and coverage scores
669
670**Core Algorithm:**
671
6720. **Input Processing** (handle URLs and local paths):
673 - Check if input starts with `http://` or `https://`
674 - If URL: Use `urllib.request.urlopen()` to fetch content, save to temp file
675 - If local path: Use directly
676 - After analysis: Clean up temp file if created
677
6781. **Component Detection** (auto-detect from file path/content):
679 - Networking: `/networking/`, `egressip`, `networkpolicy` → component_type='networking'
680 - Storage: `/storage/`, `persistentvolume` → component_type='storage'
681 - Other components: etcd, apiserver, mco, operators, etc.
682
6832. **Test Extraction** (regex-based):
684 - Pattern: `(?:g\.|o\.)?It\(\s*["']([^"']+)["']`
685 - Extract: test name, line number, tags ([Serial], [Disruptive]), test ID (pattern: `-\d+-`)
686
6873. **Coverage Analysis** (keyword search in file content):
688 - **Platforms**: Search for `aws|azure|gcp|vsphere|baremetal|rosa` (case-insensitive)
689 - **Protocols**: Search for `\bTCP\b`, `\bUDP\b`, `\bSCTP\b`, `curl|wget|http` (TCP via HTTP)
690 - **IP Stacks**: Search for `ipv4`, `ipv6`, `dualstack`
691 - **Service Types**: Search for `NodePort`, `LoadBalancer`, `ClusterIP`
692 - **Network Layers** (networking only): `layer2|l2`, `layer3|l3`, `default network`
693 - **Gateway Modes** (networking only):
694 - Search for `local.gateway|lgw` → if found, Local Gateway is tested
695 - Shared Gateway is DEFAULT in OVN-K: if tests exist but no local gateway pattern found → Shared Gateway is tested
696 - If no tests exist → neither is tested
697 - **Topologies**: `sno|single-node`, `multi-node|HA cluster`, `hypershift|hcp`, check NonHyperShiftHOST tag
698 - **Scenarios**: `failover`, `reboot`, `restart`, `delete`, `invalid`, `upgrade`, `concurrent`, `performance`, `rbac`, `traffic disruption`
699
7004. **Gap Identification**:
701 - For each category, items NOT found = gaps
702 - Assign priority: high (production-critical), medium (important), low (nice-to-have)
703 - Platform gaps: Azure/GCP/AWS = high, vSphere/Bare Metal = medium
704 - Protocol gaps: UDP = high, SCTP = medium, TCP non-HTTP = low
705 - Service type gaps: LoadBalancer = high, others = medium
706 - Scenario gaps: Error Handling = high, Traffic Disruption = high (networking only)
707
7085. **Coverage Scoring** (component-aware):
709 - Networking: avg(platform, protocol, service_type, ip_stack, network_layer, gateway_mode, topology, scenario)
710 - Storage: avg(platform, storage_class, volume_mode, scenario)
711 - Other: avg(platform, scenario)
712 - Each dimension: (tested_count / total_count) × 100
713
7146. **Output Format** (JSON to stdout):
715```json
716{
717 "analysis": {
718 "file": "/path/to/test.go",
719 "component_type": "networking",
720 "test_count": 15,
721 "test_cases": [...],
722 "coverage": {
723 "platforms": {"tested": [...], "not_tested": [...]},
724 "protocols": {"tested": [...], "not_tested": [...]},
725 ...
726 },
727 "gaps": {
728 "platforms": [{"platform": "Azure", "priority": "high", "impact": "...", "recommendation": "..."}],
729 ...
730 }
731 },
732 "scores": {
733 "overall": 62.0,
734 "platform_coverage": 100.0,
735 ...
736 }
737}
738```
739
740**Why Runtime Generation:**
741- Claude Code generates the analyzer from this specification
742- No separate `.py` file to maintain
743- SKILL.md is the single source of truth
744- Claude Code is excellent at generating code from specifications
745
746### Step 1: Execute Gap Analyzer Script (MANDATORY)
747
748**Execute the gap analyzer script to perform analysis and return structured data:**
749
750```bash
751# Run gap analyzer (outputs structured JSON to stdout)
752python3 .work/test-coverage/gaps/gap_analyzer.py <test-file-path> --output-json
753```
754
755The analyzer will output structured JSON to stdout containing:
756- Component type detection
757- Test case extraction
758- Coverage analysis
759- Gap identification
760- Priority scoring
761- Component-specific recommendations
762
763**IMPORTANT:** Do not skip this step. Do not attempt manual analysis. The script is the authoritative implementation.
764
765### Step 2: Capture and Parse Analyzer Output
766
767```python
768import json
769import subprocess
770
771# Run analyzer and capture JSON output
772result = subprocess.run(
773 ['python3', '.work/test-coverage/gaps/gap_analyzer.py', test_file, '--output-json'],
774 capture_output=True,
775 text=True
776)
777
778# Parse structured data
779analysis_data = json.loads(result.stdout)
780```
781
782### Step 3: Generate All Three Report Formats at Runtime (MANDATORY)
783
784**IMPORTANT:** Claude Code generates all three report formats based on the analyzer's structured output.
785
786#### 3.1: Generate JSON Report
787
788```python
789json_path = '.work/test-coverage/gaps/test-gaps-report.json'
790with open(json_path, 'w') as f:
791 json.dump(analysis_data, f, indent=2)
792```
793
794#### 3.2: Generate Text Summary Report
795
796Follow the text format specification in Step 6 to generate a terminal-friendly summary.
797
798```python
799text_path = '.work/test-coverage/gaps/test-gaps-summary.txt'
800# Generate text content following format in Step 6
801with open(text_path, 'w') as f:
802 f.write(text_content)
803```
804
805#### 3.3: Generate HTML Report
806
807Follow the HTML specification in Step 6 to generate an interactive report.
808
809```python
810html_path = '.work/test-coverage/gaps/test-gaps-report.html'
811# Generate HTML content following specification in Step 6
812# Include all CSS styles, JavaScript filtering, and component-specific sections
813with open(html_path, 'w') as f:
814 f.write(html_content)
815```
816
817**Key Requirements:**
818- Generate HTML following the exact structure in "Step 6: Generate Reports" above
819- Include all CSS styles inline in `<style>` tag
820- Include JavaScript filtering function in `<script>` tag
821- Escape all user-provided content with `html.escape()`
822- Apply component-specific sections based on component type
823
824### Step 4: Display Results
825
826After generating all three reports, display the results to the user:
827
828```python
829# Display summary (from text report or analysis_data)
830print(f"Component detected: {analysis_data['analysis']['component_type']}")
831print(f"Overall coverage: {analysis_data['scores']['overall']}%")
832print(f"High-priority gaps: {high_priority_count}")
833
834# Provide report locations
835print("\nReports Generated:")
836print(" ✓ HTML: .work/test-coverage/gaps/test-gaps-report.html")
837print(" ✓ JSON: .work/test-coverage/gaps/test-gaps-report.json")
838print(" ✓ Text: .work/test-coverage/gaps/test-gaps-summary.txt")
839```
840
841### Step 5: Parse Analysis Data (Optional)
842
843For programmatic access to gap data, use the `analysis_data` from Step 2:
844
845```python
846# Access analysis results (from analysis_data captured in Step 2)
847component_type = analysis_data['analysis']['component_type']
848test_count = analysis_data['analysis']['test_count']
849overall_score = analysis_data['scores']['overall']
850
851# Access gaps
852platform_gaps = analysis_data['analysis']['gaps']['platforms']
853protocol_gaps = analysis_data['analysis']['gaps'].get('protocols', [])
854scenario_gaps = analysis_data['analysis']['gaps']['scenarios']
855
856# Filter high-priority gaps
857high_priority_gaps = [
858 gap for category in analysis_data['analysis']['gaps'].values()
859 for gap in category if gap.get('priority') == 'high'
860]
861```
862
863## ⚠️ MANDATORY PRE-COMPLETION VALIDATION
864
865**CRITICAL:** Before declaring this skill complete, you MUST execute ALL validation checks below. Failure to validate is considered incomplete execution.
866
867### Validation Checklist
868
869Execute these verification steps in order. ALL must pass:
870
871#### 1. File Existence Check
872
873```bash
874# Verify all three reports exist
875test -f .work/test-coverage/gaps/test-gaps-report.html && echo "✓ HTML exists" || echo "✗ HTML MISSING"
876test -f .work/test-coverage/gaps/test-gaps-report.json && echo "✓ JSON exists" || echo "✗ JSON MISSING"
877test -f .work/test-coverage/gaps/test-gaps-summary.txt && echo "✓ Text exists" || echo "✗ Text MISSING"
878```
879
880**Required:** All three files must exist. If any are missing, regenerate them.
881
882#### 2. Dynamic Feature Extraction Verification
883
884```bash
885# Verify HTML has "Tested Features (Dynamic Feature Extraction)" section
886grep -q "Tested Features (Dynamic Feature Extraction)" .work/test-coverage/gaps/test-gaps-report.html && \
887 echo "✓ Feature extraction section present" || \
888 echo "✗ MISSING: Dynamic Feature Extraction section"
889
890# Verify JSON has feature data
891grep -q '"tested_features"' .work/test-coverage/gaps/test-gaps-report.json && \
892grep -q '"feature_gaps"' .work/test-coverage/gaps/test-gaps-report.json && \
893 echo "✓ Feature data in JSON" || \
894 echo "✗ MISSING: Feature data in JSON"
895
896# Verify Text has feature section
897grep -q "Tested Features" .work/test-coverage/gaps/test-gaps-summary.txt && \
898 echo "✓ Feature section in Text" || \
899 echo "✗ MISSING: Feature section in Text"
900```
901
902**Required:** Dynamic Feature Extraction must be present in all three reports. This is a critical requirement from Step 5a (lines 163-280).
903
904#### 3. HTML Coverage Dimension Verification
905
906**CRITICAL:** The HTML report must display ALL coverage dimension tables based on component type.
907
908```bash
909# For networking components, verify ALL 8 dimension tables exist
910grep -c "<h3>Platforms</h3>" .work/test-coverage/gaps/test-gaps-report.html
911grep -c "<h3>Protocols</h3>" .work/test-coverage/gaps/test-gaps-report.html
912grep -c "<h3>Service Types</h3>" .work/test-coverage/gaps/test-gaps-report.html
913grep -c "<h3>IP Stacks</h3>" .work/test-coverage/gaps/test-gaps-report.html
914grep -c "<h3>Network Layers</h3>" .work/test-coverage/gaps/test-gaps-report.html
915grep -c "<h3>Gateway Modes</h3>" .work/test-coverage/gaps/test-gaps-report.html
916grep -c "<h3>Topologies</h3>" .work/test-coverage/gaps/test-gaps-report.html
917grep -c "<h3>Scenarios</h3>" .work/test-coverage/gaps/test-gaps-report.html
918```
919
920**Expected Results:**
921- **Networking components:** 8 dimension tables (Platforms, Protocols, Service Types, IP Stacks, Network Layers, Gateway Modes, Topologies, Scenarios)
922- **Storage components:** 5 dimension tables (Platforms, Storage Classes, Volume Modes, Provisioners, Scenarios)
923- **Other components:** 2 dimension tables (Platforms, Scenarios)
924
925**Verification Command:**
926```bash
927# Count total coverage dimension tables
928TABLE_COUNT=$(grep -E "<h3>(Platforms|Protocols|Service Types|IP Stacks|Network Layers|Gateway Modes|Topologies|Scenarios|Storage Classes|Volume Modes|Provisioners)</h3>" .work/test-coverage/gaps/test-gaps-report.html | wc -l)
929echo "Coverage dimension tables found: $TABLE_COUNT"
930
931# Verify based on component type
932COMPONENT=$(grep -oP 'Component:</strong> \K[^<]+' .work/test-coverage/gaps/test-gaps-report.html | head -1 | tr -d '</p>')
933echo "Component type: $COMPONENT"
934
935case "$COMPONENT" in
936 Networking)
937 [ "$TABLE_COUNT" -eq 8 ] && echo "✓ All 8 networking dimensions present" || echo "✗ INCOMPLETE: Expected 8 tables, found $TABLE_COUNT"
938 ;;
939 Storage)
940 [ "$TABLE_COUNT" -eq 5 ] && echo "✓ All 5 storage dimensions present" || echo "✗ INCOMPLETE: Expected 5 tables, found $TABLE_COUNT"
941 ;;
942 *)
943 [ "$TABLE_COUNT" -eq 2 ] && echo "✓ All 2 generic dimensions present" || echo "✗ INCOMPLETE: Expected 2 tables, found $TABLE_COUNT"
944 ;;
945esac
946```
947
948**Required:** All component-specific dimension tables must be present. Missing tables indicate incomplete HTML generation.
949
950#### 4. Effort Estimates Verification
951
952```bash
953# Verify gaps include effort estimates
954grep -q "Effort Required" .work/test-coverage/gaps/test-gaps-report.html && \
955 echo "✓ Effort estimates in HTML" || \
956 echo "✗ MISSING: Effort estimates"
957```
958
959**Required:** Gaps must include effort estimates (Low, Medium, High) as specified in Step 5a.
960
961#### 5. Gap Analyzer Implementation Verification
962
963```bash
964# Verify analyzer has feature extraction function
965grep -q "def extract_features_from_tests" .work/test-coverage/gaps/gap_analyzer.py && \
966 echo "✓ Feature extraction function exists" || \
967 echo "✗ MISSING: extract_features_from_tests() function"
968
969# Verify all 5 feature categories are defined
970grep -q "Configuration Patterns" .work/test-coverage/gaps/gap_analyzer.py && \
971grep -q "Network Topology" .work/test-coverage/gaps/gap_analyzer.py && \
972grep -q "Lifecycle Operations" .work/test-coverage/gaps/gap_analyzer.py && \
973grep -q "Network Features" .work/test-coverage/gaps/gap_analyzer.py && \
974grep -q "Resilience & Recovery" .work/test-coverage/gaps/gap_analyzer.py && \
975 echo "✓ All 5 feature categories defined" || \
976 echo "✗ MISSING: Some feature categories not implemented"
977```
978
979**Required:** The gap analyzer must implement Dynamic Feature Extraction with all 5 categories.
980
981#### 6. JSON Structure Verification
982
983```python
984# Verify JSON has all required fields
985python3 << 'EOF'
986import json
987try:
988 with open('.work/test-coverage/gaps/test-gaps-report.json', 'r') as f:
989 data = json.load(f)
990
991 required_fields = [
992 ('analysis.file', lambda d: d['analysis']['file']),
993 ('analysis.component_type', lambda d: d['analysis']['component_type']),
994 ('analysis.test_count', lambda d: d['analysis']['test_count']),
995 ('analysis.tested_features', lambda d: d['analysis']['tested_features']),
996 ('analysis.feature_gaps', lambda d: d['analysis']['feature_gaps']),
997 ('scores.overall', lambda d: d['scores']['overall']),
998 ]
999
1000 missing = []
1001 for name, getter in required_fields:
1002 try:
1003 getter(data)
1004 print(f"✓ {name}")
1005 except (KeyError, TypeError):
1006 print(f"✗ MISSING: {name}")
1007 missing.append(name)
1008
1009 if not missing:
1010 print("\n✓ All required JSON fields present")
1011 else:
1012 print(f"\n✗ INCOMPLETE: Missing {len(missing)} required fields")
1013 exit(1)
1014except Exception as e:
1015 print(f"✗ ERROR: {e}")
1016 exit(1)
1017EOF
1018```
1019
1020**Required:** All required JSON fields must be present.
1021
1022### Validation Summary
1023
1024**Before declaring this skill complete:**
1025
10261. ✓ All three report files exist
10272. ✓ Dynamic Feature Extraction present in all reports
10283. ✓ HTML shows ALL component-specific coverage dimension tables
10294. ✓ Effort estimates included in gaps
10305. ✓ Gap analyzer implements feature extraction function
10316. ✓ JSON contains all required fields
1032
1033**If ANY check fails:** Fix the issue and re-run all validation checks. Do NOT declare the skill complete until ALL checks pass.
1034
1035## Error Handling
1036
1037### Common Issues and Solutions
1038
10391. **File not found**:
1040 - Verify the test file path is correct
1041 - Check that the file exists and is readable
1042
10432. **Invalid file format**:
1044 - Ensure the file is a Go test file (`.go`)
1045 - Check that the file uses Ginkgo framework (`g.It`, `g.Describe`)
1046
10473. **No test cases found**:
1048 - Verify the file contains Ginkgo test cases
1049 - Check for `g.It("...")` patterns
1050
1051## Examples
1052
1053### Example 1: Analyze Networking Test File
1054
1055```bash
1056# Run gap analyzer on a networking test file
1057cd /home/anusaxen/git/ai-helpers/plugins/test-coverage
1058python3 .work/test-coverage/gaps/gap_analyzer.py \
1059 /path/to/test/extended/networking/egressip_test.go \
1060 --output .work/gaps/
1061
1062# Output:
1063# Component detected: networking
1064# Test cases found: 25
1065# Overall coverage: 45.0%
1066# High-priority gaps: Azure platform, UDP protocol, Error handling scenarios
1067#
1068# Reports generated:
1069# HTML: .work/gaps/test-gaps-report.html
1070# JSON: .work/gaps/test-gaps-report.json
1071# Text: .work/gaps/test-gaps-summary.txt
1072```
1073
1074### Example 2: Analyze Storage Test File
1075
1076```bash
1077# Run gap analyzer on a storage test file
1078python3 .work/test-coverage/gaps/gap_analyzer.py \
1079 /path/to/test/extended/storage/persistent_volumes_test.go \
1080 --output .work/gaps/
1081
1082# Output:
1083# Component detected: storage
1084# Test cases found: 18
1085# Overall coverage: 52.0%
1086# High-priority gaps: ReadWriteMany volumes, CSI storage class, Snapshot scenarios
1087```
1088
1089### Example 3: Analyze from GitHub URL
1090
1091```bash
1092# Analyze file from GitHub raw URL
1093python3 .work/test-cove
1094
1095…(truncated)