Initial commit
This commit is contained in:
242
skills/rails-test-patterns/skill.md
Normal file
242
skills/rails-test-patterns/skill.md
Normal file
@@ -0,0 +1,242 @@
|
||||
---
|
||||
name: rails-test-patterns
|
||||
description: Ensures comprehensive test coverage following Rails testing best practices
|
||||
auto_invoke: true
|
||||
trigger_on: [file_create, file_modify]
|
||||
file_patterns: ["**/spec/**/*_spec.rb", "**/test/**/*_test.rb"]
|
||||
tags: [rails, testing, rspec, minitest, coverage, tdd]
|
||||
priority: 2
|
||||
version: 2.0
|
||||
---
|
||||
|
||||
# Rails Test Patterns Skill
|
||||
|
||||
Automatically ensures test quality and comprehensive coverage.
|
||||
|
||||
## What This Skill Does
|
||||
|
||||
**Automatic Checks:**
|
||||
- Test framework detection (RSpec vs Minitest)
|
||||
- AAA pattern (Arrange-Act-Assert)
|
||||
- Coverage thresholds (80%+ models, 70%+ controllers)
|
||||
- Factory usage over fixtures
|
||||
- No flaky tests (sleep, Time.now without freezing)
|
||||
|
||||
**When It Activates:**
|
||||
- Test files created or modified
|
||||
- New models/controllers added (ensures tests exist)
|
||||
|
||||
## Test Quality Checks
|
||||
|
||||
### 1. AAA Pattern
|
||||
|
||||
**Good:**
|
||||
```ruby
|
||||
RSpec.describe User do
|
||||
describe '#full_name' do
|
||||
it 'combines first and last name' do
|
||||
# Arrange
|
||||
user = User.new(first_name: 'John', last_name: 'Doe')
|
||||
|
||||
# Act
|
||||
result = user.full_name
|
||||
|
||||
# Assert
|
||||
expect(result).to eq('John Doe')
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
**Skill Output (if violated):**
|
||||
```
|
||||
⚠️ Test Pattern: AAA structure not clear
|
||||
Location: spec/models/user_spec.rb:15
|
||||
Recommendation: Separate Arrange, Act, Assert with comments
|
||||
```
|
||||
|
||||
### 2. Framework Detection
|
||||
|
||||
**Detects:**
|
||||
```ruby
|
||||
# RSpec
|
||||
describe Model do
|
||||
it 'does something' do
|
||||
expect(value).to eq(expected)
|
||||
end
|
||||
end
|
||||
|
||||
# Minitest
|
||||
class ModelTest < ActiveSupport::TestCase
|
||||
test "does something" do
|
||||
assert_equal expected, value
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
### 3. Factory Usage
|
||||
|
||||
**Preferred:**
|
||||
```ruby
|
||||
# spec/factories/users.rb
|
||||
FactoryBot.define do
|
||||
factory :user do
|
||||
email { Faker::Internet.email }
|
||||
name { Faker::Name.name }
|
||||
end
|
||||
end
|
||||
|
||||
# In tests
|
||||
user = create(:user)
|
||||
```
|
||||
|
||||
**Skill Output:**
|
||||
```
|
||||
ℹ️ Test Pattern: Consider using FactoryBot
|
||||
Location: spec/models/post_spec.rb:8
|
||||
Current: User.create(name: 'Test', email: 'test@example.com')
|
||||
Recommendation: Define factory and use create(:user)
|
||||
```
|
||||
|
||||
### 4. Coverage Thresholds
|
||||
|
||||
**Checks:**
|
||||
- Models: 80%+ coverage
|
||||
- Controllers: 70%+ coverage
|
||||
- Services: 90%+ coverage
|
||||
|
||||
**Skill Output:**
|
||||
```
|
||||
⚠️ Test Coverage: Below threshold
|
||||
File: app/models/order.rb
|
||||
Coverage: 65% (threshold: 80%)
|
||||
Missing: #calculate_total, #apply_discount methods
|
||||
|
||||
Add tests for uncovered methods.
|
||||
```
|
||||
|
||||
### 5. Flaky Test Detection
|
||||
|
||||
**Problem:**
|
||||
```ruby
|
||||
# BAD
|
||||
it 'expires after 1 hour' do
|
||||
user = create(:user)
|
||||
sleep(3601) # ❌ Actual waiting
|
||||
expect(user.expired?).to be true
|
||||
end
|
||||
|
||||
# GOOD
|
||||
it 'expires after 1 hour' do
|
||||
user = create(:user)
|
||||
travel 1.hour do # ✅ Time travel
|
||||
expect(user.expired?).to be true
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
**Skill Output:**
|
||||
```
|
||||
❌ Test Anti-pattern: Using sleep in test
|
||||
Location: spec/models/session_spec.rb:42
|
||||
Issue: sleep() makes tests slow and flaky
|
||||
|
||||
Fix: Use time helpers
|
||||
travel 1.hour do
|
||||
# assertions here
|
||||
end
|
||||
```
|
||||
|
||||
## Test Types
|
||||
|
||||
### Model Tests
|
||||
|
||||
**Should test:**
|
||||
- Validations
|
||||
- Associations
|
||||
- Scopes
|
||||
- Instance methods
|
||||
- Class methods
|
||||
|
||||
**Example:**
|
||||
```ruby
|
||||
RSpec.describe Post, type: :model do
|
||||
describe 'validations' do
|
||||
it { should validate_presence_of(:title) }
|
||||
it { should validate_uniqueness_of(:slug) }
|
||||
end
|
||||
|
||||
describe 'associations' do
|
||||
it { should belong_to(:user) }
|
||||
it { should have_many(:comments) }
|
||||
end
|
||||
|
||||
describe '#published?' do
|
||||
it 'returns true when published_at is set' do
|
||||
post = build(:post, published_at: 1.day.ago)
|
||||
expect(post.published?).to be true
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
### Request Tests
|
||||
|
||||
**Should test:**
|
||||
- HTTP status codes
|
||||
- Response body content
|
||||
- Authentication requirements
|
||||
- Authorization checks
|
||||
|
||||
**Example:**
|
||||
```ruby
|
||||
RSpec.describe 'Posts API', type: :request do
|
||||
describe 'GET /api/v1/posts' do
|
||||
it 'returns all posts' do
|
||||
create_list(:post, 3)
|
||||
|
||||
get '/api/v1/posts'
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(JSON.parse(response.body).size).to eq(3)
|
||||
end
|
||||
|
||||
context 'when not authenticated' do
|
||||
it 'returns unauthorized' do
|
||||
get '/api/v1/posts'
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
```yaml
|
||||
# .rails-testing.yml
|
||||
coverage:
|
||||
models: 80
|
||||
controllers: 70
|
||||
services: 90
|
||||
|
||||
patterns:
|
||||
enforce_aaa: warning
|
||||
require_factories: info
|
||||
detect_flaky: error
|
||||
|
||||
framework:
|
||||
auto_detect: true
|
||||
prefer: rspec # or minitest
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- **RSpec Best Practices**: https://rspec.info/
|
||||
- **Minitest Guide**: https://github.com/minitest/minitest
|
||||
- **FactoryBot**: https://github.com/thoughtbot/factory_bot
|
||||
- **Pattern Library**: /patterns/testing-patterns.md
|
||||
|
||||
---
|
||||
|
||||
**This skill ensures your Rails app has comprehensive, maintainable test coverage.**
|
||||
Reference in New Issue
Block a user