rspec-unit-testing-standards
Defines mandatory and recommended rules for RSpec structure, naming, and stubbing patterns.
Install
mkdir -p .claude/skills/rspec-unit-testing-standards && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/10446" && unzip -o skill.zip -d .claude/skills/rspec-unit-testing-standards && rm skill.zipInstalls to .claude/skills/rspec-unit-testing-standards
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Defines RSpec unit testing rules for this project covering structure, naming, setup patterns, stubbing, doubles, coverage, and test reliability. Use when writing, reviewing, or auditing RSpec specs under spec/unit/.Key capabilities
- →Validate RSpec unit tests
- →Audit test suite quality
- →Enforce RSpec structure rules
- →Check branch coverage
- →Verify test determinism
How it works
The skill enforces RSpec standards by checking spec file structure, naming conventions, and setup patterns against defined MUST/SHOULD rules.
Inputs & outputs
When to use rspec-unit-testing-standards
- →Reviewing RSpec test code
- →Setting up new unit tests
- →Auditing test suite quality
About this skill
RSpec Unit Testing Standards
These rules govern the structure, organization, and quality of all RSpec unit tests in this project. Apply them when writing new tests, reviewing existing ones, or auditing test quality.
Priority Levels
Use RFC-style priority words to reduce ambiguity for AI behavior:
- MUST: mandatory; do not violate without a documented exception
- SHOULD: preferred default; may be overridden when a clearer test requires it
Contents
- How to use this skill
- Related skills
- Structure
- Rule 1 (MUST): One top-level
RSpec.describeblock per class - Rule 2 (MUST): One
describeblock per public method - Rule 3 (SHOULD): Add
# frozen_string_literal: trueat the top of every spec file - Rule 4 (MUST): Spec file location must mirror source file location
- Rule 5 (MUST):
require 'spec_helper'and only the file(s) under test - Rule 6 (MUST): Test only through the public interface
- Rule 1 (MUST): One top-level
- Naming and Organization
- Setup and Subject
- Rule 11 (SHOULD): Use a named
subjectat the top of eachdescribe #methodblock - Rule 12 (SHOULD): Immediately follow
subjectwithletdefaults - Rule 13 (SHOULD): Define
let(:described_instance)at the top level when multipledescribeblocks share the same instance - Rule 14 (SHOULD): Prefer
subjectto represent the method call result - Rule 15 (SHOULD): Do not use
subjectwhen testing side effects - Rule 16 (MUST): Use
let/let!for inputs and shared setup; usebeforeonly for side effects - Rule 17 (SHOULD): Keep test setup local; extract only for substantial cross-file reuse
- Rule 11 (SHOULD): Use a named
- Doubles and Stubbing
- Coverage
- Test Reliability
- Verification
- Output
How to use this skill
These rules apply to all RSpec unit specs under spec/unit/. Extend this baseline
with domain-specific rules from related skills as needed.
Adoption and enforcement notes:
- Apply these rules as hard requirements for new and modified unit specs.
- Legacy specs may violate some rules; treat those as incremental cleanup work.
- Branch and line coverage are both reported by SimpleCov in this repository.
minimum_coverage: { line: 100, branch: 100 }is configured and enforced: a fullrake spec:unitrun fails when either threshold is missed, and CI fails the pull request with it. Rule 21 is a build gate, not just a review check. See the Test coverage policy inCONTRIBUTING.mdfor the full policy.- Focused runs (
SPEC=<glob> rake spec:unit, orrspec <file>) report coverage but do not fail on it, since they load all oflib/while exercising only a slice.
Related skills
- Command Test Conventions — additional conventions
for
Git::Commands::*unit and integration specs, built on top of these rules - Development Workflow — TDD process that governs when and how tests are written
- PR Readiness Review — final quality gate that verifies test compliance before opening a pull request
- Pull Request Review — PR review process that checks test quality against these standards
Structure
Rule 1 (MUST): One top-level RSpec.describe block per class
Use the class constant directly:
RSpec.describe Git::CommandLine::Capturing do
Never use a string in place of the constant, even for backward-compat aliases:
# Bad — string describe; described_class is unavailable, coverage tooling may not
# map the spec to the source file, and typos go undetected at load time.
RSpec.describe 'Git::CommandLineResult' do
If the constant is a backward-compat alias (e.g. Git::CommandLineResult = Git::CommandLine::Result), use the alias constant itself as the describe argument —
the alias is a real Ruby constant and loads without issue. The test content should
verify that the alias points to the correct target using object identity (be),
which would not be caught implicitly by a NameError on the canonical constant:
RSpec.describe Git::CommandLineResult do
it 'is a backward-compatible alias for Git::CommandLine::Result' do
expect(described_class).to be(Git::CommandLine::Result)
end
end
Do not test #initialize or other behavior here — that is already covered by the spec for the canonical class.
Rule 2 (MUST): One describe block per public method
Use #method_name for instance methods and .method_name for class methods.
Include #initialize:
describe '#call' do ...
describe '.build' do ...
describe '#initialize' do ...
Inherited #initialize in concrete subclasses (SHOULD): If a class is
directly instantiated by callers but does not override #initialize, its spec
SHOULD still include a describe '#initialize' block using the minimal
have_attributes form (see Rule 13). This serves two purposes:
- The spec is self-contained documentation of the constructor signature — a reader does not need to consult the ancestor's spec to know what arguments the class accepts or what attributes it exposes.
- It guards against an accidental
def initializeoverride in the subclass that silently drops or misroutes an argument, which the ancestor's spec would not catch.
Omit the inherited #initialize block only for abstract or internal classes that
callers never instantiate directly — those are sufficiently covered by the
ancestor's spec alone.
Rule 3 (SHOULD): Add # frozen_string_literal: true at the top of every spec file
Matches project-wide convention and catches accidental string mutation.
Rule 4 (MUST): Spec file location must mirror source file location
lib/git/foo/bar.rb maps to spec/unit/git/foo/bar_spec.rb. Deviating from this
makes specs hard to find and breaks coverage mapping.
Rule 5 (MUST): require 'spec_helper' and only the file(s) under test
Every unit spec MUST start with require 'spec_helper', then require only the
Ruby file(s) it directly tests. Avoid requiring unrelated libraries or classes —
doing so creates false coupling where a rename or move breaks specs that don't even
test that class.
Rule 6 (MUST): Test only through the public interface
Never call private methods directly in tests. If private logic is hard to reach through the public interface, stop and propose one of these remedies to the user:
- Extract a class — move the logic to a new class with its own public interface.
- Make the method public — promote it if it is genuinely part of the contract.
- Redesign the public API — split the public method into smaller public steps.
Never use send, instance_variable_get, or __send__ to reach private state.
Naming and Organization
Ru
Content truncated.
When not to use it
- →Integration or E2E testing
- →Legacy spec cleanup without plan
Prerequisites
Limitations
- →Requires manual verification of MUST rules
- →Legacy specs may require incremental cleanup
How it compares
Unlike generic linting, this skill enforces project-specific RSpec architectural rules like described_class usage and branch coverage thresholds.
Compared to similar skills
rspec-unit-testing-standards side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| rspec-unit-testing-standards (this skill) | 0 | 3mo | Review | Intermediate |
| ruby-coder | 5 | 5mo | No flags | Intermediate |
| rails-testing | 1 | 8mo | No flags | Beginner |
| ruby-pro | 1 | 4mo | No flags | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by ruby-git
View all by ruby-git →You might also like
ruby-coder
majesticlabs-dev
This skill guides writing of new Ruby code following modern Ruby 3.x syntax, Sandi Metz's 4 Rules for Developers, and idiomatic Ruby best practices. Use when creating new Ruby files, writing Ruby methods, or refactoring Ruby code to ensure adherence to clarity, simplicity, and maintainability standards.
rails-testing
etewiah
Help with Rails testing including unit tests, integration tests, fixtures, and debugging test failures. Use when working on tests or debugging test issues.
ruby-pro
sickn33
Write idiomatic Ruby code with metaprogramming, Rails patterns, and performance optimization. Specializes in Ruby on Rails, gem development, and testing frameworks. Use PROACTIVELY for Ruby refactoring, optimization, or complex Ruby features.
skill-rails-upgrade
sickn33
Analyze Rails apps and provide upgrade assessments
lint
i3ringit
Use this agent when you need to run linting and code quality checks on Ruby and ERB files. Run before pushing to origin.
editor
betagouv
when generating content for ruby or slim files, follow the style and conventions of the existing codebase. Use the existing code as a guide for formatting, naming, and structure. When asked to write new code, prefer to reuse patterns and styles already present in the codebase.