minitest-coder
Write Minitest tests for Ruby and Rails applications. Use when creating test files, writing test cases, or testing new features. Not for RSpec — use rspec-coder instead. Covers both traditional and spec styles, fixtures, mocking, and Rails integration testing patterns.
What this skill does
# Minitest 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 | `test "description"` |
| Spec | Complex scenarios with contexts | `describe`/`it` with `let`/`subject` |
### Traditional Style
```ruby
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
```ruby
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
- `test/services/` - Service object tests
- `test/integration/` - Full-stack tests
- `test/mailers/` - Mailer tests
- `test/jobs/` - Background job tests
- `test/fixtures/` - Test data
- `test/test_helper.rb` - Configuration
### Naming Conventions
- Mirror app structure: `app/models/user.rb` → `test/models/user_test.rb`
- Use fully qualified namespace: `class Users::ProfileServiceTest`
- **Don't add** `require 'test_helper'` (auto-imported)
## Spec Style Patterns
See [references/spec-patterns.md](references/spec-patterns.md) for detailed examples.
| Pattern | Use Case |
|---------|----------|
| `subject { ... }` | Method under test |
| `let(:name) { ... }` | Lazy-evaluated data |
| `describe "context"` | Group related tests (max 3 levels) |
| `before { ... }` | Complex setup |
```ruby
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
```yaml
# test/fixtures/users.yml
alice:
name: Alice Smith
email: [email protected]
created_at: <%= 2.days.ago %>
```
```ruby
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 [references/spec-patterns.md](references/spec-patterns.md) for detailed examples.
| Method | Purpose |
|--------|---------|
| `Object.stub :method, value` | Stub return value |
| `Minitest::Mock.new` | Verify method calls |
```ruby
test "processes payment" do
PaymentGateway.stub :charge, true do
processor = OrderProcessor.new(order)
assert processor.process
end
end
```
## Assertions Quick Reference
### Basic Assertions
```ruby
# 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
```ruby
# 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
```ruby
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**:
```ruby
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
```ruby
class UserTest < ActiveSupport::TestCase
# Validations
test "validates presence of name" do
user = User.new(email: "[email protected]")
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 [references/advanced-patterns.md](references/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 [references/anti-patterns.md](references/anti-patterns.md) for detailed examples.
| Anti-Pattern | Why Bad |
|--------------|---------|
| `require 'test_helper'` | Auto-imported |
| >3 nesting levels | Unreadable output |
| `@ivars` instead of `let` | State leakage |
| Missing `subject` | Repetitive code |
| `assert x.include?(y)` | Use `assert_includes` |
| 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 `let` for shared data
- [ ] Using `subject` for method under test
**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.
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.