Comprehensive testing guide for Ruby on Rails applications, maintained by Community. Contains 46 rules across 8 categories, prioritized by impact to guide automated test generation, review, and refactoring.
When to Apply
Reference these guidelines when:
Writing new RSpec specs for models, requests, system tests, or jobs
Setting up FactoryBot factories with traits and sequences
Writing Capybara system tests for user journeys
Testing background jobs with Sidekiq or Active Job
Reviewing test code for anti-patterns (mystery guests, flaky tests, slow specs)
Optimizing test suite performance and CI pipeline speed
Organizing test files, shared examples, and custom matchers
Rule Categories by Priority
Priority
Category
Impact
Prefix
1
Test Design & Structure
CRITICAL
design-
2
Test Data Management
CRITICAL
data-
3
Model Testing
HIGH
model-
4
Request & Controller Testing
HIGH
request-
5
System & Acceptance Testing
MEDIUM-HIGH
system-
6
Async & Background Job Testing
MEDIUM
async-
7
Test Performance & Reliability
MEDIUM
perf-
8
Test Organization & Maintenance
LOW-MEDIUM
org-
Quick Reference
1. Test Design & Structure (CRITICAL)
design-four-phase-test - Use four-phase test structure (setup, exercise, verify, teardown)
design-behavior-over-implementation - Test observable behavior, not internal implementation
design-one-assertion-per-test - One logical expectation per test for precise failure diagnosis
design-descriptive-test-names - Write test names that read like specifications
design-avoid-mystery-guest - Make all test data visible within the test itself
design-avoid-conditional-logic - No if/else or loops in test code
design-explicit-subject - Name subjects explicitly instead of using implicit subject
2. Test Data Management (CRITICAL)
data-factory-traits - Use composable factory traits instead of separate factories
data-minimal-attributes - Specify only attributes relevant to the test
data-build-over-create - Prefer build/build_stubbed over create when persistence isn't needed
data-avoid-fixture-coupling - Use factories instead of shared fixtures
data-transient-attributes - Use transient attributes for complex factory setup
data-sequence-unique-values - Use sequences for uniqueness-constrained fields
3. Model Testing (HIGH)
model-test-validations - Test validations with boundary cases, not just happy path
model-test-associations - Test associations explicitly including dependent behavior
model-test-scopes - Test scopes with matching and non-matching records
model-test-callbacks-sparingly - Test callback side effects, not callback existence
model-test-custom-methods - Test public methods with input/output pairs across scenarios
model-avoid-testing-framework - Don't test ActiveRecord or framework behavior
model-test-enums - Test enum transitions and generated scopes
4. Request & Controller Testing (HIGH)
request-over-controller-specs - Use request specs over deprecated controller specs
request-test-response-status - Assert HTTP status codes explicitly
request-test-authentication - Test authentication boundaries for every protected endpoint
request-test-authorization - Test authorization for each role
request-test-params-validation - Test parameter validation and edge cases
request-json-response-structure - Assert JSON response structure for API endpoints
5. System & Acceptance Testing (MEDIUM-HIGH)
system-page-objects - Encapsulate page interactions in page objects
system-use-accessible-selectors - Use accessible selectors over CSS/XPath
system-avoid-sleep - Never use sleep — rely on Capybara's built-in waiting
system-test-critical-paths - Reserve system tests for critical user journeys
system-database-state - Use truncation strategy for system test database cleanup
system-screenshot-on-failure - Capture screenshots on system test failure
6. Async & Background Job Testing (MEDIUM)
async-separate-enqueue-from-perform - Test enqueue and perform separately
async-use-fake-mode-default - Default to Sidekiq fake mode globally
async-test-job-perform - Test job perform method directly
async-test-mailer-delivery - Test mailer delivery with enqueued mail matcher
async-test-after-commit - Account for transaction-aware job enqueuing in Rails 7.2+
7. Test Performance & Reliability (MEDIUM)
perf-parallel-tests - Run tests in parallel across CPU cores
perf-database-strategy - Use transaction strategy for non-system tests
perf-profile-slow-specs - Profile and fix the slowest specs
perf-quarantine-flaky-tests - Quarantine flaky tests instead of retrying
perf-avoid-before-all-mutation - Never mutate state created in before(:all)
8. Test Organization & Maintenance (LOW-MEDIUM)
org-avoid-deep-nesting - Limit context nesting to 3 levels
org-shared-examples-sparingly - Use shared examples only for true behavioral contracts
org-custom-matchers - Extract custom matchers for repeated domain assertions
org-file-structure-mirrors-app - Mirror app directory structure in spec directory
How to Use
Read individual reference files for detailed explanations and code examples:
Section definitions - Category structure and impact levels
Rule template - Template for adding new rules
Reference Files
File
Description
references/_sections.md
Category definitions and ordering
assets/templates/_template.md
Template for new rules
metadata.json
Version and reference information
1---2name: rails-testing3description: Community Ruby on Rails Testing Best Practices4---5# Community Ruby on Rails Testing Best Practices67Comprehensive testing guide for Ruby on Rails applications, maintained by Community. Contains 46 rules across 8 categories, prioritized by impact to guide automated test generation, review, and refactoring.89## When to Apply1011Reference these guidelines when:12- Writing new RSpec specs for models, requests, system tests, or jobs13- Setting up FactoryBot factories with traits and sequences14- Writing Capybara system tests for user journeys15- Testing background jobs with Sidekiq or Active Job16- Reviewing test code for anti-patterns (mystery guests, flaky tests, slow specs)17- Optimizing test suite performance and CI pipeline speed18- Organizing test files, shared examples, and custom matchers1920## Rule Categories by Priority2122| Priority | Category | Impact | Prefix |23|----------|----------|--------|--------|24| 1 | Test Design & Structure | CRITICAL | `design-` |25| 2 | Test Data Management | CRITICAL | `data-` |26| 3 | Model Testing | HIGH | `model-` |27| 4 | Request & Controller Testing | HIGH | `request-` |28| 5 | System & Acceptance Testing | MEDIUM-HIGH | `system-` |29| 6 | Async & Background Job Testing | MEDIUM | `async-` |30| 7 | Test Performance & Reliability | MEDIUM | `perf-` |31| 8 | Test Organization & Maintenance | LOW-MEDIUM | `org-` |3233## Quick Reference3435### 1. Test Design & Structure (CRITICAL)3637- [`design-four-phase-test`](references/design-four-phase-test.md) - Use four-phase test structure (setup, exercise, verify, teardown)38- [`design-behavior-over-implementation`](references/design-behavior-over-implementation.md) - Test observable behavior, not internal implementation39- [`design-one-assertion-per-test`](references/design-one-assertion-per-test.md) - One logical expectation per test for precise failure diagnosis40- [`design-descriptive-test-names`](references/design-descriptive-test-names.md) - Write test names that read like specifications41- [`design-avoid-mystery-guest`](references/design-avoid-mystery-guest.md) - Make all test data visible within the test itself42- [`design-avoid-conditional-logic`](references/design-avoid-conditional-logic.md) - No if/else or loops in test code43- [`design-explicit-subject`](references/design-explicit-subject.md) - Name subjects explicitly instead of using implicit subject4445### 2. Test Data Management (CRITICAL)4647- [`data-factory-traits`](references/data-factory-traits.md) - Use composable factory traits instead of separate factories48- [`data-minimal-attributes`](references/data-minimal-attributes.md) - Specify only attributes relevant to the test49- [`data-build-over-create`](references/data-build-over-create.md) - Prefer build/build_stubbed over create when persistence isn't needed50- [`data-avoid-fixture-coupling`](references/data-avoid-fixture-coupling.md) - Use factories instead of shared fixtures51- [`data-transient-attributes`](references/data-transient-attributes.md) - Use transient attributes for complex factory setup52- [`data-sequence-unique-values`](references/data-sequence-unique-values.md) - Use sequences for uniqueness-constrained fields5354### 3. Model Testing (HIGH)5556- [`model-test-validations`](references/model-test-validations.md) - Test validations with boundary cases, not just happy path57- [`model-test-associations`](references/model-test-associations.md) - Test associations explicitly including dependent behavior58- [`model-test-scopes`](references/model-test-scopes.md) - Test scopes with matching and non-matching records59- [`model-test-callbacks-sparingly`](references/model-test-callbacks-sparingly.md) - Test callback side effects, not callback existence60- [`model-test-custom-methods`](references/model-test-custom-methods.md) - Test public methods with input/output pairs across scenarios61- [`model-avoid-testing-framework`](references/model-avoid-testing-framework.md) - Don't test ActiveRecord or framework behavior62- [`model-test-enums`](references/model-test-enums.md) - Test enum transitions and generated scopes6364### 4. Request & Controller Testing (HIGH)6566- [`request-over-controller-specs`](references/request-over-controller-specs.md) - Use request specs over deprecated controller specs67- [`request-test-response-status`](references/request-test-response-status.md) - Assert HTTP status codes explicitly68- [`request-test-authentication`](references/request-test-authentication.md) - Test authentication boundaries for every protected endpoint69- [`request-test-authorization`](references/request-test-authorization.md) - Test authorization for each role70- [`request-test-params-validation`](references/request-test-params-validation.md) - Test parameter validation and edge cases71- [`request-json-response-structure`](references/request-json-response-structure.md) - Assert JSON response structure for API endpoints7273### 5. System & Acceptance Testing (MEDIUM-HIGH)7475- [`system-page-objects`](references/system-page-objects.md) - Encapsulate page interactions in page objects76- [`system-use-accessible-selectors`](references/system-use-accessible-selectors.md) - Use accessible selectors over CSS/XPath77- [`system-avoid-sleep`](references/system-avoid-sleep.md) - Never use sleep — rely on Capybara's built-in waiting78- [`system-test-critical-paths`](references/system-test-critical-paths.md) - Reserve system tests for critical user journeys79- [`system-database-state`](references/system-database-state.md) - Use truncation strategy for system test database cleanup80- [`system-screenshot-on-failure`](references/system-screenshot-on-failure.md) - Capture screenshots on system test failure8182### 6. Async & Background Job Testing (MEDIUM)8384- [`async-separate-enqueue-from-perform`](references/async-separate-enqueue-from-perform.md) - Test enqueue and perform separately85- [`async-use-fake-mode-default`](references/async-use-fake-mode-default.md) - Default to Sidekiq fake mode globally86- [`async-test-job-perform`](references/async-test-job-perform.md) - Test job perform method directly87- [`async-test-mailer-delivery`](references/async-test-mailer-delivery.md) - Test mailer delivery with enqueued mail matcher88- [`async-test-after-commit`](references/async-test-after-commit.md) - Account for transaction-aware job enqueuing in Rails 7.2+8990### 7. Test Performance & Reliability (MEDIUM)9192- [`perf-parallel-tests`](references/perf-parallel-tests.md) - Run tests in parallel across CPU cores93- [`perf-database-strategy`](references/perf-database-strategy.md) - Use transaction strategy for non-system tests94- [`perf-profile-slow-specs`](references/perf-profile-slow-specs.md) - Profile and fix the slowest specs95- [`perf-quarantine-flaky-tests`](references/perf-quarantine-flaky-tests.md) - Quarantine flaky tests instead of retrying96- [`perf-avoid-before-all-mutation`](references/perf-avoid-before-all-mutation.md) - Never mutate state created in before(:all)9798### 8. Test Organization & Maintenance (LOW-MEDIUM)99100- [`org-avoid-deep-nesting`](references/org-avoid-deep-nesting.md) - Limit context nesting to 3 levels101- [`org-shared-examples-sparingly`](references/org-shared-examples-sparingly.md) - Use shared examples only for true behavioral contracts102- [`org-custom-matchers`](references/org-custom-matchers.md) - Extract custom matchers for repeated domain assertions103- [`org-file-structure-mirrors-app`](references/org-file-structure-mirrors-app.md) - Mirror app directory structure in spec directory104105## How to Use106107Read individual reference files for detailed explanations and code examples:108109- [Section definitions](references/_sections.md) - Category structure and impact levels110- [Rule template](assets/templates/_template.md) - Template for adding new rules111112## Reference Files113114| File | Description |115|------|-------------|116| [references/_sections.md](references/_sections.md) | Category definitions and ordering |117| [assets/templates/_template.md](assets/templates/_template.md) | Template for new rules |118| [metadata.json](metadata.json) | Version and reference information |
Run npx skillmds@latest add comeonoliver/rails-testing in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Community Ruby on Rails Testing Best Practices It is listed under Coding & Dev Tools on SkillMD.
This skill has not completed SkillMD's automated safety review yet. Independent scanners report: SkillSpector: PASS, Skill Scanner: PASS. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
ComeOnOliver (@comeonoliver) published this skill. Their other Agent Skills are listed on their SkillMD profile.