Guides Test-Driven Development workflow with Red-Green-Refactor cycle. Use when the user wants to implement a feature using TDD, write tests first, follow test-driven practices, or mentions red-green-refactor.
This skill guides you through the Test-Driven Development cycle:
Copy and track progress:
TDD Progress:
- [ ] Step 1: Understand the requirement
- [ ] Step 2: Choose test type (unit/request/system)
- [ ] Step 3: Write failing spec (RED)
- [ ] Step 4: Verify spec fails correctly
- [ ] Step 5: Implement minimal code (GREEN)
- [ ] Step 6: Verify spec passes
- [ ] Step 7: Refactor if needed
- [ ] Step 8: Verify specs still pass
Before writing any code, understand:
Ask clarifying questions if requirements are ambiguous.
| Test Type | Use For | Location | Example |
|-----------|---------|----------|---------|
| Model spec | Validations, scopes, instance methods | spec/models/ | Testing User#full_name |
| Request spec | API endpoints, HTTP responses | spec/requests/ | Testing POST /api/users |
| System spec | Full user flows with JavaScript | spec/system/ or spec/e2e/ | Testing login flow |
| Service spec | Business logic, complex operations | spec/services/ | Testing CreateOrderService |
| Job spec | Background job behavior | spec/jobs/ | Testing SendEmailJob |
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe ClassName, type: :spec_type do
describe '#method_name' do
subject { described_class.new(args) }
context 'when condition is met' do
let(:dependency) { create(:factory) }
it 'behaves as expected' do
expect(subject.method_name).to eq(expected_value)
end
end
context 'when edge case' do
it 'handles gracefully' do
expect { subject.method_name }.to raise_error(SpecificError)
end
end
end
end
it block tests one thingdescribe/contextbuild over create when possibleRun the spec:
bundle exec rspec path/to/spec.rb --format documentation
The spec MUST fail with a clear message indicating:
Important: If the spec passes immediately, you're not doing TDD. Either:
Write the MINIMUM code to pass:
# Start with the simplest thing that could work
def full_name
"#{first_name} #{last_name}"
end
Run the spec again:
bundle exec rspec path/to/spec.rb --format documentation
It MUST pass. If it fails:
Now improve the code while keeping tests green:
Run all related specs:
bundle exec rspec spec/models/user_spec.rb
All specs must pass. If any fail:
describe 'validations' do
it { is_expected.to validate_presence_of(:email) }
it { is_expected.to validate_uniqueness_of(:email).case_insensitive }
it { is_expected.to validate_length_of(:name).is_at_most(100) }
end
describe 'associations' do
it { is_expected.to belong_to(:organization) }
it { is_expected.to have_many(:posts).dependent(:destroy) }
end
describe '.active' do
let!(:active_user) { create(:user, status: :active) }
let!(:inactive_user) { create(:user, status: :inactive) }
it 'returns only active users' do
expect(User.active).to contain_exactly(active_user)
end
end
describe '#call' do
subject(:result) { described_class.new.call(params) }
context 'with valid params' do
let(:params) { { email: 'test@example.com' } }
it 'returns success' do
expect(result).to be_success
end
it 'creates a user' do
expect { result }.to change(User, :count).by(1)
end
end
context 'with invalid params' do
let(:params) { { email: '' } }
it 'returns failure' do
expect(result).to be_failure
end
end
end
build over create, mock external servicesSearch for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer