Claude-skill-registry-data minitest-coder
This skill guides writing comprehensive Minitest tests for Ruby and Rails applications. Use when creating test files, writing test cases, or testing new features. Covers both traditional and spec styles, fixtures, mocking, and Rails integration testing patterns.
git clone https://github.com/majiayu000/claude-skill-registry-data
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry-data "$T" && mkdir -p ~/.claude/skills && cp -r "$T/data/minitest-coder" ~/.claude/skills/majiayu000-claude-skill-registry-data-minitest-coder && rm -rf "$T"
data/minitest-coder/SKILL.mdMinitest Coder
Core Philosophy
- AAA Pattern: Arrange-Act-Assert structure for clarity
- Behavior over Implementation: Test what code does, not how
- Isolation: Tests should be independent
- Descriptive Names: Clear test descriptions
- Coverage: Test happy paths AND edge cases
- Fast Tests: Minimize database operations
- Fixtures: Use fixtures for test data
Minitest Styles
| Style | Best For | Syntax |
|---|---|---|
| Traditional | Simple unit tests | |
| Spec | Complex scenarios with contexts | / with / |
Traditional Style
class UserTest < ActiveSupport::TestCase test "validates presence of name" do user = User.new assert_not user.valid? assert_includes user.errors[:name], "can't be blank" end end
Spec Style
class UserTest < ActiveSupport::TestCase describe "#full_name" do subject { user.full_name } let(:user) { User.new(first_name: "Buffy", last_name:) } describe "with last name" do let(:last_name) { "Summers" } it "returns full name" do assert_equal "Buffy Summers", subject end end end end
Test Organization
File Structure
test/ ├── models/ # Model unit tests ├── services/ # Service object tests ├── integration/ # Full-stack tests ├── mailers/ # Mailer tests ├── jobs/ # Background job tests ├── fixtures/ # Test data └── test_helper.rb # Configuration
Naming Conventions
- Mirror app structure:
→app/models/user.rbtest/models/user_test.rb - Use fully qualified namespace:
class Users::ProfileServiceTest - Don't add
(auto-imported)require 'test_helper'
Spec Style Patterns
See resources/spec-patterns.md for detailed examples.
| Pattern | Use Case |
|---|---|
| Method under test |
| Lazy-evaluated data |
| Group related tests (max 3 levels) |
| Complex setup |
describe "#process" do subject { processor.process } let(:processor) { OrderProcessor.new(order) } let(:order) { orders(:paid_order) } it "succeeds" do assert subject.success? end end
Fixtures
# test/fixtures/users.yml alice: name: Alice Smith email: alice@example.com created_at: <%= 2.days.ago %>
class UserTest < ActiveSupport::TestCase fixtures :users test "validates uniqueness" do duplicate = User.new(email: users(:alice).email) assert_not duplicate.valid? end end
Mocking and Stubbing
See resources/spec-patterns.md for detailed examples.
| Method | Purpose |
|---|---|
| Stub return value |
| Verify method calls |
test "processes payment" do PaymentGateway.stub :charge, true do processor = OrderProcessor.new(order) assert processor.process end end
Assertions Quick Reference
Basic Assertions
# Boolean assert user.valid? assert_not user.admin? # Equality assert_equal "Alice", user.name assert_nil user.deleted_at # Collections assert_includes users, admin_user assert_empty order.items # Exceptions assert_raises ActiveRecord::RecordInvalid do user.save! end
Rails Assertions
# Changes assert_changes -> { user.reload.status }, to: "active" do user.activate! end assert_difference "User.count", 1 do User.create(name: "Charlie") end # Responses assert_response :success assert_redirected_to user_path(user)
AAA Pattern
test "processes refund" do # Arrange order = orders(:completed_order) original_balance = order.user.account_balance # Act result = order.process_refund # Assert assert result.success? assert_equal "refunded", order.reload.status end
Spec style with subject:
describe "#process_refund" do subject { order.process_refund } let(:order) { orders(:completed_order) } it "updates status" do subject assert_equal "refunded", order.reload.status end it "credits user" do assert_changes -> { order.user.reload.account_balance }, by: order.total do subject end end end
Test Coverage Standards
| Type | Test For |
|---|---|
| Models | Validations, associations, scopes, callbacks, methods |
| Services | Happy path, sad path, edge cases, external integrations |
| Controllers | Status codes, redirects, parameter handling |
| Jobs | Execution, retry logic, error handling |
Coverage Example
class UserTest < ActiveSupport::TestCase # Validations test "validates presence of name" do user = User.new(email: "test@example.com") assert_not user.valid? assert_includes user.errors[:name], "can't be blank" end # Methods describe "#full_name" do subject { user.full_name } let(:user) { User.new(first_name: "Alice", last_name: "Smith") } it "returns full name" do assert_equal "Alice Smith", subject end describe "without last name" do let(:user) { User.new(first_name: "Alice") } it "returns first name only" do assert_equal "Alice", subject end end end end
Advanced Patterns
See resources/advanced-patterns.md for production-tested patterns from 37signals.
| Pattern | Problem Solved |
|---|---|
| Current.account fixtures | Multi-tenant URL isolation |
| Assertion-validating helpers | Early failure with clear messages |
| Deterministic UUIDs | Predictable fixture ordering |
| VCR timestamp filtering | Reusable API cassettes |
| Thread-based concurrency | Race condition detection |
| Adapter-aware helpers | SQLite/MySQL compatibility |
Anti-Patterns
See resources/anti-patterns.md for detailed examples.
| Anti-Pattern | Why Bad |
|---|---|
| Auto-imported |
| >3 nesting levels | Unreadable output |
instead of | State leakage |
Missing | Repetitive code |
| Use |
| Testing private methods | Implementation coupling |
| Not using fixtures | Slow tests |
Best Practices Checklist
Organization:
- Files mirror app structure
- NOT adding
require 'test_helper' - Using fully qualified namespace
Style Choice:
- Traditional for simple tests
- Spec for complex contexts
- Max 3 nesting levels
Test Data:
- Using fixtures (not factories)
- Using
for shared datalet - Using
for method under testsubject
Assertions:
- Correct assertion methods
- Rails helpers (
,assert_changes
)assert_difference - Testing behavior, not implementation
Coverage:
- Happy path tested
- Sad path tested
- Edge cases covered
When to Choose Style
Traditional: Simple validations, straightforward tests, no shared setup
Spec: Multiple contexts, lazy evaluation needed, nested scenarios, reusable subject
Can mix both in the same file if it improves clarity.