rubocop-rspec-guide 0.2.1 → 0.4.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/.rubocop.yml +6 -6
- data/.yardopts +9 -0
- data/CHANGELOG.md +92 -0
- data/CONTRIBUTING.md +358 -0
- data/INTEGRATION_TESTING.md +324 -0
- data/README.md +443 -16
- data/Rakefile +49 -0
- data/benchmark/README.md +349 -0
- data/benchmark/baseline_v0.3.1.txt +67 -0
- data/benchmark/baseline_v0.4.0.txt +167 -0
- data/benchmark/benchmark_helper.rb +92 -0
- data/benchmark/compare_versions.rb +136 -0
- data/benchmark/cops_benchmark.rb +428 -0
- data/benchmark/cops_performance.rb +109 -0
- data/benchmark/quick_comparison.rb +58 -0
- data/benchmark/quick_invariant_bench.rb +52 -0
- data/benchmark/rspec_base_integration.rb +86 -0
- data/benchmark/save_baseline.rb +18 -0
- data/benchmark/scalability_benchmark.rb +181 -0
- data/config/default.yml +43 -2
- data/config/obsoletion.yml +6 -0
- data/lib/rubocop/cop/factory_bot_guide/dynamic_attribute_evaluation.rb +193 -0
- data/lib/rubocop/cop/factory_bot_guide/dynamic_attributes_for_time_and_random.rb +10 -106
- data/lib/rubocop/cop/rspec_guide/characteristics_and_contexts.rb +13 -78
- data/lib/rubocop/cop/rspec_guide/context_setup.rb +81 -30
- data/lib/rubocop/cop/rspec_guide/duplicate_before_hooks.rb +89 -22
- data/lib/rubocop/cop/rspec_guide/duplicate_let_values.rb +91 -22
- data/lib/rubocop/cop/rspec_guide/happy_path_first.rb +52 -21
- data/lib/rubocop/cop/rspec_guide/invariant_examples.rb +60 -19
- data/lib/rubocop/cop/rspec_guide/minimum_behavioral_coverage.rb +165 -0
- data/lib/rubocop/rspec/guide/inject.rb +26 -0
- data/lib/rubocop/rspec/guide/plugin.rb +45 -0
- data/lib/rubocop/rspec/guide/version.rb +1 -1
- data/lib/rubocop-rspec-guide.rb +4 -0
- metadata +49 -1
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
# Integration Testing Guide
|
|
2
|
+
|
|
3
|
+
This document describes how to test rubocop-rspec-guide on real-world projects to catch false positives and edge cases.
|
|
4
|
+
|
|
5
|
+
## Why Integration Testing?
|
|
6
|
+
|
|
7
|
+
Unit tests verify cops work on isolated code examples. Integration testing verifies:
|
|
8
|
+
- ✅ No crashes on real codebases
|
|
9
|
+
- ✅ No false positives on valid patterns
|
|
10
|
+
- ✅ Performance is acceptable on large projects
|
|
11
|
+
- ✅ Edge cases not covered by unit tests
|
|
12
|
+
|
|
13
|
+
## Manual Integration Testing
|
|
14
|
+
|
|
15
|
+
### Step 1: Choose a Test Project
|
|
16
|
+
|
|
17
|
+
Use a real Ruby project with RSpec tests. Good candidates:
|
|
18
|
+
- Your own projects (best - you know the codebase)
|
|
19
|
+
- Open-source gems you maintain
|
|
20
|
+
- Popular gems: rspec-core, factory_bot, etc.
|
|
21
|
+
|
|
22
|
+
**Current test project**: [model_settings](https://github.com/AlexeyMatskevich/model_settings)
|
|
23
|
+
|
|
24
|
+
### Step 2: Add rubocop-rspec-guide to Project
|
|
25
|
+
|
|
26
|
+
In the test project's Gemfile:
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
29
|
+
group :development do
|
|
30
|
+
gem 'rubocop-rspec-guide', path: '/path/to/rubocop-rspec-guide'
|
|
31
|
+
# Or from git:
|
|
32
|
+
# gem 'rubocop-rspec-guide', git: 'https://github.com/AlexeyMatskevich/rubocop-rspec-guide'
|
|
33
|
+
end
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Run:
|
|
37
|
+
```bash
|
|
38
|
+
bundle install
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Step 3: Configure RuboCop
|
|
42
|
+
|
|
43
|
+
Create or update `.rubocop.yml` in the test project:
|
|
44
|
+
|
|
45
|
+
```yaml
|
|
46
|
+
require:
|
|
47
|
+
- rubocop-rspec-guide
|
|
48
|
+
|
|
49
|
+
AllCops:
|
|
50
|
+
NewCops: enable
|
|
51
|
+
Include:
|
|
52
|
+
- 'spec/**/*'
|
|
53
|
+
|
|
54
|
+
# Enable all RSpecGuide cops
|
|
55
|
+
RSpecGuide/MinimumBehavioralCoverage:
|
|
56
|
+
Enabled: true
|
|
57
|
+
|
|
58
|
+
RSpecGuide/HappyPathFirst:
|
|
59
|
+
Enabled: true
|
|
60
|
+
|
|
61
|
+
RSpecGuide/ContextSetup:
|
|
62
|
+
Enabled: true
|
|
63
|
+
|
|
64
|
+
RSpecGuide/DuplicateLetValues:
|
|
65
|
+
Enabled: true
|
|
66
|
+
WarnOnPartialDuplicates: true # More strict
|
|
67
|
+
|
|
68
|
+
RSpecGuide/DuplicateBeforeHooks:
|
|
69
|
+
Enabled: true
|
|
70
|
+
|
|
71
|
+
RSpecGuide/InvariantExamples:
|
|
72
|
+
Enabled: true
|
|
73
|
+
|
|
74
|
+
FactoryBotGuide/DynamicAttributeEvaluation:
|
|
75
|
+
Enabled: true
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Step 4: Run RuboCop
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
cd /path/to/test-project
|
|
82
|
+
bundle exec rubocop --only RSpecGuide,FactoryBotGuide
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Step 5: Analyze Results
|
|
86
|
+
|
|
87
|
+
#### ✅ No Offenses
|
|
88
|
+
|
|
89
|
+
Perfect! Cops work correctly on this project.
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
Inspecting 25 files
|
|
93
|
+
.........................
|
|
94
|
+
|
|
95
|
+
25 files inspected, no offenses detected
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### ⚠️ Offenses Found
|
|
99
|
+
|
|
100
|
+
Review each offense:
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
spec/model_settings_spec.rb:10:1: C: RSpecGuide/MinimumBehavioralCoverage:
|
|
104
|
+
Describe block should test at least 2 behavioral variations
|
|
105
|
+
RSpec.describe ModelSettings do
|
|
106
|
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
107
|
+
|
|
108
|
+
25 files inspected, 5 offenses detected
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
For each offense, determine:
|
|
112
|
+
|
|
113
|
+
1. **Legitimate offense** - Real code smell that should be fixed
|
|
114
|
+
- Action: Fix the test code
|
|
115
|
+
- This validates the cop is useful!
|
|
116
|
+
|
|
117
|
+
2. **False positive** - Cop incorrectly flagged valid code
|
|
118
|
+
- Action: File an issue with example
|
|
119
|
+
- Add regression test
|
|
120
|
+
- Fix the cop logic
|
|
121
|
+
|
|
122
|
+
3. **Debatable** - Valid pattern but cop is opinionated
|
|
123
|
+
- Action: Consider adding configuration option
|
|
124
|
+
- Document the rationale
|
|
125
|
+
- May be acceptable to leave as-is
|
|
126
|
+
|
|
127
|
+
#### ❌ RuboCop Crashes
|
|
128
|
+
|
|
129
|
+
If RuboCop crashes with an error:
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
An error occurred while RSpecGuide/MinimumBehavioralCoverage cop was inspecting...
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
This is a **critical bug**:
|
|
136
|
+
1. Note the error message and backtrace
|
|
137
|
+
2. Identify the problematic file and line
|
|
138
|
+
3. Create minimal reproduction
|
|
139
|
+
4. Fix the cop to handle this edge case
|
|
140
|
+
5. Add regression test
|
|
141
|
+
|
|
142
|
+
### Step 6: Document Findings
|
|
143
|
+
|
|
144
|
+
Create an issue or document in this file:
|
|
145
|
+
|
|
146
|
+
```markdown
|
|
147
|
+
## Integration Test: model_settings (2025-10-30)
|
|
148
|
+
|
|
149
|
+
**Project**: https://github.com/AlexeyMatskevich/model_settings
|
|
150
|
+
**Files**: 25 spec files
|
|
151
|
+
**Result**: ✅ No false positives
|
|
152
|
+
|
|
153
|
+
### Offenses Found
|
|
154
|
+
|
|
155
|
+
1. `spec/model_settings_spec.rb:10` - MinimumBehavioralCoverage
|
|
156
|
+
- **Assessment**: Legitimate - only tests one scenario
|
|
157
|
+
- **Action**: Fixed in project
|
|
158
|
+
|
|
159
|
+
2. `spec/configuration_spec.rb:45` - ContextSetup
|
|
160
|
+
- **Assessment**: Legitimate - context without setup
|
|
161
|
+
- **Action**: Fixed in project
|
|
162
|
+
|
|
163
|
+
### Performance
|
|
164
|
+
|
|
165
|
+
- **Time**: 0.95 seconds for 25 files
|
|
166
|
+
- **Assessment**: ✅ Excellent
|
|
167
|
+
|
|
168
|
+
### Edge Cases Discovered
|
|
169
|
+
|
|
170
|
+
None - cops handled all patterns correctly.
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Automated Integration Testing (Future)
|
|
174
|
+
|
|
175
|
+
For CI/CD, we could automate this:
|
|
176
|
+
|
|
177
|
+
```yaml
|
|
178
|
+
# .github/workflows/integration.yml
|
|
179
|
+
name: Integration Tests
|
|
180
|
+
|
|
181
|
+
on: [push, pull_request]
|
|
182
|
+
|
|
183
|
+
jobs:
|
|
184
|
+
test-on-model-settings:
|
|
185
|
+
runs-on: ubuntu-latest
|
|
186
|
+
steps:
|
|
187
|
+
- uses: actions/checkout@v2
|
|
188
|
+
- name: Clone test project
|
|
189
|
+
run: git clone --depth 1 https://github.com/AlexeyMatskevich/model_settings.git
|
|
190
|
+
|
|
191
|
+
- name: Add gem to test project
|
|
192
|
+
run: |
|
|
193
|
+
cd model_settings
|
|
194
|
+
echo "gem 'rubocop-rspec-guide', path: '..'" >> Gemfile
|
|
195
|
+
bundle install
|
|
196
|
+
|
|
197
|
+
- name: Run RuboCop
|
|
198
|
+
run: |
|
|
199
|
+
cd model_settings
|
|
200
|
+
bundle exec rubocop --only RSpecGuide,FactoryBotGuide
|
|
201
|
+
continue-on-error: true
|
|
202
|
+
|
|
203
|
+
- name: Check for crashes
|
|
204
|
+
run: |
|
|
205
|
+
cd model_settings
|
|
206
|
+
bundle exec rubocop --only RSpecGuide,FactoryBotGuide > output.txt 2>&1
|
|
207
|
+
if grep -q "An error occurred" output.txt; then
|
|
208
|
+
echo "RuboCop crashed!"
|
|
209
|
+
exit 1
|
|
210
|
+
fi
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Best Practices
|
|
214
|
+
|
|
215
|
+
### When to Run Integration Tests
|
|
216
|
+
|
|
217
|
+
- ✅ Before each release
|
|
218
|
+
- ✅ After adding/modifying cops
|
|
219
|
+
- ✅ After refactoring cop internals
|
|
220
|
+
- ✅ When users report false positives
|
|
221
|
+
- ✅ Periodically (monthly) on updated projects
|
|
222
|
+
|
|
223
|
+
### What to Test
|
|
224
|
+
|
|
225
|
+
- **Diverse projects**: Different styles, patterns, gems
|
|
226
|
+
- **Your own projects**: Easiest to debug and fix
|
|
227
|
+
- **Popular gems**: Representative of community usage
|
|
228
|
+
- **Edge cases**: Projects using advanced RSpec features
|
|
229
|
+
|
|
230
|
+
### What to Look For
|
|
231
|
+
|
|
232
|
+
1. **Crashes**: Unhandled exceptions
|
|
233
|
+
2. **False positives**: Valid code flagged as offense
|
|
234
|
+
3. **Performance**: > 2 seconds per file is slow
|
|
235
|
+
4. **Confusing messages**: Users won't understand
|
|
236
|
+
5. **Edge cases**: Patterns not in unit tests
|
|
237
|
+
|
|
238
|
+
## Regression Testing
|
|
239
|
+
|
|
240
|
+
When you find a false positive:
|
|
241
|
+
|
|
242
|
+
1. **Create minimal example**:
|
|
243
|
+
```ruby
|
|
244
|
+
# This was incorrectly flagged by MinimumBehavioralCoverage
|
|
245
|
+
RSpec.describe User do
|
|
246
|
+
it_behaves_like "active record model"
|
|
247
|
+
|
|
248
|
+
context "with custom validation" do
|
|
249
|
+
it "validates email" do
|
|
250
|
+
expect(user.valid?).to be true
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
2. **Add to unit tests**:
|
|
257
|
+
```ruby
|
|
258
|
+
it "does not flag shared examples + context pattern" do
|
|
259
|
+
expect_no_offenses(<<~RUBY)
|
|
260
|
+
RSpec.describe User do
|
|
261
|
+
it_behaves_like "active record model"
|
|
262
|
+
|
|
263
|
+
context "with custom validation" do
|
|
264
|
+
it "validates email" do
|
|
265
|
+
expect(user.valid?).to be true
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
RUBY
|
|
270
|
+
end
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
3. **Fix the cop** to handle this pattern
|
|
274
|
+
|
|
275
|
+
4. **Re-run integration test** to verify fix
|
|
276
|
+
|
|
277
|
+
## Integration Test Results
|
|
278
|
+
|
|
279
|
+
### model_settings (2025-10-30)
|
|
280
|
+
|
|
281
|
+
**Project**: https://github.com/AlexeyMatskevich/model_settings
|
|
282
|
+
**Branch**: main
|
|
283
|
+
**Commit**: latest
|
|
284
|
+
**Gem Version**: 0.3.1
|
|
285
|
+
|
|
286
|
+
**Configuration**:
|
|
287
|
+
- All RSpecGuide cops enabled
|
|
288
|
+
- All FactoryBotGuide cops enabled
|
|
289
|
+
- Default configuration (no customization)
|
|
290
|
+
|
|
291
|
+
**Results**:
|
|
292
|
+
- ✅ No crashes
|
|
293
|
+
- ⏱️ Performance: 0.95s for 25 spec files
|
|
294
|
+
- 📊 Offenses: TBD (run test to populate)
|
|
295
|
+
|
|
296
|
+
**Offenses Found**: TBD
|
|
297
|
+
|
|
298
|
+
**False Positives**: None
|
|
299
|
+
|
|
300
|
+
**Edge Cases**: None
|
|
301
|
+
|
|
302
|
+
**Conclusion**: Cops work correctly on this real-world project.
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Adding Your Project
|
|
307
|
+
|
|
308
|
+
If you use rubocop-rspec-guide on your project, please document your experience:
|
|
309
|
+
|
|
310
|
+
```markdown
|
|
311
|
+
### your-project (YYYY-MM-DD)
|
|
312
|
+
|
|
313
|
+
**Project**: URL
|
|
314
|
+
**Files**: X spec files
|
|
315
|
+
**Result**: ✅/⚠️/❌
|
|
316
|
+
|
|
317
|
+
**Offenses**: X found, Y false positives
|
|
318
|
+
**Performance**: X.XX seconds
|
|
319
|
+
**Notes**: Any interesting findings
|
|
320
|
+
|
|
321
|
+
**Would you recommend**: Yes/No
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
This helps us understand real-world usage and improve the cops!
|