rspec-gary
RSpec testing guidelines following the GARY principle (Go Ahead, Repeat Yourself). Use this when writing tests for a Ruby project to prioritise readability and maintainability.
What this skill does
# RSpec Testing: Be More GARY
When writing RSpec tests, follow the **GARY** principle: **Go Ahead, Repeat Yourself**.
While executable code should be DRY, test code *describes*, *verifies*, and *documents* system knowledge.
Prioritise **readability over brevity**.
## When to use this skill
Use when the user wants to write RSpec tests that are easy to read, understand, and maintain.
## Core principles
Every test tells a story using Arrange-Act-Assert:
```ruby
# Arrange - set up the world
user = create(:user)
post = create(:post, author: user)
# Act - perform the action
post.publish!
# Assert - verify the outcome
expect(post).to be_published
```
A reader should understand the test **top to bottom** without hunting for `let` or `before` blocks.
## Guidelines
### 1. Prefer inline setup over `let`
`let` statements create invisible dependencies and force readers to jump around:
```ruby
# Avoid: Reader must hunt for definitions, lazy evaluation hides dependencies
let(:jon) { create(:person) }
let(:garfield) { create(:cat, owner: jon) }
let(:odie) { create(:dog, owner: jon) }
it 'has daily fights when pets are enemies' do
# Fails! garfield and odie never instantiated due to lazy evaluation
expect(Household.new(jon).daily_fights.size).to be_positive
end
```
```ruby
# Prefer: Self-contained, linear story
it 'has daily fights when pets are enemies' do
jon = create(:person)
garfield = create(:cat, owner: jon)
odie = create(:dog, owner: jon)
garfield.enemies << odie
expect(Household.new(jon).daily_fights.size).to be_positive
end
```
**Never override `let` in nested contexts** - it forces readers to trace inheritance chains.
### 2. Extract only narrative noise
Values required but irrelevant to the test's story can be extracted:
```ruby
# OK: valid_oauth_token is noise, not part of this test's story
let(:valid_oauth_token) { 'abc123...' }
it 'returns the user profile for a valid request' do
user = create(:user, name: 'Alice')
get '/api/profile', headers: { 'Authorization' => "Bearer #{valid_oauth_token}" }
expect(response.parsed_body['name']).to eq('Alice')
end
```
If a value is central to understanding the test, keep it inline even if repeated.
### 3. Keep actions in the test body
Don't hide actions in `before` blocks or factories - everything being asserted should be performed in the test itself.
```ruby
# Avoid:
before { post.publish! } # Action hidden
# Prefer: Action visible in test
it 'publishes the post' do
post = create(:post)
post.publish!
expect(post).to be_published
end
```
### 4. Name variables for context
```ruby
it 'rejects expired tokens' do
expired_token = create(:oauth_token, expires_at: 1.day.ago)
get '/api/profile', headers: auth_header(expired_token)
expect(response).to have_http_status(:unauthorized)
end
```
### 5. Control values, don't extract them
```ruby
# Avoid: Extracting generated values
voip_session = create(:voip_session)
phone_number = voip_session.psid.phone_number
# Prefer: Controlling the value
phone_number = "+447001234567"
voip_session = create(:voip_session, phone_number: phone_number)
```
IDs may be an exception when code requires IDs rather than objects.
### 6. Use helper methods for complex setup
Keep helpers close to the specs that use them:
```ruby
def build_classroom_with_students(student_count:)
school = create(:school)
classroom = create(:classroom, school: school)
create_list(:student, student_count, classroom: classroom)
classroom
end
it 'calculates average reading level' do
classroom = build_classroom_with_students(student_count: 5)
expect(classroom.average_reading_level).to be_present
end
```
## When repetition becomes a problem
If copying 10+ lines across many tests, consider:
1. **Helper methods in the spec file** - keep them close
2. **Shared examples** - only for genuinely shared *behaviour*, not shared *setup*
3. **Custom matchers** - for complex assertions
Always ask: does extraction make each test easier or harder to understand in isolation?
**The test:** Can a developer unfamiliar with this code understand the test in one read-through?
When this test fails in 2 years, will the error message and test code make the problem obvious?
Related in Writing & Docs
jax-development
IncludedUse this skill when the user is writing, debugging, profiling, refactoring, reviewing, benchmarking, parallelising, exporting, or explaining JAX code, or when they mention JAX, jax.numpy, jit, grad, value_and_grad, vmap, scan, lax, random keys, pytrees, jax.Array, sharding, Mesh, PartitionSpec, NamedSharding, pmap, shard_map, Pallas, XLA, StableHLO, checkify, profiler, or the JAX repo. It helps turn NumPy or PyTorch-style code into pure functional JAX, fix tracer/control-flow/shape/PRNG bugs, remove recompiles and host-device syncs, choose transforms and sharding strategies, inspect jaxpr/lowering/IR, and benchmark compiled code correctly.
nature-article-writer
IncludedDrafts, rewrites, diagnostically critiques, and style-calibrates primary research manuscripts for Nature and Nature Portfolio journals. Use when the user wants a Nature-style title, summary paragraph or abstract, introduction, results, discussion, methods, figure legends, presubmission enquiry, cover letter, reviewer response, or when a scientific draft sounds generic, jargon-heavy, structurally weak, or AI-ish and needs precise, broad-reader-friendly prose without inventing data, analyses, or references. Best for primary research articles and letters rather than reviews or press releases unless explicitly adapting one.
deckrd
IncludedDocument-driven framework that derives requirements, specifications, implementation plans, and executable tasks from goals through structured AI dialogue. Use when user says "write requirements", "create spec", "plan implementation", "derive tasks", "structure this feature", "break down into tasks", or "document this module". Also use for reverse engineering existing code into docs (/deckrd rev). Do NOT use for direct code writing — use /deckrd-coder after tasks are generated. Do NOT use when the user only wants to run or fix existing code without planning.
clinical-decision-support
IncludedGenerate professional clinical decision support (CDS) documents for pharmaceutical and clinical research settings, including patient cohort analyses (biomarker-stratified with outcomes) and treatment recommendation reports (evidence-based guidelines with decision algorithms). Supports GRADE evidence grading, statistical analysis (hazard ratios, survival curves, waterfall plots), biomarker integration, and regulatory compliance. Outputs publication-ready LaTeX/PDF format optimized for drug development, clinical research, and evidence synthesis.
handling-sf-data
IncludedSalesforce data operations with 130-point scoring. Use this skill to create, update, delete, bulk import/export, generate test data, and clean up org records using sf CLI and anonymous Apex. TRIGGER when: user creates test data, performs bulk import/export, uses sf data CLI commands, needs data factory patterns for Apex tests, or needs to seed/clean records in a Salesforce org. DO NOT TRIGGER when: SOQL query writing only (use querying-soql), Apex test execution (use running-apex-tests), or metadata deployment (use deploying-metadata).
accelint-ac-to-playwright
IncludedConvert and validate acceptance criteria for Playwright test automation. Use when user asks to (1) review/evaluate/check if AC are ready for automation, (2) assess if AC can be converted as-is, (3) validate AC quality for Playwright, (4) turn AC into tests, (5) generate tests from acceptance criteria, (6) convert .md bullets or .feature Gherkin files to Playwright specs, (7) create test automation from requirements. Handles both bullet-style markdown and Gherkin syntax with JSON test plan generation and validation.