simplecov-mcp 0.3.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE +21 -0
- data/README.md +173 -356
- data/docs/ADVANCED_USAGE.md +967 -0
- data/docs/ARCHITECTURE.md +79 -0
- data/docs/BRANCH_ONLY_COVERAGE.md +81 -0
- data/docs/CLI_USAGE.md +637 -0
- data/docs/DEVELOPMENT.md +82 -0
- data/docs/ERROR_HANDLING.md +93 -0
- data/docs/EXAMPLES.md +430 -0
- data/docs/INSTALLATION.md +352 -0
- data/docs/LIBRARY_API.md +635 -0
- data/docs/MCP_INTEGRATION.md +488 -0
- data/docs/TROUBLESHOOTING.md +276 -0
- data/docs/arch-decisions/001-x-arch-decision.md +93 -0
- data/docs/arch-decisions/002-x-arch-decision.md +157 -0
- data/docs/arch-decisions/003-x-arch-decision.md +163 -0
- data/docs/arch-decisions/004-x-arch-decision.md +199 -0
- data/docs/arch-decisions/005-x-arch-decision.md +187 -0
- data/docs/arch-decisions/README.md +60 -0
- data/docs/presentations/simplecov-mcp-presentation.md +249 -0
- data/exe/simplecov-mcp +4 -4
- data/lib/simplecov_mcp/app_context.rb +26 -0
- data/lib/simplecov_mcp/base_tool.rb +74 -0
- data/lib/simplecov_mcp/cli.rb +234 -0
- data/lib/simplecov_mcp/cli_config.rb +56 -0
- data/lib/simplecov_mcp/commands/base_command.rb +78 -0
- data/lib/simplecov_mcp/commands/command_factory.rb +39 -0
- data/lib/simplecov_mcp/commands/detailed_command.rb +24 -0
- data/lib/simplecov_mcp/commands/list_command.rb +13 -0
- data/lib/simplecov_mcp/commands/raw_command.rb +22 -0
- data/lib/simplecov_mcp/commands/summary_command.rb +24 -0
- data/lib/simplecov_mcp/commands/uncovered_command.rb +26 -0
- data/lib/simplecov_mcp/commands/version_command.rb +18 -0
- data/lib/simplecov_mcp/constants.rb +22 -0
- data/lib/simplecov_mcp/error_handler.rb +124 -0
- data/lib/simplecov_mcp/error_handler_factory.rb +31 -0
- data/lib/simplecov_mcp/errors.rb +179 -0
- data/lib/simplecov_mcp/formatters/source_formatter.rb +148 -0
- data/lib/simplecov_mcp/mcp_server.rb +40 -0
- data/lib/simplecov_mcp/mode_detector.rb +55 -0
- data/lib/simplecov_mcp/model.rb +300 -0
- data/lib/simplecov_mcp/option_normalizers.rb +92 -0
- data/lib/simplecov_mcp/option_parser_builder.rb +134 -0
- data/lib/simplecov_mcp/option_parsers/env_options_parser.rb +50 -0
- data/lib/simplecov_mcp/option_parsers/error_helper.rb +109 -0
- data/lib/simplecov_mcp/path_relativizer.rb +61 -0
- data/lib/simplecov_mcp/presenters/base_coverage_presenter.rb +44 -0
- data/lib/simplecov_mcp/presenters/coverage_detailed_presenter.rb +16 -0
- data/lib/simplecov_mcp/presenters/coverage_raw_presenter.rb +16 -0
- data/lib/simplecov_mcp/presenters/coverage_summary_presenter.rb +16 -0
- data/lib/simplecov_mcp/presenters/coverage_uncovered_presenter.rb +16 -0
- data/lib/simplecov_mcp/presenters/project_coverage_presenter.rb +52 -0
- data/lib/simplecov_mcp/resolvers/coverage_line_resolver.rb +126 -0
- data/lib/simplecov_mcp/resolvers/resolver_factory.rb +28 -0
- data/lib/simplecov_mcp/resolvers/resultset_path_resolver.rb +78 -0
- data/lib/simplecov_mcp/resultset_loader.rb +136 -0
- data/lib/simplecov_mcp/staleness_checker.rb +243 -0
- data/lib/{simple_cov_mcp → simplecov_mcp}/tools/all_files_coverage_tool.rb +31 -13
- data/lib/{simple_cov_mcp → simplecov_mcp}/tools/coverage_detailed_tool.rb +7 -7
- data/lib/{simple_cov_mcp → simplecov_mcp}/tools/coverage_raw_tool.rb +7 -7
- data/lib/{simple_cov_mcp → simplecov_mcp}/tools/coverage_summary_tool.rb +7 -7
- data/lib/simplecov_mcp/tools/coverage_table_tool.rb +90 -0
- data/lib/{simple_cov_mcp → simplecov_mcp}/tools/help_tool.rb +13 -4
- data/lib/{simple_cov_mcp → simplecov_mcp}/tools/uncovered_lines_tool.rb +7 -7
- data/lib/{simple_cov_mcp → simplecov_mcp}/tools/version_tool.rb +11 -3
- data/lib/simplecov_mcp/util.rb +82 -0
- data/lib/{simple_cov_mcp → simplecov_mcp}/version.rb +1 -1
- data/lib/simplecov_mcp.rb +144 -2
- data/spec/MCP_INTEGRATION_TESTS_README.md +111 -0
- data/spec/TIMESTAMPS.md +48 -0
- data/spec/all_files_coverage_tool_spec.rb +29 -25
- data/spec/base_tool_spec.rb +11 -10
- data/spec/cli/show_default_report_spec.rb +33 -0
- data/spec/cli_config_spec.rb +137 -0
- data/spec/cli_enumerated_options_spec.rb +68 -0
- data/spec/cli_error_spec.rb +105 -47
- data/spec/cli_source_spec.rb +82 -23
- data/spec/cli_spec.rb +140 -5
- data/spec/cli_success_predicate_spec.rb +141 -0
- data/spec/cli_table_spec.rb +1 -1
- data/spec/cli_usage_spec.rb +10 -26
- data/spec/commands/base_command_spec.rb +187 -0
- data/spec/commands/command_factory_spec.rb +72 -0
- data/spec/commands/detailed_command_spec.rb +48 -0
- data/spec/commands/raw_command_spec.rb +46 -0
- data/spec/commands/summary_command_spec.rb +47 -0
- data/spec/commands/uncovered_command_spec.rb +49 -0
- data/spec/constants_spec.rb +61 -0
- data/spec/coverage_table_tool_spec.rb +17 -33
- data/spec/error_handler_spec.rb +22 -13
- data/spec/error_mode_spec.rb +143 -0
- data/spec/errors_edge_cases_spec.rb +239 -0
- data/spec/errors_stale_spec.rb +2 -2
- data/spec/file_based_mcp_tools_spec.rb +99 -0
- data/spec/fixtures/project1/lib/bar.rb +0 -1
- data/spec/fixtures/project1/lib/foo.rb +0 -1
- data/spec/help_tool_spec.rb +11 -17
- data/spec/integration_spec.rb +845 -0
- data/spec/logging_fallback_spec.rb +128 -0
- data/spec/mcp_logging_spec.rb +44 -0
- data/spec/mcp_server_integration_spec.rb +23 -0
- data/spec/mcp_server_spec.rb +15 -4
- data/spec/mode_detector_spec.rb +148 -0
- data/spec/model_error_handling_spec.rb +210 -0
- data/spec/model_staleness_spec.rb +40 -10
- data/spec/option_normalizers_spec.rb +204 -0
- data/spec/option_parsers/env_options_parser_spec.rb +233 -0
- data/spec/option_parsers/error_helper_spec.rb +222 -0
- data/spec/path_relativizer_spec.rb +83 -0
- data/spec/presenters/coverage_detailed_presenter_spec.rb +19 -0
- data/spec/presenters/coverage_raw_presenter_spec.rb +15 -0
- data/spec/presenters/coverage_summary_presenter_spec.rb +15 -0
- data/spec/presenters/coverage_uncovered_presenter_spec.rb +16 -0
- data/spec/presenters/project_coverage_presenter_spec.rb +86 -0
- data/spec/resolvers/coverage_line_resolver_spec.rb +57 -0
- data/spec/resolvers/resolver_factory_spec.rb +61 -0
- data/spec/resolvers/resultset_path_resolver_spec.rb +55 -0
- data/spec/resultset_loader_spec.rb +167 -0
- data/spec/shared_examples/README.md +115 -0
- data/spec/shared_examples/coverage_presenter_examples.rb +66 -0
- data/spec/shared_examples/file_based_mcp_tools.rb +174 -0
- data/spec/shared_examples/mcp_tool_text_json_response.rb +16 -0
- data/spec/simple_cov_mcp_module_spec.rb +16 -0
- data/spec/simplecov_mcp_model_spec.rb +340 -9
- data/spec/simplecov_mcp_opts_spec.rb +182 -0
- data/spec/spec_helper.rb +147 -4
- data/spec/staleness_checker_spec.rb +373 -0
- data/spec/staleness_more_spec.rb +16 -13
- data/spec/support/mcp_runner.rb +64 -0
- data/spec/tools_error_handling_spec.rb +144 -0
- data/spec/util_spec.rb +109 -34
- data/spec/version_spec.rb +117 -9
- data/spec/version_tool_spec.rb +131 -10
- metadata +120 -63
- data/lib/simple_cov/mcp.rb +0 -9
- data/lib/simple_cov_mcp/base_tool.rb +0 -70
- data/lib/simple_cov_mcp/cli.rb +0 -390
- data/lib/simple_cov_mcp/error_handler.rb +0 -131
- data/lib/simple_cov_mcp/error_handler_factory.rb +0 -38
- data/lib/simple_cov_mcp/errors.rb +0 -176
- data/lib/simple_cov_mcp/mcp_server.rb +0 -30
- data/lib/simple_cov_mcp/model.rb +0 -104
- data/lib/simple_cov_mcp/staleness_checker.rb +0 -125
- data/lib/simple_cov_mcp/tools/coverage_table_tool.rb +0 -61
- data/lib/simple_cov_mcp/util.rb +0 -122
- data/lib/simple_cov_mcp.rb +0 -102
- data/spec/coverage_detailed_tool_spec.rb +0 -36
- data/spec/coverage_raw_tool_spec.rb +0 -32
- data/spec/coverage_summary_tool_spec.rb +0 -39
- data/spec/legacy_shim_spec.rb +0 -13
- data/spec/uncovered_lines_tool_spec.rb +0 -33
@@ -0,0 +1,93 @@
|
|
1
|
+
# Error Handling Guide
|
2
|
+
|
3
|
+
This tool provides different error handling behavior depending on how it's used:
|
4
|
+
|
5
|
+
## CLI Mode
|
6
|
+
|
7
|
+
When used as a command-line tool, errors are displayed as user-friendly messages without stack traces:
|
8
|
+
|
9
|
+
```bash
|
10
|
+
$ simplecov-mcp summary nonexistent.rb
|
11
|
+
File error: No coverage data found for the specified file
|
12
|
+
```
|
13
|
+
|
14
|
+
For debugging, use the `--error-mode trace` flag to see full stack traces:
|
15
|
+
|
16
|
+
```bash
|
17
|
+
$ simplecov-mcp --error-mode trace summary nonexistent.rb
|
18
|
+
```
|
19
|
+
|
20
|
+
## Library Mode
|
21
|
+
|
22
|
+
When used as a Ruby library, callers work with `SimpleCovMcp::CoverageModel` directly. Errors raise custom exception classes that can be caught and handled:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
handler = SimpleCovMcp::ErrorHandlerFactory.for_library # disables CLI-style logging
|
26
|
+
context = SimpleCovMcp.create_context(error_handler: handler)
|
27
|
+
|
28
|
+
SimpleCovMcp.with_context(context) do
|
29
|
+
model = SimpleCovMcp::CoverageModel.new
|
30
|
+
begin
|
31
|
+
model.summary_for('missing.rb')
|
32
|
+
rescue SimpleCovMcp::FileError => e
|
33
|
+
puts "Handled gracefully: #{e.user_friendly_message}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
```
|
37
|
+
|
38
|
+
Available exception classes:
|
39
|
+
- `SimpleCovMcp::Error` - Base error class
|
40
|
+
- `SimpleCovMcp::FileError` - File not found or access issues
|
41
|
+
- `SimpleCovMcp::CoverageDataError` - Invalid or missing coverage data
|
42
|
+
- `SimpleCovMcp::ConfigurationError` - Configuration problems
|
43
|
+
- `SimpleCovMcp::UsageError` - Command usage errors
|
44
|
+
|
45
|
+
## MCP Server Mode
|
46
|
+
|
47
|
+
When running as an MCP server, errors are handled internally and returned as structured responses to the MCP client. The MCP server uses:
|
48
|
+
|
49
|
+
- **Logging enabled** - Errors are logged to `simplecov_mcp.log` in the current directory for server debugging
|
50
|
+
- **Clean error messages** - User-friendly messages are returned to the client without stack traces by default
|
51
|
+
- **Structured responses** - Errors are returned as proper MCP tool responses, not exceptions
|
52
|
+
|
53
|
+
The MCP server automatically configures error handling appropriately for server usage.
|
54
|
+
|
55
|
+
## Custom Error Handlers
|
56
|
+
|
57
|
+
Library usage can opt into different logging behavior by installing a custom handler on the active context:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
handler = SimpleCovMcp::ErrorHandler.new(
|
61
|
+
log_errors: true, # Enable logging when embedding
|
62
|
+
show_stack_traces: false # Keep error messages clean
|
63
|
+
)
|
64
|
+
|
65
|
+
context = SimpleCovMcp.create_context(error_handler: handler)
|
66
|
+
|
67
|
+
SimpleCovMcp.with_context(context) do
|
68
|
+
model = SimpleCovMcp::CoverageModel.new
|
69
|
+
model.summary_for('lib/simplecov_mcp/model.rb')
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
## Stale Coverage Errors
|
74
|
+
|
75
|
+
When strict staleness checking is enabled (`--stale error`), the model (and CLI) raise a `CoverageDataStaleError` if a source file appears newer than the coverage data or the line counts differ.
|
76
|
+
|
77
|
+
- Enable per instance: `SimpleCovMcp::CoverageModel.new(staleness: 'error')`
|
78
|
+
|
79
|
+
The error message is detailed and includes:
|
80
|
+
|
81
|
+
- File and Coverage times (UTC and local) and line counts
|
82
|
+
- A delta indicating how much newer the file is than coverage
|
83
|
+
- The absolute path to the `.resultset.json` used
|
84
|
+
|
85
|
+
**Example excerpt:**
|
86
|
+
|
87
|
+
```
|
88
|
+
Coverage data stale: Coverage data appears stale for lib/foo.rb
|
89
|
+
File - time: 2025-09-16T14:03:22Z (local 2025-09-16T07:03:22-07:00), lines: 226
|
90
|
+
Coverage - time: 2025-09-15T21:11:09Z (local 2025-09-15T14:11:09-07:00), lines: 220
|
91
|
+
Delta - file is +123s newer than coverage
|
92
|
+
Resultset - /path/to/your/project/coverage/.resultset.json
|
93
|
+
```
|
data/docs/EXAMPLES.md
ADDED
@@ -0,0 +1,430 @@
|
|
1
|
+
# Examples and Recipes
|
2
|
+
|
3
|
+
Practical examples for common tasks with simplecov-mcp. Examples are organized by skill level and use case.
|
4
|
+
|
5
|
+
## Table of Contents
|
6
|
+
|
7
|
+
- [Quick Start Examples](#quick-start-examples)
|
8
|
+
- [CLI Examples](#cli-examples)
|
9
|
+
- [Ruby Library Examples](#ruby-library-examples)
|
10
|
+
- [AI Assistant Prompts](#ai-assistant-prompts)
|
11
|
+
- [CI/CD Integration](#cicd-integration)
|
12
|
+
- [Advanced Usage](#advanced-usage)
|
13
|
+
|
14
|
+
## Quick Start Examples
|
15
|
+
|
16
|
+
### View All Coverage
|
17
|
+
|
18
|
+
```bash
|
19
|
+
# Default: show all files, worst coverage first
|
20
|
+
simplecov-mcp
|
21
|
+
|
22
|
+
# Show files with best coverage first
|
23
|
+
simplecov-mcp list --sort-order descending
|
24
|
+
|
25
|
+
# Export to JSON for processing
|
26
|
+
simplecov-mcp list --json > coverage-report.json
|
27
|
+
```
|
28
|
+
|
29
|
+
### Check Specific File
|
30
|
+
|
31
|
+
```bash
|
32
|
+
# Quick summary
|
33
|
+
simplecov-mcp summary lib/my_class.rb
|
34
|
+
|
35
|
+
# See which lines aren't covered
|
36
|
+
simplecov-mcp uncovered lib/my_class.rb
|
37
|
+
|
38
|
+
# View uncovered code with context
|
39
|
+
simplecov-mcp uncovered lib/my_class.rb --source=uncovered --source-context 3
|
40
|
+
```
|
41
|
+
|
42
|
+
### Find Coverage Gaps
|
43
|
+
|
44
|
+
```bash
|
45
|
+
# Files with worst coverage
|
46
|
+
simplecov-mcp list | head -10
|
47
|
+
|
48
|
+
# Only show files below 80%
|
49
|
+
simplecov-mcp list --json | jq '.files[] | select(.percentage < 80)'
|
50
|
+
|
51
|
+
# Check specific directory
|
52
|
+
simplecov-mcp list --tracked-globs "lib/services/**/*.rb"
|
53
|
+
```
|
54
|
+
|
55
|
+
## CLI Examples
|
56
|
+
|
57
|
+
### Coverage Analysis
|
58
|
+
|
59
|
+
**Find files needing attention:**
|
60
|
+
```bash
|
61
|
+
# Show only lib/ files
|
62
|
+
simplecov-mcp list --tracked-globs "lib/**/*.rb"
|
63
|
+
|
64
|
+
# Get uncovered line counts
|
65
|
+
simplecov-mcp list --json | jq '.files[] | {file: .file, uncovered: (.total - .covered)}'
|
66
|
+
```
|
67
|
+
|
68
|
+
**Detailed investigation:**
|
69
|
+
```bash
|
70
|
+
# See detailed hit counts
|
71
|
+
simplecov-mcp detailed lib/auth_service.rb
|
72
|
+
|
73
|
+
# Show full source with coverage markers
|
74
|
+
simplecov-mcp summary lib/auth_service.rb --source=full
|
75
|
+
|
76
|
+
# Focus on uncovered areas only
|
77
|
+
simplecov-mcp uncovered lib/auth_service.rb --source=uncovered --source-context 5
|
78
|
+
```
|
79
|
+
|
80
|
+
### Working with JSON Output
|
81
|
+
|
82
|
+
**Parse and filter:**
|
83
|
+
```bash
|
84
|
+
# Files below threshold
|
85
|
+
simplecov-mcp list --json | jq '.files[] | select(.percentage < 90) | {file, coverage: .percentage}'
|
86
|
+
|
87
|
+
# Count total uncovered lines
|
88
|
+
simplecov-mcp list --json | jq '[.files[] | (.total - .covered)] | add'
|
89
|
+
|
90
|
+
# Group by directory
|
91
|
+
simplecov-mcp list --json | jq 'group_by(.file | split("/")[0]) | map({dir: .[0].file | split("/")[0], avg: (map(.percentage) | add / length)})'
|
92
|
+
```
|
93
|
+
|
94
|
+
**Generate reports:**
|
95
|
+
```bash
|
96
|
+
# Create markdown table
|
97
|
+
echo "| File | Coverage |" > report.md
|
98
|
+
echo "|------|----------|" >> report.md
|
99
|
+
simplecov-mcp list --json | jq -r '.files[] | "| \(.file) | \(.percentage)% |"' >> report.md
|
100
|
+
|
101
|
+
# Export for spreadsheet
|
102
|
+
simplecov-mcp list --json | jq -r '.files[] | [.file, .percentage] | @csv' > coverage.csv
|
103
|
+
```
|
104
|
+
|
105
|
+
## Ruby Library Examples
|
106
|
+
|
107
|
+
### Basic Usage
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
require "simplecov_mcp"
|
111
|
+
|
112
|
+
model = SimpleCovMcp::CoverageModel.new
|
113
|
+
|
114
|
+
# Get all files with coverage
|
115
|
+
files = model.all_files
|
116
|
+
puts "Total files: #{files.length}"
|
117
|
+
puts "Average coverage: #{files.sum { |f| f['percentage'] } / files.length}%"
|
118
|
+
|
119
|
+
# Check specific file
|
120
|
+
summary = model.summary_for("lib/auth_service.rb")
|
121
|
+
puts "Coverage: #{summary['summary']['pct']}%"
|
122
|
+
|
123
|
+
# Find uncovered lines
|
124
|
+
uncovered = model.uncovered_for("lib/auth_service.rb")
|
125
|
+
puts "Uncovered lines: #{uncovered['uncovered'].join(', ')}"
|
126
|
+
```
|
127
|
+
|
128
|
+
### Filtering and Analysis
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
require "simplecov_mcp"
|
132
|
+
|
133
|
+
model = SimpleCovMcp::CoverageModel.new
|
134
|
+
all_files = model.all_files
|
135
|
+
|
136
|
+
# Find files below threshold
|
137
|
+
THRESHOLD = 80.0
|
138
|
+
low_coverage = all_files.select { |f| f['percentage'] < THRESHOLD }
|
139
|
+
|
140
|
+
if low_coverage.any?
|
141
|
+
puts "Files below #{THRESHOLD}%:"
|
142
|
+
low_coverage.each do |file|
|
143
|
+
puts " #{file['file']}: #{file['percentage']}%"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Group by directory
|
148
|
+
by_dir = all_files.group_by { |f| File.dirname(f['file']) }
|
149
|
+
by_dir.each do |dir, files|
|
150
|
+
avg = files.sum { |f| f['percentage'] } / files.length
|
151
|
+
puts "#{dir}: #{avg.round(2)}% (#{files.length} files)"
|
152
|
+
end
|
153
|
+
```
|
154
|
+
|
155
|
+
### Custom Formatting
|
156
|
+
|
157
|
+
```ruby
|
158
|
+
require "simplecov_mcp"
|
159
|
+
|
160
|
+
model = SimpleCovMcp::CoverageModel.new
|
161
|
+
all_files = model.all_files
|
162
|
+
|
163
|
+
# Filter to specific directory
|
164
|
+
lib_files = all_files.select { |f| f['file'].start_with?('lib/') }
|
165
|
+
|
166
|
+
# Generate custom table
|
167
|
+
table = model.format_table(lib_files, sort_order: :ascending)
|
168
|
+
puts table
|
169
|
+
|
170
|
+
# Or create your own format
|
171
|
+
lib_files.each do |file|
|
172
|
+
status = file['percentage'] >= 90 ? '✓' : '⚠'
|
173
|
+
puts "#{status} #{file['file']}: #{file['percentage']}%"
|
174
|
+
end
|
175
|
+
```
|
176
|
+
|
177
|
+
## AI Assistant Prompts
|
178
|
+
|
179
|
+
### Coverage Analysis
|
180
|
+
|
181
|
+
```
|
182
|
+
Using simplecov-mcp, show me a table of all files sorted by coverage percentage.
|
183
|
+
```
|
184
|
+
|
185
|
+
```
|
186
|
+
Using simplecov-mcp, find the 10 files with the lowest coverage and create a markdown report with:
|
187
|
+
1. File path
|
188
|
+
2. Current coverage %
|
189
|
+
3. Number of uncovered lines
|
190
|
+
```
|
191
|
+
|
192
|
+
```
|
193
|
+
Using simplecov-mcp, analyze the lib/services/ directory and identify which files should be prioritized for additional testing based on coverage gaps and file complexity.
|
194
|
+
```
|
195
|
+
|
196
|
+
### Finding Specific Issues
|
197
|
+
|
198
|
+
```
|
199
|
+
Using simplecov-mcp, show me the uncovered lines in lib/auth_service.rb with 5 lines of context around each uncovered block.
|
200
|
+
```
|
201
|
+
|
202
|
+
```
|
203
|
+
Using simplecov-mcp, find all files in lib/models/ with less than 80% coverage and list the specific uncovered line numbers for each.
|
204
|
+
```
|
205
|
+
|
206
|
+
### Test Generation
|
207
|
+
|
208
|
+
```
|
209
|
+
Using simplecov-mcp, identify the uncovered lines in lib/payment_processor.rb and write RSpec tests to cover them.
|
210
|
+
```
|
211
|
+
|
212
|
+
```
|
213
|
+
Using simplecov-mcp, analyze coverage gaps in the lib/api/ directory and generate a test plan prioritizing:
|
214
|
+
1. Public API methods
|
215
|
+
2. Error handling paths
|
216
|
+
3. Edge cases
|
217
|
+
```
|
218
|
+
|
219
|
+
### Reporting
|
220
|
+
|
221
|
+
```
|
222
|
+
Using simplecov-mcp, create a coverage report showing:
|
223
|
+
- Overall project coverage percentage
|
224
|
+
- Top 5 files with worst coverage
|
225
|
+
- Recommended next steps to improve coverage
|
226
|
+
|
227
|
+
Format as markdown.
|
228
|
+
```
|
229
|
+
|
230
|
+
## CI/CD Integration
|
231
|
+
|
232
|
+
### GitHub Actions
|
233
|
+
|
234
|
+
**Fail on low coverage:**
|
235
|
+
```yaml
|
236
|
+
name: Coverage Check
|
237
|
+
|
238
|
+
on: [push, pull_request]
|
239
|
+
|
240
|
+
jobs:
|
241
|
+
coverage:
|
242
|
+
runs-on: ubuntu-latest
|
243
|
+
steps:
|
244
|
+
- uses: actions/checkout@v3
|
245
|
+
|
246
|
+
- name: Setup Ruby
|
247
|
+
uses: ruby/setup-ruby@v1
|
248
|
+
with:
|
249
|
+
ruby-version: 3.3
|
250
|
+
bundler-cache: true
|
251
|
+
|
252
|
+
- name: Run tests
|
253
|
+
run: bundle exec rspec
|
254
|
+
|
255
|
+
- name: Install simplecov-mcp
|
256
|
+
run: gem install simplecov-mcp
|
257
|
+
|
258
|
+
- name: Check coverage threshold
|
259
|
+
run: |
|
260
|
+
simplecov-mcp list --json > coverage.json
|
261
|
+
BELOW_THRESHOLD=$(jq '[.files[] | select(.percentage < 80)] | length' coverage.json)
|
262
|
+
if [ "$BELOW_THRESHOLD" -gt 0 ]; then
|
263
|
+
echo "❌ $BELOW_THRESHOLD files below 80% coverage"
|
264
|
+
jq -r '.files[] | select(.percentage < 80) | "\(.file): \(.percentage)%"' coverage.json
|
265
|
+
exit 1
|
266
|
+
fi
|
267
|
+
echo "✓ All files meet coverage threshold"
|
268
|
+
|
269
|
+
- name: Upload coverage report
|
270
|
+
uses: actions/upload-artifact@v3
|
271
|
+
with:
|
272
|
+
name: coverage-report
|
273
|
+
path: coverage.json
|
274
|
+
```
|
275
|
+
|
276
|
+
**Check for stale coverage:**
|
277
|
+
```yaml
|
278
|
+
- name: Verify coverage is fresh
|
279
|
+
run: simplecov-mcp --stale error || exit 1
|
280
|
+
```
|
281
|
+
|
282
|
+
### GitLab CI
|
283
|
+
|
284
|
+
```yaml
|
285
|
+
test:
|
286
|
+
image: ruby:3.3
|
287
|
+
before_script:
|
288
|
+
- gem install simplecov-mcp
|
289
|
+
script:
|
290
|
+
- bundle exec rspec
|
291
|
+
- simplecov-mcp --stale error
|
292
|
+
artifacts:
|
293
|
+
paths:
|
294
|
+
- coverage/
|
295
|
+
reports:
|
296
|
+
coverage_report:
|
297
|
+
coverage_format: simplecov
|
298
|
+
path: coverage/.resultset.json
|
299
|
+
```
|
300
|
+
|
301
|
+
### Custom Success Predicate
|
302
|
+
|
303
|
+
```ruby
|
304
|
+
# coverage_policy.rb
|
305
|
+
->(model) do
|
306
|
+
all_files = model.all_files
|
307
|
+
|
308
|
+
# Must have at least 80% average coverage
|
309
|
+
avg_coverage = all_files.sum { |f| f['percentage'] } / all_files.length
|
310
|
+
return false if avg_coverage < 80.0
|
311
|
+
|
312
|
+
# No files below 60%
|
313
|
+
return false if all_files.any? { |f| f['percentage'] < 60.0 }
|
314
|
+
|
315
|
+
# lib/ files must average 90%
|
316
|
+
lib_files = all_files.select { |f| f['file'].start_with?('lib/') }
|
317
|
+
lib_avg = lib_files.sum { |f| f['percentage'] } / lib_files.length
|
318
|
+
return false if lib_avg < 90.0
|
319
|
+
|
320
|
+
true
|
321
|
+
end
|
322
|
+
```
|
323
|
+
|
324
|
+
```bash
|
325
|
+
# Use in CI
|
326
|
+
simplecov-mcp --success-predicate coverage_policy.rb
|
327
|
+
```
|
328
|
+
|
329
|
+
## Advanced Usage
|
330
|
+
|
331
|
+
### Directory-Level Analysis
|
332
|
+
|
333
|
+
```ruby
|
334
|
+
require "simplecov_mcp"
|
335
|
+
|
336
|
+
model = SimpleCovMcp::CoverageModel.new
|
337
|
+
all_files = model.all_files
|
338
|
+
|
339
|
+
# Calculate coverage by directory
|
340
|
+
by_directory = all_files.group_by { |f| f['file'].split('/')[0..1].join('/') }
|
341
|
+
|
342
|
+
results = by_directory.map do |dir, files|
|
343
|
+
total_lines = files.sum { |f| f['total'] }
|
344
|
+
covered_lines = files.sum { |f| f['covered'] }
|
345
|
+
percentage = (covered_lines.to_f / total_lines * 100).round(2)
|
346
|
+
|
347
|
+
{
|
348
|
+
directory: dir,
|
349
|
+
files: files.length,
|
350
|
+
coverage: percentage,
|
351
|
+
covered: covered_lines,
|
352
|
+
total: total_lines
|
353
|
+
}
|
354
|
+
end
|
355
|
+
|
356
|
+
# Sort by coverage ascending
|
357
|
+
results.sort_by { |r| r[:coverage] }.each do |r|
|
358
|
+
puts "#{r[:directory]}: #{r[:coverage]}% (#{r[:files]} files)"
|
359
|
+
end
|
360
|
+
```
|
361
|
+
|
362
|
+
### Coverage Delta Tracking
|
363
|
+
|
364
|
+
```ruby
|
365
|
+
require "simplecov_mcp"
|
366
|
+
require "json"
|
367
|
+
|
368
|
+
# Save current coverage
|
369
|
+
model = SimpleCovMcp::CoverageModel.new
|
370
|
+
current = model.all_files
|
371
|
+
|
372
|
+
File.write("coverage_baseline.json", JSON.pretty_generate(current))
|
373
|
+
|
374
|
+
# Later, compare with baseline
|
375
|
+
baseline = JSON.parse(File.read("coverage_baseline.json"))
|
376
|
+
|
377
|
+
current.each do |file|
|
378
|
+
baseline_file = baseline.find { |f| f['file'] == file['file'] }
|
379
|
+
next unless baseline_file
|
380
|
+
|
381
|
+
delta = file['percentage'] - baseline_file['percentage']
|
382
|
+
if delta.abs > 0.1 # Changed by more than 0.1%
|
383
|
+
symbol = delta > 0 ? '↑' : '↓'
|
384
|
+
puts "#{symbol} #{file['file']}: #{baseline_file['percentage']}% → #{file['percentage']}%"
|
385
|
+
end
|
386
|
+
end
|
387
|
+
```
|
388
|
+
|
389
|
+
### Integration with Code Review
|
390
|
+
|
391
|
+
```ruby
|
392
|
+
# pr_coverage_check.rb
|
393
|
+
require "simplecov_mcp"
|
394
|
+
require "json"
|
395
|
+
|
396
|
+
model = SimpleCovMcp::CoverageModel.new
|
397
|
+
|
398
|
+
# Get changed files from PR (example using git)
|
399
|
+
changed_files = `git diff --name-only origin/main`.split("\n")
|
400
|
+
changed_files.select! { |f| f.end_with?('.rb') }
|
401
|
+
|
402
|
+
puts "## Coverage Report for Changed Files\n\n"
|
403
|
+
puts "| File | Coverage | Status |"
|
404
|
+
puts "|------|----------|--------|"
|
405
|
+
|
406
|
+
changed_files.each do |file|
|
407
|
+
begin
|
408
|
+
summary = model.summary_for(file)
|
409
|
+
pct = summary['summary']['pct']
|
410
|
+
status = pct >= 80 ? '✅' : '⚠️'
|
411
|
+
puts "| #{file} | #{pct}% | #{status} |"
|
412
|
+
rescue
|
413
|
+
puts "| #{file} | N/A | ❌ No coverage |"
|
414
|
+
end
|
415
|
+
end
|
416
|
+
```
|
417
|
+
|
418
|
+
## Example Scripts
|
419
|
+
|
420
|
+
The [`/examples`](/examples) directory contains runnable scripts:
|
421
|
+
|
422
|
+
- **[filter_and_table_demo.rb](/examples/filter_and_table_demo.rb)** - Filter and format coverage data
|
423
|
+
- **[success_predicates/](/examples/success_predicates/)** - Custom coverage policy examples
|
424
|
+
|
425
|
+
## Related Documentation
|
426
|
+
|
427
|
+
- [CLI Usage Guide](CLI_USAGE.md) - Complete command reference
|
428
|
+
- [Library API Guide](LIBRARY_API.md) - Ruby API documentation
|
429
|
+
- [MCP Integration](MCP_INTEGRATION.md) - AI assistant setup
|
430
|
+
- [Troubleshooting](TROUBLESHOOTING.md) - Common issues
|