Use when writing Rails tests - enforces fixtures-only, integration-style controller tests, Current.session setup, simple naming, and Minitest syntax (NO FactoryBot, NO RSpec)
From vanilla-railsnpx claudepluginhub zemptime/zemptime-marketplace --plugin vanilla-railsThis skill uses the workspace's default tool permissions.
Designs and optimizes AI agent action spaces, tool definitions, observation formats, error recovery, and context for higher task completion rates.
Enables AI agents to execute x402 payments with per-task budgets, spending controls, and non-custodial wallets via MCP tools. Use when agents pay for APIs, services, or other agents.
Compares coding agents like Claude Code and Aider on custom YAML-defined codebase tasks using git worktrees, measuring pass rate, cost, time, and consistency.
NO FACTORYBOT. NO RSPEC. NO DATA CREATION IN TESTS.
| Never use | Use instead |
|---|---|
create(:model), build(:model), FactoryBot | Fixtures: cards(:logo) |
let, describe, it, context, subject | test "name", setup do |
expect(...).to, .should | assert, assert_equal, assert_not |
refute | assert_not |
ActionController::TestCase | ActionDispatch::IntegrationTest |
before_each | setup do |
RSpec mocks (allow, expect) | Mocha (.stubs) |
If any banned pattern appears, delete it and rewrite.
test "close card" do
cards(:logo).close
assert cards(:logo).closed?
end
Fixture missing? Add it to the fixtures file. Never create data in tests.
class Cards::ClosuresControllerTest < ActionDispatch::IntegrationTest
setup do
sign_in_as :kevin
end
test "create" do
post card_closure_path(cards(:logo)), as: :turbo_stream
assert_response :success
end
end
Always set Current.session in setup, even if you think it's not needed:
class Card::CloseableTest < ActiveSupport::TestCase
setup do
Current.session = sessions(:david)
end
test "close records user" do
cards(:logo).close(user: users(:kevin))
assert_equal users(:kevin), cards(:logo).closed_by
end
end
State changes: assert_difference with lambda syntax:
assert_difference -> { Card.count }, +1 do
post board_cards_path(boards(:writebook))
end
assert_difference({
-> { cards(:logo).events.count } => +1,
-> { Event.count } => +1
}) do
cards(:logo).close(user: users(:kevin))
end
Boolean toggles: assert_changes:
assert_changes -> { cards(:logo).reload.closed? }, from: false, to: true do
post card_closure_path(cards(:logo)), as: :turbo_stream
end
Exceptions: assert_raises:
assert_raises ActiveRecord::RecordNotFound do
Card.find("nonexistent")
end
Concise. File + method name provide context.
# Good
test "create"
test "close records user"
# Bad
test "should create a new card when given valid parameters"
Same rules — fixtures, no data creation:
class SmokeTest < ApplicationSystemTestCase
test "create a card" do
sign_in_as(users(:david))
visit board_url(boards(:writebook))
click_on "Add a card"
end
end
Use mocha for stubs, webmock for HTTP:
TestMailer.stubs(:goes_boom).raises(Net::SMTPSyntaxError)
stub_request(:post, webhook.url).to_return(status: 200)
| Red flag | Action |
|---|---|
create(:model) or FactoryBot | Delete. Use fixtures. |
describe, it, context | Delete. Use test. |
expect(...).to | Delete. Use assert. |
Model test without Current.session | Add Current.session = sessions(:fixture) |
| Test names starting with "should" | Shorten. |
| Data creation in tests | Add fixture instead. |