spec_scout 0.1.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 +7 -0
- data/.idea/.gitignore +10 -0
- data/.idea/Projects.iml +41 -0
- data/.idea/copilot.data.migration.ask2agent.xml +6 -0
- data/.idea/modules.xml +8 -0
- data/.idea/vcs.xml +6 -0
- data/.rspec_status +236 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +72 -0
- data/LICENSE +21 -0
- data/README.md +433 -0
- data/Rakefile +12 -0
- data/examples/README.md +321 -0
- data/examples/best_practices.md +401 -0
- data/examples/configurations/basic_config.rb +24 -0
- data/examples/configurations/ci_config.rb +35 -0
- data/examples/configurations/conservative_config.rb +32 -0
- data/examples/configurations/development_config.rb +37 -0
- data/examples/configurations/performance_focused_config.rb +38 -0
- data/examples/output_formatter_demo.rb +67 -0
- data/examples/sample_outputs/console_output_high_confidence.txt +27 -0
- data/examples/sample_outputs/console_output_medium_confidence.txt +27 -0
- data/examples/sample_outputs/console_output_no_action.txt +27 -0
- data/examples/sample_outputs/console_output_risk_detected.txt +27 -0
- data/examples/sample_outputs/json_output_high_confidence.json +108 -0
- data/examples/sample_outputs/json_output_no_action.json +108 -0
- data/examples/workflows/basic_workflow.md +159 -0
- data/examples/workflows/ci_integration.md +372 -0
- data/exe/spec_scout +7 -0
- data/lib/spec_scout/agent_result.rb +44 -0
- data/lib/spec_scout/agents/database_agent.rb +113 -0
- data/lib/spec_scout/agents/factory_agent.rb +179 -0
- data/lib/spec_scout/agents/intent_agent.rb +223 -0
- data/lib/spec_scout/agents/risk_agent.rb +290 -0
- data/lib/spec_scout/base_agent.rb +72 -0
- data/lib/spec_scout/cli.rb +158 -0
- data/lib/spec_scout/configuration.rb +162 -0
- data/lib/spec_scout/consensus_engine.rb +535 -0
- data/lib/spec_scout/enforcement_handler.rb +182 -0
- data/lib/spec_scout/output_formatter.rb +307 -0
- data/lib/spec_scout/profile_data.rb +37 -0
- data/lib/spec_scout/profile_normalizer.rb +238 -0
- data/lib/spec_scout/recommendation.rb +62 -0
- data/lib/spec_scout/safety_validator.rb +127 -0
- data/lib/spec_scout/spec_scout.rb +519 -0
- data/lib/spec_scout/testprof_integration.rb +206 -0
- data/lib/spec_scout/version.rb +5 -0
- data/lib/spec_scout.rb +43 -0
- metadata +166 -0
data/README.md
ADDED
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
# Spec Scout
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/rb/spec_scout)
|
|
4
|
+
[](https://github.com/ajeet-g2/spec-scout/actions/workflows/ruby.yml)
|
|
5
|
+
|
|
6
|
+
Spec Scout is a Ruby gem that transforms TestProf from a profiling tool into an intelligent optimization advisor. The system wraps TestProf execution, consumes its structured output, and uses specialized agents to analyze profiling data and generate actionable recommendations.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **Intelligent Analysis**: Uses specialized agents to analyze different aspects of test performance
|
|
11
|
+
- **TestProf Integration**: Automatically executes and consumes TestProf profiling data
|
|
12
|
+
- **Safe by Default**: Never auto-modifies code, provides recommendations only
|
|
13
|
+
- **CI-Friendly**: Non-blocking operation with configurable enforcement modes
|
|
14
|
+
- **Multiple Output Formats**: Console and JSON output support
|
|
15
|
+
- **Extensible**: Agent-based architecture supports future enhancements
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
Add this line to your application's Gemfile:
|
|
20
|
+
|
|
21
|
+
```ruby
|
|
22
|
+
gem 'spec_scout'
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
And then execute:
|
|
26
|
+
|
|
27
|
+
$ bundle install
|
|
28
|
+
|
|
29
|
+
Or install it yourself as:
|
|
30
|
+
|
|
31
|
+
$ gem install spec_scout
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
### Command Line Usage
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Run with default settings
|
|
39
|
+
spec_scout
|
|
40
|
+
|
|
41
|
+
# Analyze specific spec file
|
|
42
|
+
spec_scout spec/models/user_spec.rb
|
|
43
|
+
|
|
44
|
+
# Enable enforcement mode (fail on high confidence recommendations)
|
|
45
|
+
spec_scout --enforce
|
|
46
|
+
|
|
47
|
+
# JSON output for CI integration
|
|
48
|
+
spec_scout --output json
|
|
49
|
+
|
|
50
|
+
# Disable specific agents
|
|
51
|
+
spec_scout --disable-agent risk
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Programmatic Usage
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
require 'spec_scout'
|
|
58
|
+
|
|
59
|
+
# Configure Spec Scout
|
|
60
|
+
SpecScout.configure do |config|
|
|
61
|
+
config.enable = true
|
|
62
|
+
config.use_test_prof = true
|
|
63
|
+
config.enabled_agents = [:database, :factory, :intent, :risk]
|
|
64
|
+
config.output_format = :console
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Analyze a specific spec file
|
|
68
|
+
scout = SpecScout::SpecScout.new
|
|
69
|
+
result = scout.analyze('spec/models/user_spec.rb')
|
|
70
|
+
|
|
71
|
+
# Access recommendation
|
|
72
|
+
if result[:recommendation]
|
|
73
|
+
puts result[:recommendation].action
|
|
74
|
+
puts result[:recommendation].confidence
|
|
75
|
+
puts result[:recommendation].explanation
|
|
76
|
+
end
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Configuration
|
|
80
|
+
|
|
81
|
+
### Configuration Options
|
|
82
|
+
|
|
83
|
+
```ruby
|
|
84
|
+
SpecScout.configure do |config|
|
|
85
|
+
# Enable/disable Spec Scout entirely
|
|
86
|
+
config.enable = true
|
|
87
|
+
|
|
88
|
+
# Enable/disable TestProf integration
|
|
89
|
+
config.use_test_prof = true
|
|
90
|
+
|
|
91
|
+
# Enable enforcement mode (fail on high confidence recommendations)
|
|
92
|
+
config.enforcement_mode = false
|
|
93
|
+
config.fail_on_high_confidence = false
|
|
94
|
+
|
|
95
|
+
# Select which agents to run
|
|
96
|
+
config.enabled_agents = [:database, :factory, :intent, :risk]
|
|
97
|
+
|
|
98
|
+
# Output format (:console or :json)
|
|
99
|
+
config.output_format = :console
|
|
100
|
+
|
|
101
|
+
# Safety settings (recommended to keep false)
|
|
102
|
+
config.auto_apply_enabled = false
|
|
103
|
+
config.blocking_mode_enabled = false
|
|
104
|
+
end
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Environment Variables
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Enable debug output
|
|
111
|
+
export SPEC_SCOUT_DEBUG=1
|
|
112
|
+
|
|
113
|
+
# Disable Spec Scout entirely
|
|
114
|
+
export SPEC_SCOUT_DISABLE=1
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Command Line Options
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
Usage: spec_scout [options] [spec_file]
|
|
121
|
+
|
|
122
|
+
Options:
|
|
123
|
+
--disable Disable SpecScout analysis
|
|
124
|
+
--no-testprof Disable TestProf integration
|
|
125
|
+
--enforce Enable enforcement mode (fail on high confidence)
|
|
126
|
+
--fail-on-high-confidence Fail on high confidence recommendations
|
|
127
|
+
--output FORMAT, -o FORMAT Output format (console, json)
|
|
128
|
+
--enable-agent AGENT Enable specific agent (database, factory, intent, risk)
|
|
129
|
+
--disable-agent AGENT Disable specific agent
|
|
130
|
+
--spec SPEC_FILE Analyze specific spec file
|
|
131
|
+
--version, -v Show version
|
|
132
|
+
--help, -h Show this help message
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Agents
|
|
136
|
+
|
|
137
|
+
Spec Scout uses specialized agents to analyze different aspects of test performance:
|
|
138
|
+
|
|
139
|
+
### Database Agent
|
|
140
|
+
Analyzes database usage patterns and identifies unnecessary persistence.
|
|
141
|
+
|
|
142
|
+
**Recommendations:**
|
|
143
|
+
- Avoid database persistence when not needed
|
|
144
|
+
- Use `build_stubbed` instead of `create` for factories
|
|
145
|
+
- Optimize database queries
|
|
146
|
+
|
|
147
|
+
### Factory Agent
|
|
148
|
+
Evaluates FactoryBot strategy appropriateness and usage patterns.
|
|
149
|
+
|
|
150
|
+
**Recommendations:**
|
|
151
|
+
- Switch from `create` to `build_stubbed` when persistence isn't required
|
|
152
|
+
- Optimize factory association strategies
|
|
153
|
+
- Reduce factory usage overhead
|
|
154
|
+
|
|
155
|
+
### Intent Agent
|
|
156
|
+
Classifies test intent and behavior patterns to ensure appropriate test boundaries.
|
|
157
|
+
|
|
158
|
+
**Recommendations:**
|
|
159
|
+
- Identify unit vs integration test behavior
|
|
160
|
+
- Ensure test boundaries match intent
|
|
161
|
+
- Optimize test scope and isolation
|
|
162
|
+
|
|
163
|
+
### Risk Agent
|
|
164
|
+
Identifies potentially unsafe optimizations that could break test functionality.
|
|
165
|
+
|
|
166
|
+
**Safety Checks:**
|
|
167
|
+
- Detects `after_commit` callbacks
|
|
168
|
+
- Identifies complex callback chains
|
|
169
|
+
- Flags high-risk optimization scenarios
|
|
170
|
+
|
|
171
|
+
## Output Examples
|
|
172
|
+
|
|
173
|
+
### Console Output
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
✔ Spec Scout Recommendation
|
|
177
|
+
|
|
178
|
+
spec/models/user_spec.rb:42
|
|
179
|
+
|
|
180
|
+
Summary:
|
|
181
|
+
- Factory :user used `create` (3x)
|
|
182
|
+
- DB inserts: 3, selects: 5
|
|
183
|
+
- Runtime: 150ms
|
|
184
|
+
- Type: model spec
|
|
185
|
+
|
|
186
|
+
Agent Signals:
|
|
187
|
+
- Database Agent: DB unnecessary (✔ HIGH)
|
|
188
|
+
- Factory Agent: prefer build_stubbed (⚠ MEDIUM)
|
|
189
|
+
- Intent Agent: unit test behavior (✔ HIGH)
|
|
190
|
+
- Risk Agent: safe to optimize (✔ HIGH)
|
|
191
|
+
|
|
192
|
+
Final Recommendation:
|
|
193
|
+
✔ Replace `create(:user)` with `build_stubbed(:user)`
|
|
194
|
+
Confidence: ✔ HIGH
|
|
195
|
+
|
|
196
|
+
Reasoning:
|
|
197
|
+
- No database persistence required for this test
|
|
198
|
+
- Factory creates unnecessary database records
|
|
199
|
+
- Test exhibits unit test behavior patterns
|
|
200
|
+
- No risk factors detected
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### JSON Output
|
|
204
|
+
|
|
205
|
+
```json
|
|
206
|
+
{
|
|
207
|
+
"spec_location": "spec/models/user_spec.rb:42",
|
|
208
|
+
"action": "replace_factory_strategy",
|
|
209
|
+
"from_value": "create(:user)",
|
|
210
|
+
"to_value": "build_stubbed(:user)",
|
|
211
|
+
"confidence": "high",
|
|
212
|
+
"explanation": [
|
|
213
|
+
"No database persistence required for this test",
|
|
214
|
+
"Factory creates unnecessary database records",
|
|
215
|
+
"Test exhibits unit test behavior patterns",
|
|
216
|
+
"No risk factors detected"
|
|
217
|
+
],
|
|
218
|
+
"agent_results": [
|
|
219
|
+
{
|
|
220
|
+
"agent_name": "database",
|
|
221
|
+
"verdict": "db_unnecessary",
|
|
222
|
+
"confidence": "high",
|
|
223
|
+
"reasoning": "No database writes or reloads detected",
|
|
224
|
+
"metadata": {}
|
|
225
|
+
}
|
|
226
|
+
],
|
|
227
|
+
"profile_data": {
|
|
228
|
+
"example_location": "spec/models/user_spec.rb:42",
|
|
229
|
+
"spec_type": "model",
|
|
230
|
+
"runtime_ms": 150,
|
|
231
|
+
"factories": {
|
|
232
|
+
"user": {
|
|
233
|
+
"strategy": "create",
|
|
234
|
+
"count": 3
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
"db": {
|
|
238
|
+
"total_queries": 8,
|
|
239
|
+
"inserts": 3,
|
|
240
|
+
"selects": 5
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
"metadata": {
|
|
244
|
+
"timestamp": "2024-01-15T10:30:00Z",
|
|
245
|
+
"spec_scout_version": "1.0.0"
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## CI Integration
|
|
251
|
+
|
|
252
|
+
### GitHub Actions
|
|
253
|
+
|
|
254
|
+
```yaml
|
|
255
|
+
name: Spec Scout Analysis
|
|
256
|
+
|
|
257
|
+
on: [push, pull_request]
|
|
258
|
+
|
|
259
|
+
jobs:
|
|
260
|
+
spec_scout:
|
|
261
|
+
runs-on: ubuntu-latest
|
|
262
|
+
steps:
|
|
263
|
+
- uses: actions/checkout@v3
|
|
264
|
+
- uses: ruby/setup-ruby@v1
|
|
265
|
+
with:
|
|
266
|
+
ruby-version: 3.1
|
|
267
|
+
bundler-cache: true
|
|
268
|
+
|
|
269
|
+
- name: Run Spec Scout
|
|
270
|
+
run: |
|
|
271
|
+
bundle exec spec_scout --output json > spec_scout_results.json
|
|
272
|
+
|
|
273
|
+
- name: Upload results
|
|
274
|
+
uses: actions/upload-artifact@v3
|
|
275
|
+
with:
|
|
276
|
+
name: spec-scout-results
|
|
277
|
+
path: spec_scout_results.json
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Enforcement Mode
|
|
281
|
+
|
|
282
|
+
Enable enforcement mode to fail CI builds on high-confidence recommendations:
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
# Fail on high confidence recommendations
|
|
286
|
+
bundle exec spec_scout --enforce --fail-on-high-confidence
|
|
287
|
+
|
|
288
|
+
# Exit code 0: No high confidence recommendations
|
|
289
|
+
# Exit code 1: High confidence recommendations found
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Advanced Usage
|
|
293
|
+
|
|
294
|
+
### Custom Agent Configuration
|
|
295
|
+
|
|
296
|
+
```ruby
|
|
297
|
+
# Enable only specific agents
|
|
298
|
+
SpecScout.configure do |config|
|
|
299
|
+
config.enabled_agents = [:database, :factory] # Skip intent and risk agents
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
# Disable risky optimizations
|
|
303
|
+
SpecScout.configure do |config|
|
|
304
|
+
config.disable_agent(:risk) # Skip risk assessment
|
|
305
|
+
end
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Integration with RSpec
|
|
309
|
+
|
|
310
|
+
```ruby
|
|
311
|
+
# spec/spec_helper.rb
|
|
312
|
+
require 'spec_scout'
|
|
313
|
+
|
|
314
|
+
RSpec.configure do |config|
|
|
315
|
+
config.before(:suite) do
|
|
316
|
+
SpecScout.configure do |scout_config|
|
|
317
|
+
scout_config.enable = true
|
|
318
|
+
scout_config.output_format = :json
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
config.after(:suite) do
|
|
323
|
+
# Run Spec Scout analysis after test suite
|
|
324
|
+
scout = SpecScout::SpecScout.new
|
|
325
|
+
results = scout.analyze
|
|
326
|
+
|
|
327
|
+
# Process results as needed
|
|
328
|
+
if results[:recommendation]&.confidence == :high
|
|
329
|
+
puts "High confidence optimization available!"
|
|
330
|
+
puts results[:recommendation].explanation
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### TestProf Integration
|
|
337
|
+
|
|
338
|
+
Spec Scout automatically integrates with TestProf. Ensure TestProf is configured in your test suite:
|
|
339
|
+
|
|
340
|
+
```ruby
|
|
341
|
+
# spec/spec_helper.rb or test/test_helper.rb
|
|
342
|
+
require 'test_prof'
|
|
343
|
+
|
|
344
|
+
# TestProf configuration (optional - Spec Scout will enable profiling automatically)
|
|
345
|
+
TestProf.configure do |config|
|
|
346
|
+
config.output_dir = 'tmp/test_prof'
|
|
347
|
+
end
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
## Troubleshooting
|
|
351
|
+
|
|
352
|
+
### Common Issues
|
|
353
|
+
|
|
354
|
+
#### "No profile data available"
|
|
355
|
+
- Ensure TestProf is installed and configured
|
|
356
|
+
- Check that specs are actually running
|
|
357
|
+
- Verify TestProf integration is enabled: `config.use_test_prof = true`
|
|
358
|
+
|
|
359
|
+
#### "No agents produced results"
|
|
360
|
+
- Check that agents are enabled: `config.enabled_agents`
|
|
361
|
+
- Verify profile data contains relevant metrics
|
|
362
|
+
- Enable debug mode: `SPEC_SCOUT_DEBUG=1`
|
|
363
|
+
|
|
364
|
+
#### "TestProf execution failed"
|
|
365
|
+
- Ensure TestProf is compatible with your Ruby/Rails version
|
|
366
|
+
- Check TestProf configuration for conflicts
|
|
367
|
+
- Run TestProf directly to isolate issues: `bundle exec rspec --profile`
|
|
368
|
+
|
|
369
|
+
### Debug Mode
|
|
370
|
+
|
|
371
|
+
Enable debug output to troubleshoot issues:
|
|
372
|
+
|
|
373
|
+
```bash
|
|
374
|
+
SPEC_SCOUT_DEBUG=1 bundle exec spec_scout spec/models/user_spec.rb
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Debug output includes:
|
|
378
|
+
- TestProf integration status
|
|
379
|
+
- Agent execution details
|
|
380
|
+
- Profile data normalization
|
|
381
|
+
- Consensus engine decisions
|
|
382
|
+
|
|
383
|
+
### Performance Considerations
|
|
384
|
+
|
|
385
|
+
- Spec Scout adds minimal overhead beyond TestProf execution
|
|
386
|
+
- Agent analysis typically takes < 2ms per example
|
|
387
|
+
- Large test suites (10k+ examples) are supported
|
|
388
|
+
- Memory usage is optimized to prevent leaks
|
|
389
|
+
|
|
390
|
+
## Development
|
|
391
|
+
|
|
392
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
393
|
+
|
|
394
|
+
### Running Tests
|
|
395
|
+
|
|
396
|
+
```bash
|
|
397
|
+
# Run all tests
|
|
398
|
+
bundle exec rspec
|
|
399
|
+
|
|
400
|
+
# Run unit tests only
|
|
401
|
+
bundle exec rspec spec/lib
|
|
402
|
+
|
|
403
|
+
# Run integration tests
|
|
404
|
+
bundle exec rspec spec/integration
|
|
405
|
+
|
|
406
|
+
# Run property-based tests
|
|
407
|
+
bundle exec rspec spec/properties
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### Contributing
|
|
411
|
+
|
|
412
|
+
1. Fork the repository
|
|
413
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
414
|
+
3. Write tests for your changes
|
|
415
|
+
4. Ensure all tests pass (`bundle exec rspec`)
|
|
416
|
+
5. Commit your changes (`git commit -am 'Add some feature'`)
|
|
417
|
+
6. Push to the branch (`git push origin my-new-feature`)
|
|
418
|
+
7. Create a Pull Request
|
|
419
|
+
|
|
420
|
+
## Compatibility
|
|
421
|
+
|
|
422
|
+
- **Ruby**: 2.7.0 or higher
|
|
423
|
+
- **Rails**: 5.2 or higher (for TestProf integration)
|
|
424
|
+
- **TestProf**: 1.0 or higher
|
|
425
|
+
|
|
426
|
+
## License
|
|
427
|
+
|
|
428
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
429
|
+
|
|
430
|
+
## Acknowledgments
|
|
431
|
+
|
|
432
|
+
- Built on top of [TestProf](https://github.com/test-prof/test-prof) by Vladimir Dementyev
|
|
433
|
+
- Inspired by the Ruby testing community's focus on performance optimization
|