cov-loupe 3.0.0 → 4.0.0.pre
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/AGENTS.md +230 -0
- data/CLAUDE.md +5 -0
- data/CODE_OF_CONDUCT.md +62 -0
- data/CONTRIBUTING.md +102 -0
- data/GEMINI.md +5 -0
- data/README.md +154 -51
- data/RELEASE_NOTES.md +452 -0
- data/dev/images/cov-loupe-icon-lores.png +0 -0
- data/dev/images/cov-loupe-icon-square.png +0 -0
- data/dev/images/cov-loupe-icon.png +0 -0
- data/dev/images/cov-loupe-logo.png +0 -0
- data/dev/prompts/README.md +74 -0
- data/dev/prompts/archive/architectural-review-and-actions-prompt.md +53 -0
- data/dev/prompts/archive/investigate-and-report-issues-prompt.md +33 -0
- data/dev/prompts/archive/produce-action-items-prompt.md +25 -0
- data/dev/prompts/guidelines/ai-code-evaluator-guidelines.md +337 -0
- data/dev/prompts/improve/refactor-test-suite.md +18 -0
- data/dev/prompts/improve/simplify-code-logic.md +133 -0
- data/dev/prompts/improve/update-documentation.md +21 -0
- data/dev/prompts/review/comprehensive-codebase-review.md +176 -0
- data/dev/prompts/review/identify-action-items.md +143 -0
- data/dev/prompts/review/verify-code-changes.md +54 -0
- data/dev/prompts/validate/create-screencast-outline.md +234 -0
- data/dev/prompts/validate/test-documentation-examples.md +180 -0
- data/docs/QUICKSTART.md +63 -0
- data/docs/assets/images/cov-loupe-logo-lores.png +0 -0
- data/docs/assets/images/cov-loupe-logo.png +0 -0
- data/docs/assets/images/favicon.png +0 -0
- data/docs/assets/stylesheets/branding.css +16 -0
- data/docs/assets/stylesheets/extra.css +15 -0
- data/docs/code_of_conduct.md +1 -0
- data/docs/contributing.md +1 -0
- data/docs/dev/ARCHITECTURE.md +56 -11
- data/docs/dev/DEVELOPMENT.md +116 -12
- data/docs/dev/FUTURE_ENHANCEMENTS.md +14 -0
- data/docs/dev/README.md +3 -2
- data/docs/dev/RELEASING.md +2 -0
- data/docs/dev/arch-decisions/README.md +10 -7
- data/docs/dev/arch-decisions/application-architecture.md +259 -0
- data/docs/dev/arch-decisions/coverage-data-quality.md +193 -0
- data/docs/dev/arch-decisions/output-character-mode.md +217 -0
- data/docs/dev/arch-decisions/path-resolution.md +90 -0
- data/docs/dev/arch-decisions/{004-x-arch-decision.md → policy-validation.md} +32 -28
- data/docs/dev/arch-decisions/{005-x-arch-decision.md → simplecov-integration.md} +47 -44
- data/docs/dev/presentations/cov-loupe-presentation.md +15 -13
- data/docs/examples/mcp-inputs.md +3 -0
- data/docs/examples/prompts.md +3 -0
- data/docs/examples/success_predicates.md +3 -0
- data/docs/fixtures/demo_project/.resultset.json +170 -0
- data/docs/fixtures/demo_project/README.md +6 -0
- data/docs/fixtures/demo_project/app/controllers/admin/audit_logs_controller.rb +19 -0
- data/docs/fixtures/demo_project/app/controllers/orders_controller.rb +26 -0
- data/docs/fixtures/demo_project/app/models/order.rb +20 -0
- data/docs/fixtures/demo_project/app/models/user.rb +19 -0
- data/docs/fixtures/demo_project/lib/api/client.rb +22 -0
- data/docs/fixtures/demo_project/lib/ops/jobs/cleanup_job.rb +16 -0
- data/docs/fixtures/demo_project/lib/ops/jobs/report_job.rb +17 -0
- data/docs/fixtures/demo_project/lib/payments/processor.rb +15 -0
- data/docs/fixtures/demo_project/lib/payments/refund_service.rb +15 -0
- data/docs/fixtures/demo_project/lib/payments/reporting/exporter.rb +16 -0
- data/docs/index.md +1 -0
- data/docs/license.md +3 -0
- data/docs/release_notes.md +3 -0
- data/docs/user/ADVANCED_USAGE.md +208 -115
- data/docs/user/CLI_FALLBACK_FOR_LLMS.md +2 -0
- data/docs/user/CLI_USAGE.md +276 -101
- data/docs/user/ERROR_HANDLING.md +4 -4
- data/docs/user/EXAMPLES.md +121 -128
- data/docs/user/INSTALLATION.md +9 -28
- data/docs/user/LIBRARY_API.md +227 -122
- data/docs/user/MCP_INTEGRATION.md +114 -203
- data/docs/user/README.md +5 -1
- data/docs/user/TROUBLESHOOTING.md +49 -27
- data/docs/user/installing-a-prelease-version-of-covloupe.md +43 -0
- data/docs/user/{V2-BREAKING-CHANGES.md → migrations/MIGRATING_TO_V2.md} +62 -72
- data/docs/user/migrations/MIGRATING_TO_V3.md +72 -0
- data/docs/user/migrations/MIGRATING_TO_V4.md +591 -0
- data/docs/user/migrations/README.md +22 -0
- data/docs/user/prompts/README.md +9 -0
- data/docs/user/prompts/non-web-coverage-analysis-prompt.md +103 -0
- data/docs/user/prompts/rails-coverage-analysis-prompt.md +94 -0
- data/docs/user/prompts/use-cli-not-mcp-prompt.md +53 -0
- data/examples/cli_demo.sh +77 -0
- data/examples/filter_and_table_demo-output.md +114 -0
- data/examples/filter_and_table_demo.rb +174 -0
- data/examples/fixtures/demo_project/coverage/.resultset.json +10 -0
- data/examples/mcp-inputs/README.md +66 -0
- data/examples/mcp-inputs/coverage_detailed.json +1 -0
- data/examples/mcp-inputs/coverage_raw.json +1 -0
- data/examples/mcp-inputs/coverage_summary.json +1 -0
- data/examples/mcp-inputs/list.json +1 -0
- data/examples/mcp-inputs/uncovered_lines.json +1 -0
- data/examples/prompts/README.md +27 -0
- data/examples/prompts/custom_resultset.txt +2 -0
- data/examples/prompts/detailed_with_source.txt +2 -0
- data/examples/prompts/list_lowest.txt +2 -0
- data/examples/prompts/summary.txt +2 -0
- data/examples/prompts/uncovered.txt +2 -0
- data/examples/success_predicates/README.md +198 -0
- data/examples/success_predicates/all_files_above_threshold_predicate.rb +21 -0
- data/examples/success_predicates/directory_specific_thresholds_predicate.rb +30 -0
- data/examples/success_predicates/project_coverage_minimum_predicate.rb +6 -0
- data/lib/cov_loupe/base_tool.rb +229 -20
- data/lib/cov_loupe/cli.rb +132 -23
- data/lib/cov_loupe/commands/base_command.rb +25 -6
- data/lib/cov_loupe/commands/command_factory.rb +0 -1
- data/lib/cov_loupe/commands/detailed_command.rb +10 -5
- data/lib/cov_loupe/commands/list_command.rb +2 -1
- data/lib/cov_loupe/commands/raw_command.rb +7 -5
- data/lib/cov_loupe/commands/summary_command.rb +12 -7
- data/lib/cov_loupe/commands/totals_command.rb +74 -10
- data/lib/cov_loupe/commands/uncovered_command.rb +7 -5
- data/lib/cov_loupe/commands/validate_command.rb +11 -3
- data/lib/cov_loupe/commands/version_command.rb +6 -4
- data/lib/cov_loupe/{app_config.rb → config/app_config.rb} +13 -5
- data/lib/cov_loupe/config/app_context.rb +43 -0
- data/lib/cov_loupe/config/boolean_type.rb +91 -0
- data/lib/cov_loupe/config/logger.rb +92 -0
- data/lib/cov_loupe/{option_normalizers.rb → config/option_normalizers.rb} +55 -24
- data/lib/cov_loupe/{option_parser_builder.rb → config/option_parser_builder.rb} +46 -24
- data/lib/cov_loupe/coverage/coverage_calculator.rb +53 -0
- data/lib/cov_loupe/coverage/coverage_reporter.rb +63 -0
- data/lib/cov_loupe/coverage/coverage_table_formatter.rb +133 -0
- data/lib/cov_loupe/{error_handler.rb → errors/error_handler.rb} +21 -33
- data/lib/cov_loupe/{errors.rb → errors/errors.rb} +48 -71
- data/lib/cov_loupe/formatters/formatters.rb +75 -0
- data/lib/cov_loupe/formatters/source_formatter.rb +18 -7
- data/lib/cov_loupe/formatters/table_formatter.rb +80 -0
- data/lib/cov_loupe/loaders/all.rb +15 -0
- data/lib/cov_loupe/loaders/all_cli.rb +10 -0
- data/lib/cov_loupe/loaders/all_mcp.rb +23 -0
- data/lib/cov_loupe/loaders/resultset_loader.rb +147 -0
- data/lib/cov_loupe/mcp_server.rb +3 -2
- data/lib/cov_loupe/model/model.rb +520 -0
- data/lib/cov_loupe/model/model_data.rb +13 -0
- data/lib/cov_loupe/model/model_data_cache.rb +116 -0
- data/lib/cov_loupe/option_parsers/env_options_parser.rb +17 -6
- data/lib/cov_loupe/option_parsers/error_helper.rb +16 -10
- data/lib/cov_loupe/output_chars.rb +192 -0
- data/lib/cov_loupe/paths/glob_utils.rb +100 -0
- data/lib/cov_loupe/{path_relativizer.rb → paths/path_relativizer.rb} +5 -13
- data/lib/cov_loupe/paths/path_utils.rb +265 -0
- data/lib/cov_loupe/paths/volume_case_sensitivity.rb +173 -0
- data/lib/cov_loupe/presenters/base_coverage_presenter.rb +9 -13
- data/lib/cov_loupe/presenters/coverage_payload_presenter.rb +21 -0
- data/lib/cov_loupe/presenters/payload_caching.rb +23 -0
- data/lib/cov_loupe/presenters/project_coverage_presenter.rb +73 -21
- data/lib/cov_loupe/presenters/project_totals_presenter.rb +16 -10
- data/lib/cov_loupe/repositories/coverage_repository.rb +149 -0
- data/lib/cov_loupe/resolvers/coverage_line_resolver.rb +90 -76
- data/lib/cov_loupe/resolvers/{resolver_factory.rb → resolver_helpers.rb} +6 -5
- data/lib/cov_loupe/resolvers/resultset_path_resolver.rb +40 -12
- data/lib/cov_loupe/scripts/command_execution.rb +113 -0
- data/lib/cov_loupe/scripts/latest_ci_status.rb +97 -0
- data/lib/cov_loupe/scripts/pre_release_check.rb +164 -0
- data/lib/cov_loupe/scripts/setup_doc_server.rb +23 -0
- data/lib/cov_loupe/scripts/start_doc_server.rb +24 -0
- data/lib/cov_loupe/staleness/stale_status.rb +23 -0
- data/lib/cov_loupe/staleness/staleness_checker.rb +328 -0
- data/lib/cov_loupe/staleness/staleness_message_formatter.rb +91 -0
- data/lib/cov_loupe/tools/coverage_detailed_tool.rb +14 -15
- data/lib/cov_loupe/tools/coverage_raw_tool.rb +14 -14
- data/lib/cov_loupe/tools/coverage_summary_tool.rb +16 -16
- data/lib/cov_loupe/tools/coverage_table_tool.rb +139 -21
- data/lib/cov_loupe/tools/coverage_totals_tool.rb +31 -13
- data/lib/cov_loupe/tools/help_tool.rb +16 -20
- data/lib/cov_loupe/tools/list_tool.rb +65 -0
- data/lib/cov_loupe/tools/uncovered_lines_tool.rb +14 -14
- data/lib/cov_loupe/tools/validate_tool.rb +18 -24
- data/lib/cov_loupe/tools/version_tool.rb +8 -3
- data/lib/cov_loupe/version.rb +1 -1
- data/lib/cov_loupe.rb +83 -55
- metadata +184 -154
- data/docs/dev/BRANCH_ONLY_COVERAGE.md +0 -158
- data/docs/dev/arch-decisions/001-x-arch-decision.md +0 -95
- data/docs/dev/arch-decisions/002-x-arch-decision.md +0 -159
- data/docs/dev/arch-decisions/003-x-arch-decision.md +0 -165
- data/lib/cov_loupe/app_context.rb +0 -26
- data/lib/cov_loupe/constants.rb +0 -22
- data/lib/cov_loupe/coverage_reporter.rb +0 -31
- data/lib/cov_loupe/formatters.rb +0 -51
- data/lib/cov_loupe/mode_detector.rb +0 -56
- data/lib/cov_loupe/model.rb +0 -339
- data/lib/cov_loupe/presenters/coverage_detailed_presenter.rb +0 -14
- data/lib/cov_loupe/presenters/coverage_raw_presenter.rb +0 -14
- data/lib/cov_loupe/presenters/coverage_summary_presenter.rb +0 -14
- data/lib/cov_loupe/presenters/coverage_uncovered_presenter.rb +0 -14
- data/lib/cov_loupe/resultset_loader.rb +0 -131
- data/lib/cov_loupe/staleness_checker.rb +0 -247
- data/lib/cov_loupe/table_formatter.rb +0 -64
- data/lib/cov_loupe/tools/all_files_coverage_tool.rb +0 -51
- data/lib/cov_loupe/util.rb +0 -88
- data/spec/MCP_INTEGRATION_TESTS_README.md +0 -111
- data/spec/TIMESTAMPS.md +0 -48
- data/spec/all_files_coverage_tool_spec.rb +0 -53
- data/spec/app_config_spec.rb +0 -142
- data/spec/base_tool_spec.rb +0 -62
- data/spec/cli/show_default_report_spec.rb +0 -33
- data/spec/cli_enumerated_options_spec.rb +0 -90
- data/spec/cli_error_spec.rb +0 -184
- data/spec/cli_format_spec.rb +0 -123
- data/spec/cli_json_options_spec.rb +0 -50
- data/spec/cli_source_spec.rb +0 -44
- data/spec/cli_spec.rb +0 -192
- data/spec/cli_table_spec.rb +0 -28
- data/spec/cli_usage_spec.rb +0 -42
- data/spec/commands/base_command_spec.rb +0 -107
- data/spec/commands/command_factory_spec.rb +0 -76
- data/spec/commands/detailed_command_spec.rb +0 -34
- data/spec/commands/list_command_spec.rb +0 -28
- data/spec/commands/raw_command_spec.rb +0 -69
- data/spec/commands/summary_command_spec.rb +0 -34
- data/spec/commands/totals_command_spec.rb +0 -34
- data/spec/commands/uncovered_command_spec.rb +0 -55
- data/spec/commands/validate_command_spec.rb +0 -213
- data/spec/commands/version_command_spec.rb +0 -38
- data/spec/constants_spec.rb +0 -61
- data/spec/cov_loupe/formatters/source_formatter_spec.rb +0 -267
- data/spec/cov_loupe/formatters_spec.rb +0 -76
- data/spec/cov_loupe/presenters/base_coverage_presenter_spec.rb +0 -79
- data/spec/cov_loupe_model_spec.rb +0 -454
- data/spec/cov_loupe_module_spec.rb +0 -37
- data/spec/cov_loupe_opts_spec.rb +0 -185
- data/spec/coverage_reporter_spec.rb +0 -102
- data/spec/coverage_table_tool_spec.rb +0 -59
- data/spec/coverage_totals_tool_spec.rb +0 -37
- data/spec/error_handler_spec.rb +0 -197
- data/spec/error_mode_spec.rb +0 -139
- data/spec/errors_edge_cases_spec.rb +0 -312
- data/spec/errors_stale_spec.rb +0 -83
- data/spec/file_based_mcp_tools_spec.rb +0 -99
- data/spec/help_tool_spec.rb +0 -26
- data/spec/integration_spec.rb +0 -789
- data/spec/logging_fallback_spec.rb +0 -128
- data/spec/mcp_logging_spec.rb +0 -44
- data/spec/mcp_server_integration_spec.rb +0 -23
- data/spec/mcp_server_spec.rb +0 -106
- data/spec/mode_detector_spec.rb +0 -153
- data/spec/model_error_handling_spec.rb +0 -269
- data/spec/model_staleness_spec.rb +0 -79
- data/spec/option_normalizers_spec.rb +0 -203
- data/spec/option_parsers/env_options_parser_spec.rb +0 -221
- data/spec/option_parsers/error_helper_spec.rb +0 -222
- data/spec/path_relativizer_spec.rb +0 -98
- data/spec/presenters/coverage_detailed_presenter_spec.rb +0 -19
- data/spec/presenters/coverage_raw_presenter_spec.rb +0 -15
- data/spec/presenters/coverage_summary_presenter_spec.rb +0 -15
- data/spec/presenters/coverage_uncovered_presenter_spec.rb +0 -16
- data/spec/presenters/project_coverage_presenter_spec.rb +0 -87
- data/spec/presenters/project_totals_presenter_spec.rb +0 -144
- data/spec/resolvers/coverage_line_resolver_spec.rb +0 -282
- data/spec/resolvers/resolver_factory_spec.rb +0 -61
- data/spec/resolvers/resultset_path_resolver_spec.rb +0 -60
- data/spec/resultset_loader_spec.rb +0 -167
- data/spec/shared_examples/README.md +0 -115
- data/spec/shared_examples/coverage_presenter_examples.rb +0 -66
- data/spec/shared_examples/file_based_mcp_tools.rb +0 -179
- data/spec/shared_examples/formatted_command_examples.rb +0 -64
- data/spec/shared_examples/mcp_tool_text_json_response.rb +0 -16
- data/spec/spec_helper.rb +0 -127
- data/spec/staleness_checker_spec.rb +0 -374
- data/spec/staleness_more_spec.rb +0 -42
- data/spec/support/cli_helpers.rb +0 -22
- data/spec/support/control_flow_helpers.rb +0 -20
- data/spec/support/fake_mcp.rb +0 -40
- data/spec/support/io_helpers.rb +0 -29
- data/spec/support/mcp_helpers.rb +0 -35
- data/spec/support/mcp_runner.rb +0 -66
- data/spec/support/mocking_helpers.rb +0 -30
- data/spec/table_format_spec.rb +0 -70
- data/spec/tools/validate_tool_spec.rb +0 -132
- data/spec/tools_error_handling_spec.rb +0 -130
- data/spec/util_spec.rb +0 -154
- data/spec/version_spec.rb +0 -123
- data/spec/version_tool_spec.rb +0 -141
- /data/{spec/fixtures/project1 → examples/fixtures/demo_project}/lib/bar.rb +0 -0
- /data/{spec/fixtures/project1 → examples/fixtures/demo_project}/lib/foo.rb +0 -0
- /data/lib/cov_loupe/{config_parser.rb → config/config_parser.rb} +0 -0
- /data/lib/cov_loupe/{predicate_evaluator.rb → config/predicate_evaluator.rb} +0 -0
- /data/lib/cov_loupe/{error_handler_factory.rb → errors/error_handler_factory.rb} +0 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Test Coverage Analysis Prompt for Ruby Applications
|
|
2
|
+
|
|
3
|
+
[Back to main README](../../index.md)
|
|
4
|
+
|
|
5
|
+
Use the cov-loupe MCP server tool to analyze the test coverage data generated by simplecov for this Ruby project.
|
|
6
|
+
|
|
7
|
+
Generate a detailed coverage analysis report and output it to a markdown file named `test_coverage_analysis.md`.
|
|
8
|
+
|
|
9
|
+
The report should include:
|
|
10
|
+
|
|
11
|
+
## 1. Executive Summary
|
|
12
|
+
- Overall coverage percentage and trend direction
|
|
13
|
+
- High-level assessment of testing health across the application
|
|
14
|
+
- Key strengths and critical gaps at a glance
|
|
15
|
+
|
|
16
|
+
## 2. Coverage by Application Component
|
|
17
|
+
Detailed analysis of coverage across different application layers:
|
|
18
|
+
- **Core Domain Logic**: Business logic classes, domain models, and entities
|
|
19
|
+
- **Services/Commands**: Service objects, command patterns, and use cases
|
|
20
|
+
- **Data Access Layer**: Repository patterns, data mappers, database interactions
|
|
21
|
+
- **External Integrations**: API clients, third-party service wrappers
|
|
22
|
+
- **Utilities/Helpers**: Helper modules, utility classes, and shared functions
|
|
23
|
+
- **CLI Components**: Command-line interface handlers and argument parsers (if applicable)
|
|
24
|
+
- **Configuration**: Configuration classes and initialization logic
|
|
25
|
+
- **Lib files**: Custom libraries and reusable modules
|
|
26
|
+
- **Concerns/Mixins**: Shared modules and concerns
|
|
27
|
+
|
|
28
|
+
## 3. Well-Tested Areas
|
|
29
|
+
- What's working well and why
|
|
30
|
+
- Testing patterns and practices to replicate
|
|
31
|
+
- Examples of strong test coverage with specific file references
|
|
32
|
+
|
|
33
|
+
## 4. Poorly-Tested Areas
|
|
34
|
+
Organize by:
|
|
35
|
+
- **Complexity to Test**: Simple/Moderate/Complex (considering dependencies, I/O operations, external services, etc.)
|
|
36
|
+
- **Risk Level**: High/Medium/Low (impact on data integrity, system reliability, business logic correctness)
|
|
37
|
+
- **Coverage Gap Size**: Percentage of uncovered lines and number of untested methods
|
|
38
|
+
|
|
39
|
+
## 5. Priority Issues Table
|
|
40
|
+
Create a markdown table with these columns:
|
|
41
|
+
- File/Module Path
|
|
42
|
+
- Component Type (Service/Domain/Integration/etc.)
|
|
43
|
+
- Current Coverage %
|
|
44
|
+
- Uncovered Lines Count
|
|
45
|
+
- Risk Level (High/Medium/Low)
|
|
46
|
+
- Complexity to Fix (High/Medium/Low)
|
|
47
|
+
- Priority Score (1-10, with 10 being highest priority)
|
|
48
|
+
- Recommended Action (specific next steps)
|
|
49
|
+
|
|
50
|
+
Sort by Priority Score descending.
|
|
51
|
+
|
|
52
|
+
## 6. Ruby Application Testing Analysis
|
|
53
|
+
- **Domain Logic Testing**: Coverage of business rules, validations, calculations, state transitions
|
|
54
|
+
- **Service Layer Testing**: Coverage of orchestration logic, error handling, transaction boundaries
|
|
55
|
+
- **Data Access Testing**: Coverage of queries, data transformations, persistence operations
|
|
56
|
+
- **Integration Testing**: Testing of interactions between components and external systems
|
|
57
|
+
- **API Client Testing**: Coverage of HTTP requests, response parsing, error handling
|
|
58
|
+
- **File I/O Operations**: Testing of file reading/writing, parsing, serialization
|
|
59
|
+
- **Concurrency/Threading**: Coverage of thread-safe operations, race conditions (if applicable)
|
|
60
|
+
- **Error Handling**: Testing of exception handling, retry logic, fallback mechanisms
|
|
61
|
+
- **Security**: Testing of input validation, data sanitization, authentication/authorization
|
|
62
|
+
- **Missing Test Types**: Identify gaps in unit/integration/end-to-end tests
|
|
63
|
+
|
|
64
|
+
## 7. Common Ruby Testing Anti-Patterns Detected
|
|
65
|
+
- Over-mocking leading to brittle tests
|
|
66
|
+
- Missing edge case coverage in core domain logic
|
|
67
|
+
- Untested error handling and failure scenarios
|
|
68
|
+
- Missing tests for external service integrations
|
|
69
|
+
- Lack of integration tests for critical workflows
|
|
70
|
+
- Untested concurrency or threading logic (if applicable)
|
|
71
|
+
- Insufficient testing of data transformation pipelines
|
|
72
|
+
- Missing tests for CLI argument parsing and validation
|
|
73
|
+
|
|
74
|
+
## 8. Actionable Testing Roadmap
|
|
75
|
+
Prioritized list of specific issues to resolve, organized by effort level:
|
|
76
|
+
- **Quick Wins** (< 2 hours): Simple tests with high impact
|
|
77
|
+
- **Sprint 1** (2-8 hours): Medium complexity, high priority
|
|
78
|
+
- **Sprint 2** (1-2 days): Complex but critical coverage gaps
|
|
79
|
+
- **Long-term** (> 2 days): Large refactoring or architectural test improvements
|
|
80
|
+
|
|
81
|
+
Include specific file paths, method names, and recommended testing approaches for each item.
|
|
82
|
+
|
|
83
|
+
## 9. Metrics Dashboard
|
|
84
|
+
Key numbers:
|
|
85
|
+
- Overall coverage percentage
|
|
86
|
+
- Number of files at 0% coverage
|
|
87
|
+
- Number of files at 100% coverage
|
|
88
|
+
- Number of files above 90% coverage
|
|
89
|
+
- Number of files below 50% coverage
|
|
90
|
+
- Coverage by component type (Domain %, Services %, Integrations %, etc.)
|
|
91
|
+
- Trend direction (if historical data available)
|
|
92
|
+
- Lines of code vs lines of test code ratio
|
|
93
|
+
- Average cyclomatic complexity of untested methods (if available)
|
|
94
|
+
|
|
95
|
+
## 10. Risk Assessment
|
|
96
|
+
- **Critical Paths**: Identify core business workflows and their test coverage
|
|
97
|
+
- **High-Risk Untested Code**: Data processing, financial calculations, authentication, data deletion, etc.
|
|
98
|
+
- **Security Implications**: Areas where lack of tests could lead to vulnerabilities
|
|
99
|
+
- **Technical Debt**: Old code with no tests that should be prioritized for coverage
|
|
100
|
+
- **External Dependencies**: Integration points with poor test coverage
|
|
101
|
+
- **Data Integrity Risks**: Operations that modify or delete data without adequate test coverage
|
|
102
|
+
|
|
103
|
+
Include specific file paths, line numbers, and code examples where relevant. Focus on actionable insights rather than just reporting numbers. Provide concrete recommendations for improving the test suite architecture and coverage strategy.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Test Coverage Analysis Prompt for Ruby on Rails Project
|
|
2
|
+
|
|
3
|
+
[Back to main README](../../index.md)
|
|
4
|
+
|
|
5
|
+
Use the cov-loupe MCP server tool to analyze the test coverage data generated by simplecov for this Ruby on Rails project. Generate a detailed coverage analysis report and output it to a markdown file named `test_coverage_analysis.md`.
|
|
6
|
+
|
|
7
|
+
The report should include:
|
|
8
|
+
|
|
9
|
+
## 1. Executive Summary
|
|
10
|
+
- Overall coverage percentage and trend direction
|
|
11
|
+
- High-level assessment of testing health across the Rails application
|
|
12
|
+
- Key strengths and critical gaps at a glance
|
|
13
|
+
|
|
14
|
+
## 2. Coverage by Rails Component
|
|
15
|
+
Detailed analysis of coverage across different Rails layers:
|
|
16
|
+
- **Models**: ActiveRecord models, validations, scopes, associations, callbacks
|
|
17
|
+
- **Controllers**: Actions, before_actions, strong parameters, response handling
|
|
18
|
+
- **Views**: View helpers, partials, component logic
|
|
19
|
+
- **Mailers**: Email templates and delivery logic
|
|
20
|
+
- **Jobs**: ActiveJob background jobs and queue handlers
|
|
21
|
+
- **Services/POROs**: Business logic classes and service objects
|
|
22
|
+
- **Concerns**: Shared modules and mixins
|
|
23
|
+
- **Lib files**: Custom libraries and utilities
|
|
24
|
+
- **Configuration**: Initializers and config files (if applicable)
|
|
25
|
+
|
|
26
|
+
## 3. Well-Tested Areas
|
|
27
|
+
- What's working well and why
|
|
28
|
+
- Testing patterns and practices to replicate
|
|
29
|
+
- Examples of strong test coverage with specific file references
|
|
30
|
+
|
|
31
|
+
## 4. Poorly-Tested Areas
|
|
32
|
+
Organize by:
|
|
33
|
+
- **Complexity to Test**: Simple/Moderate/Complex (considering Rails dependencies, database setup, external services, etc.)
|
|
34
|
+
- **Risk Level**: High/Medium/Low (impact on user experience, data integrity, security)
|
|
35
|
+
- **Coverage Gap Size**: Percentage of uncovered lines and number of untested methods
|
|
36
|
+
|
|
37
|
+
## 5. Priority Issues Table
|
|
38
|
+
Create a markdown table with these columns:
|
|
39
|
+
- File/Module Path
|
|
40
|
+
- Component Type (Model/Controller/Job/etc.)
|
|
41
|
+
- Current Coverage %
|
|
42
|
+
- Uncovered Lines Count
|
|
43
|
+
- Risk Level (High/Medium/Low)
|
|
44
|
+
- Complexity to Fix (High/Medium/Low)
|
|
45
|
+
- Priority Score (1-10, with 10 being highest priority)
|
|
46
|
+
- Recommended Action (specific next steps)
|
|
47
|
+
|
|
48
|
+
Sort by Priority Score descending.
|
|
49
|
+
|
|
50
|
+
## 6. Rails-Specific Testing Analysis
|
|
51
|
+
- **Model Testing**: Coverage of validations, associations, scopes, callbacks, custom methods
|
|
52
|
+
- **Controller Testing**: Coverage of happy paths vs error handling, authentication/authorization
|
|
53
|
+
- **Integration Testing**: Request specs, feature specs, system tests
|
|
54
|
+
- **API Testing**: Coverage of JSON/XML responses, API versioning
|
|
55
|
+
- **Database Operations**: Testing of migrations, seeds, complex queries
|
|
56
|
+
- **Background Jobs**: Coverage of job execution, retry logic, error handling
|
|
57
|
+
- **Security**: Testing of authentication, authorization, input sanitization, CSRF protection
|
|
58
|
+
- **Missing Test Types**: Identify gaps in unit/integration/system/feature tests
|
|
59
|
+
|
|
60
|
+
## 7. Common Rails Testing Anti-Patterns Detected
|
|
61
|
+
- Over-reliance on controller tests vs request specs
|
|
62
|
+
- Missing edge case coverage in models
|
|
63
|
+
- Untested error handling and failure scenarios
|
|
64
|
+
- Missing tests for background jobs and mailers
|
|
65
|
+
- Lack of integration tests for critical user flows
|
|
66
|
+
- Untested authorization/permission logic
|
|
67
|
+
|
|
68
|
+
## 8. Actionable Testing Roadmap
|
|
69
|
+
Prioritized list of specific issues to resolve, organized by effort level:
|
|
70
|
+
- **Quick Wins** (< 2 hours): Simple tests with high impact
|
|
71
|
+
- **Sprint 1** (2-8 hours): Medium complexity, high priority
|
|
72
|
+
- **Sprint 2** (1-2 days): Complex but critical coverage gaps
|
|
73
|
+
- **Long-term** (> 2 days): Large refactoring or architectural test improvements
|
|
74
|
+
|
|
75
|
+
Include specific file paths, method names, and recommended testing approaches for each item.
|
|
76
|
+
|
|
77
|
+
## 9. Metrics Dashboard
|
|
78
|
+
Key numbers:
|
|
79
|
+
- Overall coverage percentage
|
|
80
|
+
- Number of files at 0% coverage
|
|
81
|
+
- Number of files at 100% coverage
|
|
82
|
+
- Number of files above 90% coverage
|
|
83
|
+
- Number of files below 50% coverage
|
|
84
|
+
- Coverage by component type (Models %, Controllers %, etc.)
|
|
85
|
+
- Trend direction (if historical data available)
|
|
86
|
+
- Lines of code vs lines of test code ratio
|
|
87
|
+
|
|
88
|
+
## 10. Risk Assessment
|
|
89
|
+
- **Critical Paths**: Identify core user journeys and their test coverage
|
|
90
|
+
- **High-Risk Untested Code**: Payment processing, authentication, data deletion, etc.
|
|
91
|
+
- **Security Implications**: Areas where lack of tests could lead to vulnerabilities
|
|
92
|
+
- **Technical Debt**: Old code with no tests that should be prioritized for coverage
|
|
93
|
+
|
|
94
|
+
Include specific file paths, line numbers, and code examples where relevant. Focus on actionable insights rather than just reporting numbers. Provide concrete recommendations for improving the test suite architecture and coverage strategy.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Use the 'cov-loupe' application as a command line utility.
|
|
2
|
+
|
|
3
|
+
[Back to main README](../../index.md)
|
|
4
|
+
|
|
5
|
+
The `cov-loupe` application provides precise test coverage information for your Ruby application.
|
|
6
|
+
|
|
7
|
+
It reads the `.resultset.json` file generated by SimpleCov, and offers multiple ways to analyze and display its information.
|
|
8
|
+
|
|
9
|
+
Below is the help for version 4.0.0.pre, but run `cov-loupe --help` to make sure you get the most up-to-date information.
|
|
10
|
+
|
|
11
|
+
----
|
|
12
|
+
```bash
|
|
13
|
+
-------------------------------------------------------------------------------
|
|
14
|
+
Usage: cov-loupe [options] [subcommand] [args] (default subcommand: list)
|
|
15
|
+
Repository: https://github.com/keithrbennett/cov-loupe
|
|
16
|
+
Documentation (Web): https://keithrbennett.github.io/cov-loupe/
|
|
17
|
+
Documentation (Local): /home/kbennett/code/cov-loupe/**/*.md
|
|
18
|
+
Version: 4.0.0.pre
|
|
19
|
+
-------------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
Subcommands:
|
|
22
|
+
detailed <path> Show per-line rows with hits/covered
|
|
23
|
+
list Show files coverage (default: table, or use --format)
|
|
24
|
+
raw <path> Show the SimpleCov 'lines' array
|
|
25
|
+
summary <path> Show covered/total/% for a file
|
|
26
|
+
totals Show aggregated line totals and average %
|
|
27
|
+
uncovered <path> Show uncovered lines and a summary
|
|
28
|
+
validate <file> Evaluate coverage policy from file (exit 0=pass, 1=fail, 2=error)
|
|
29
|
+
validate -i <code> Evaluate coverage policy from code string
|
|
30
|
+
version Show version information
|
|
31
|
+
|
|
32
|
+
Options:
|
|
33
|
+
-r, --resultset PATH Path or directory that contains .resultset.json (default: coverage/.resultset.json)
|
|
34
|
+
-R, --root PATH Project root (default: .)
|
|
35
|
+
-f, --format FORMAT Output format: t[able]|j[son]|pretty-json|y[aml]|a[wesome-print] (default: table)
|
|
36
|
+
-o, --sort-order ORDER Sort order for list: a[scending]|d[escending] (default descending)
|
|
37
|
+
-s, --source MODE Source display: f[ull]|u[ncovered]
|
|
38
|
+
-c, --context-lines N Context lines around uncovered lines (non-negative, default: 2)
|
|
39
|
+
-C, --color BOOLEAN Enable/disable ANSI colors for source output (default: true). Accepts: yes/no/y/n/true/false/t/f/on/off/+/-/1/0
|
|
40
|
+
-S, --raise-on-stale BOOLEAN Raise error if coverage is stale (default: false). Accepts: yes/no/y/n/true/false/t/f/on/off/+/-/1/0
|
|
41
|
+
-g, --tracked-globs x,y,z Globs for filtering files (list/totals subcommands)
|
|
42
|
+
-h, --help Show help
|
|
43
|
+
-l, --log-file PATH Log file path (default ./cov_loupe.log, use stdout/stderr for streams)
|
|
44
|
+
-m, --mode MODE Execution mode: cli|mcp (default: cli)
|
|
45
|
+
-e, --error-mode MODE Error handling mode: o[ff]|l[og]|d[ebug] (default log). off (silent), log (log errors to file), debug (verbose with backtraces)
|
|
46
|
+
-v, --version Show version information and exit.
|
|
47
|
+
|
|
48
|
+
Examples:
|
|
49
|
+
cov-loupe --resultset coverage list
|
|
50
|
+
cov-loupe --format json --resultset coverage summary lib/foo.rb
|
|
51
|
+
cov-loupe --source uncovered --context-lines 2 uncovered lib/foo.rb
|
|
52
|
+
cov-loupe totals --format json
|
|
53
|
+
```
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Demo script for cov-loupe CLI subcommands and options
|
|
3
|
+
# Runs against the included fixture project at spec/fixtures/project1.
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
8
|
+
cd "$ROOT_DIR"
|
|
9
|
+
CLI=("exe/cov-loupe")
|
|
10
|
+
PROJ="examples/fixtures/demo_project"
|
|
11
|
+
RESULTSET_DIR="coverage" # directory containing .resultset.json under PROJ
|
|
12
|
+
|
|
13
|
+
run() {
|
|
14
|
+
cat <<BANNER
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
-------------------------------------------------------------------------------
|
|
19
|
+
+ ${CLI[*]} $*
|
|
20
|
+
-------------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
BANNER
|
|
23
|
+
"${CLI[@]}" "$@"
|
|
24
|
+
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
cat <<INTRO
|
|
28
|
+
== cov-loupe CLI demo ==
|
|
29
|
+
|
|
30
|
+
Note: Project root and resultset JSON file normally do not need to be specified.
|
|
31
|
+
We set --root here to use the examples/fixtures/demo_project nondefault location,
|
|
32
|
+
and later demonstrate a nondefault resultset via the --resultset option.
|
|
33
|
+
|
|
34
|
+
Project root: $PROJ
|
|
35
|
+
Resultset (dir): $RESULTSET_DIR
|
|
36
|
+
|
|
37
|
+
INTRO
|
|
38
|
+
|
|
39
|
+
# 1) List all files (table)
|
|
40
|
+
run list --root "$PROJ"
|
|
41
|
+
|
|
42
|
+
# 2) List as JSON, descending sort
|
|
43
|
+
run list --root "$PROJ" --sort-order descending --json
|
|
44
|
+
|
|
45
|
+
# 3) Summary for a file (text and JSON)
|
|
46
|
+
run summary lib/foo.rb --root "$PROJ"
|
|
47
|
+
run summary lib/foo.rb --root "$PROJ" --json
|
|
48
|
+
|
|
49
|
+
# 4) Include source with summary (full and uncovered-only with context)
|
|
50
|
+
run summary lib/foo.rb --root "$PROJ" --source
|
|
51
|
+
run summary lib/foo.rb --root "$PROJ" --source=uncovered --source-context 1
|
|
52
|
+
|
|
53
|
+
# 5) Uncovered lines (text with source and JSON)
|
|
54
|
+
run uncovered lib/foo.rb --root "$PROJ" --source=uncovered --source-context 2
|
|
55
|
+
run uncovered lib/foo.rb --root "$PROJ" --json
|
|
56
|
+
|
|
57
|
+
# 6) Detailed per-line data (text and JSON), with source
|
|
58
|
+
run detailed lib/foo.rb --root "$PROJ" --source -C false
|
|
59
|
+
run detailed lib/foo.rb --root "$PROJ" --json
|
|
60
|
+
|
|
61
|
+
# 7) Raw lines array (JSON)
|
|
62
|
+
run raw lib/foo.rb --root "$PROJ" --json
|
|
63
|
+
|
|
64
|
+
# 8) Using environment variable for a NONDEFAULT resultset location
|
|
65
|
+
# Copy the default resultset into a simple alt directory to simulate a custom layout.
|
|
66
|
+
ALT_DIR="$PROJ/alt_resultset"
|
|
67
|
+
mkdir -p "$ALT_DIR"
|
|
68
|
+
cp -f "$PROJ/coverage/.resultset.json" "$ALT_DIR/.resultset.json"
|
|
69
|
+
echo
|
|
70
|
+
echo "+ ${CLI[*]} list --root $PROJ --resultset $PROJ/alt_resultset"
|
|
71
|
+
"${CLI[@]}" list --root "$PROJ" --resultset "$PROJ/alt_resultset"
|
|
72
|
+
|
|
73
|
+
echo
|
|
74
|
+
echo "== Done =="
|
|
75
|
+
|
|
76
|
+
# Cleanup files created for the nondefault resultset demo
|
|
77
|
+
rm -rf "$ALT_DIR"
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# cov-loupe Library Usage Examples
|
|
2
|
+
=============================================
|
|
3
|
+
|
|
4
|
+
## 1. Full Coverage Table
|
|
5
|
+
```
|
|
6
|
+
┌────────────────────────────────────────────────┬──────────┬───────────┬─────────┬───────┐
|
|
7
|
+
│ File │ % │ Covered │ Total │ Stale │
|
|
8
|
+
├────────────────────────────────────────────────┼──────────┼───────────┼─────────┼───────┤
|
|
9
|
+
│ /home/kbennett/code/cov-loupe/lib/bar.rb │ 33.33% │ 1 │ 3 │ ! │
|
|
10
|
+
│ /home/kbennett/code/cov-loupe/lib/foo.rb │ 66.67% │ 2 │ 3 │ ! │
|
|
11
|
+
└────────────────────────────────────────────────┴──────────┴───────────┴─────────┴───────┘
|
|
12
|
+
Files: total 2, ok 0, stale 2
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## 2. Filter by Directory (lib/ only)
|
|
16
|
+
```ruby
|
|
17
|
+
# Filter files by directory (e.g., only show files in lib/)
|
|
18
|
+
files_data = model.list
|
|
19
|
+
lib_files = files_data.select { |file| file["file"].include?("/lib/") }
|
|
20
|
+
lib_files_table = model.format_table(lib_files)
|
|
21
|
+
# => formatted table showing only files from lib/ directory
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Result:
|
|
25
|
+
```
|
|
26
|
+
┌────────────────────────────────────────────────┬──────────┬───────────┬─────────┬───────┐
|
|
27
|
+
│ File │ % │ Covered │ Total │ Stale │
|
|
28
|
+
├────────────────────────────────────────────────┼──────────┼───────────┼─────────┼───────┤
|
|
29
|
+
│ /home/kbennett/code/cov-loupe/lib/bar.rb │ 33.33% │ 1 │ 3 │ ! │
|
|
30
|
+
│ /home/kbennett/code/cov-loupe/lib/foo.rb │ 66.67% │ 2 │ 3 │ ! │
|
|
31
|
+
└────────────────────────────────────────────────┴──────────┴───────────┴─────────┴───────┘
|
|
32
|
+
Files: total 2, ok 0, stale 2
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 3. Filter by Pattern (files with specific naming)
|
|
36
|
+
```ruby
|
|
37
|
+
# Filter by pattern (e.g., only show files with "foo" in name)
|
|
38
|
+
foo_files = files_data.select { |file| file["file"].include?("foo") }
|
|
39
|
+
foo_table = model.format_table(foo_files)
|
|
40
|
+
# => formatted table showing only files with 'foo' in filename
|
|
41
|
+
```
|
|
42
|
+
check_coverage_data
|
|
43
|
+
|
|
44
|
+
Result:
|
|
45
|
+
```
|
|
46
|
+
┌────────────────────────────────────────────────┬──────────┬───────────┬─────────┬───────┐
|
|
47
|
+
│ File │ % │ Covered │ Total │ Stale │
|
|
48
|
+
├────────────────────────────────────────────────┼──────────┼───────────┼─────────┼───────┤
|
|
49
|
+
│ /home/kbennett/code/cov-loupe/lib/foo.rb │ 66.67% │ 2 │ 3 │ ! │
|
|
50
|
+
└────────────────────────────────────────────────┴──────────┴───────────┴─────────┴───────┘
|
|
51
|
+
Files: total 1, ok 0, stale 1
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## 4. Filter by Coverage Threshold (only high-coverage files)
|
|
55
|
+
```ruby
|
|
56
|
+
# Filter by coverage percentage (e.g., only files >= 50% coverage)
|
|
57
|
+
high_coverage_files = files_data.select { |file| file["percentage"] >= 50.0 }
|
|
58
|
+
high_coverage_table = model.format_table(high_coverage_files)
|
|
59
|
+
# => formatted table showing only well-covered files
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Result:
|
|
63
|
+
```
|
|
64
|
+
┌────────────────────────────────────────────────┬──────────┬───────────┬─────────┬───────┐
|
|
65
|
+
│ File │ % │ Covered │ Total │ Stale │
|
|
66
|
+
├────────────────────────────────────────────────┼──────────┼───────────┼─────────┼───────┤
|
|
67
|
+
│ /home/kbennett/code/cov-loupe/lib/foo.rb │ 66.67% │ 2 │ 3 │ ! │
|
|
68
|
+
└────────────────────────────────────────────────┴──────────┴───────────┴─────────┴───────┘
|
|
69
|
+
Files: total 1, ok 0, stale 1
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## 5. Staleness Analysis
|
|
73
|
+
```ruby
|
|
74
|
+
# Analyze coverage staleness to find potentially problematic files
|
|
75
|
+
stale_files, healthy_files = files_data.partition { |file| file["stale"] }
|
|
76
|
+
|
|
77
|
+
puts "## Potentially Stale Coverage Files"
|
|
78
|
+
puts model.format_table(stale_files, sort_order: :descending)
|
|
79
|
+
|
|
80
|
+
puts "## Healthy Coverage Files"
|
|
81
|
+
puts model.format_table(healthy_files, sort_order: :descending)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Result:
|
|
85
|
+
```
|
|
86
|
+
## Potentially Stale Coverage Files
|
|
87
|
+
┌────────────────────────────────────────────────┬──────────┬───────────┬─────────┬───────┐
|
|
88
|
+
│ File │ % │ Covered │ Total │ Stale │
|
|
89
|
+
├────────────────────────────────────────────────┼──────────┼───────────┼─────────┼───────┤
|
|
90
|
+
│ /home/kbennett/code/cov-loupe/lib/foo.rb │ 66.67% │ 2 │ 3 │ ! │
|
|
91
|
+
│ /home/kbennett/code/cov-loupe/lib/bar.rb │ 33.33% │ 1 │ 3 │ ! │
|
|
92
|
+
└────────────────────────────────────────────────┴──────────┴───────────┴─────────┴───────┘
|
|
93
|
+
Files: total 2, ok 0, stale 2
|
|
94
|
+
|
|
95
|
+
## Healthy Coverage Files
|
|
96
|
+
(No healthy files found)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
NOTE: To see staleness analysis in action with both stale and healthy files,
|
|
100
|
+
try modifying file timestamps:
|
|
101
|
+
- Make one file appear older: `touch -t 202401010000 spec/fixtures/project1/lib/foo.rb`
|
|
102
|
+
- Or make one file appear newer: `touch spec/fixtures/project1/lib/bar.rb`
|
|
103
|
+
Then run this script again to see partition results change.
|
|
104
|
+
|
|
105
|
+
## Summary
|
|
106
|
+
This example demonstrates how cov-loupe can be used as a library to:
|
|
107
|
+
- Load and query coverage data
|
|
108
|
+
- Filter files by various criteria (directory, filename, coverage threshold)
|
|
109
|
+
- Perform staleness analysis to identify potentially problematic files
|
|
110
|
+
- Generate CI/CD integration reports with exit codes for monitoring
|
|
111
|
+
- Create custom reports tailored to specific needs
|
|
112
|
+
|
|
113
|
+
The table formatting functionality (format_table) is now accessible
|
|
114
|
+
directly in library mode, not just through the CLI!
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Example: Using cov-loupe as a library to filter and format coverage tables
|
|
5
|
+
# This demonstrates filtering files by directory and other criteria, then generating tables
|
|
6
|
+
|
|
7
|
+
require_relative '../lib/cov_loupe'
|
|
8
|
+
|
|
9
|
+
def check_coverage_data
|
|
10
|
+
unless File.exist?('spec/fixtures/project1/coverage/.resultset.json')
|
|
11
|
+
puts <<~DOC
|
|
12
|
+
Error: Coverage data file not found.
|
|
13
|
+
|
|
14
|
+
Please run this script from project root directory:
|
|
15
|
+
|
|
16
|
+
examples/filter_and_table_demo.rb
|
|
17
|
+
|
|
18
|
+
If coverage data is missing, run tests first to generate it:
|
|
19
|
+
|
|
20
|
+
bundle exec rspec
|
|
21
|
+
DOC
|
|
22
|
+
exit 1
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def output_examples
|
|
27
|
+
puts <<~DOC
|
|
28
|
+
# cov-loupe Library Usage Examples
|
|
29
|
+
=============================================
|
|
30
|
+
|
|
31
|
+
DOC
|
|
32
|
+
|
|
33
|
+
# Initialize coverage model
|
|
34
|
+
# Using the built-in coverage data from running specs
|
|
35
|
+
model = CovLoupe::CoverageModel.new(
|
|
36
|
+
root: '.',
|
|
37
|
+
resultset: 'spec/fixtures/project1/coverage'
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
puts <<~DOC
|
|
41
|
+
## 1. Full Coverage Table
|
|
42
|
+
```
|
|
43
|
+
#{model.format_table}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
DOC
|
|
47
|
+
|
|
48
|
+
puts <<~DOC
|
|
49
|
+
## 2. Filter by Directory (lib/ only)
|
|
50
|
+
```ruby
|
|
51
|
+
# Filter files by directory (e.g., only show files in lib/)
|
|
52
|
+
files_data = model.list['files']
|
|
53
|
+
lib_files = files_data.select { |file| file["file"].include?("/lib/") }
|
|
54
|
+
lib_files_table = model.format_table(lib_files)
|
|
55
|
+
# => formatted table showing only files from lib/ directory
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
DOC
|
|
59
|
+
|
|
60
|
+
# Execute the code
|
|
61
|
+
files_data = model.list['files']
|
|
62
|
+
lib_files = files_data.select { |file| file['file'].include?('/lib/') }
|
|
63
|
+
lib_files_table = model.format_table(lib_files)
|
|
64
|
+
puts <<~DOC
|
|
65
|
+
Result:
|
|
66
|
+
```
|
|
67
|
+
#{lib_files_table}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
DOC
|
|
71
|
+
|
|
72
|
+
puts <<~DOC
|
|
73
|
+
## 3. Filter by Pattern (files with specific naming)
|
|
74
|
+
```ruby
|
|
75
|
+
# Filter by pattern (e.g., only show files with "foo" in name)
|
|
76
|
+
# Note: files_data is the array from model.list['files']
|
|
77
|
+
foo_files = files_data.select { |file| file["file"].include?("foo") }
|
|
78
|
+
foo_table = model.format_table(foo_files)
|
|
79
|
+
# => formatted table showing only files with 'foo' in filename
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
DOC
|
|
83
|
+
|
|
84
|
+
# Execute the code
|
|
85
|
+
foo_files = files_data.select { |file| file['file'].include?('foo') }
|
|
86
|
+
foo_table = model.format_table(foo_files)
|
|
87
|
+
puts <<~DOC
|
|
88
|
+
Result:
|
|
89
|
+
```
|
|
90
|
+
#{foo_table}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
DOC
|
|
94
|
+
|
|
95
|
+
puts <<~DOC
|
|
96
|
+
## 4. Filter by Coverage Threshold (only high-coverage files)
|
|
97
|
+
```ruby
|
|
98
|
+
# Filter by coverage percentage (e.g., only files >= 50% coverage)
|
|
99
|
+
# Note: files_data is the array from model.list['files']
|
|
100
|
+
high_coverage_files = files_data.select { |file| file["percentage"] >= 50.0 }
|
|
101
|
+
high_coverage_table = model.format_table(high_coverage_files)
|
|
102
|
+
# => formatted table showing only well-covered files
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
DOC
|
|
106
|
+
|
|
107
|
+
# Execute the code
|
|
108
|
+
high_coverage_files = files_data.select { |file| file['percentage'] >= 50.0 }
|
|
109
|
+
high_coverage_table = model.format_table(high_coverage_files)
|
|
110
|
+
puts <<~DOC
|
|
111
|
+
Result:
|
|
112
|
+
```
|
|
113
|
+
#{high_coverage_table}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
DOC
|
|
117
|
+
|
|
118
|
+
puts <<~DOC
|
|
119
|
+
## 5. Staleness Analysis
|
|
120
|
+
```ruby
|
|
121
|
+
# Analyze coverage staleness to find potentially problematic files
|
|
122
|
+
# Note: files_data is the array from model.list['files']
|
|
123
|
+
stale_files, healthy_files = files_data.partition { |file| file["stale"] }
|
|
124
|
+
|
|
125
|
+
puts "## Potentially Stale Coverage Files"
|
|
126
|
+
puts model.format_table(stale_files, sort_order: :descending)
|
|
127
|
+
|
|
128
|
+
puts "## Healthy Coverage Files"
|
|
129
|
+
puts model.format_table(healthy_files, sort_order: :descending)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
DOC
|
|
133
|
+
|
|
134
|
+
# Execute the stale analysis
|
|
135
|
+
stale_files, healthy_files = files_data.partition { |file| file['stale'] }
|
|
136
|
+
|
|
137
|
+
puts 'Result:'
|
|
138
|
+
puts '```'
|
|
139
|
+
puts '## Potentially Stale Coverage Files'
|
|
140
|
+
puts model.format_table(stale_files, sort_order: :descending) if stale_files.any?
|
|
141
|
+
puts '(No stale files found)' if stale_files.empty?
|
|
142
|
+
puts
|
|
143
|
+
puts '## Healthy Coverage Files'
|
|
144
|
+
puts model.format_table(healthy_files, sort_order: :descending) if healthy_files.any?
|
|
145
|
+
puts '(No healthy files found)' if healthy_files.empty?
|
|
146
|
+
puts '```'
|
|
147
|
+
puts
|
|
148
|
+
puts 'NOTE: To see staleness analysis in action with both stale and healthy files,'
|
|
149
|
+
puts 'try modifying file timestamps:'
|
|
150
|
+
puts ' - Make one file appear older: `touch -t 202401010000 spec/fixtures/project1/lib/foo.rb`'
|
|
151
|
+
puts ' - Or make one file appear newer: `touch spec/fixtures/project1/lib/bar.rb`'
|
|
152
|
+
puts 'Then run this script again to see partition results change.'
|
|
153
|
+
puts
|
|
154
|
+
|
|
155
|
+
puts <<~DOC
|
|
156
|
+
## Summary
|
|
157
|
+
This example demonstrates how cov-loupe can be used as a library to:
|
|
158
|
+
- Load and query coverage data
|
|
159
|
+
- Filter files by various criteria (directory, filename, coverage threshold)
|
|
160
|
+
- Perform staleness analysis to identify potentially problematic files
|
|
161
|
+
- Generate CI/CD integration reports with exit codes for monitoring
|
|
162
|
+
- Create custom reports tailored to specific needs
|
|
163
|
+
|
|
164
|
+
The table formatting functionality (format_table) is now accessible
|
|
165
|
+
directly in library mode, not just through the CLI!
|
|
166
|
+
DOC
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def main
|
|
170
|
+
check_coverage_data
|
|
171
|
+
output_examples
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
main if __FILE__ == $PROGRAM_NAME
|