Minitest
Minitest ships in Ruby’s standard library and is Rails’ default testing framework. It supports two styles — classic Test::Unit-style assertions, and a spec-style DSL — that can be mixed freely.
Assertion style
require "minitest/autorun"
class PostTest < Minitest::Test
def setup
@post = Post.new(title: "Hello")
end
def test_title_is_present
assert @post.valid?
assert_equal "Hello", @post.title
end
def teardown
# runs after every test
end
end
Spec style
describe Post do
before { @post = Post.new(title: "Hello") }
it "is valid with a title" do
_(@post).must_be :valid?
end
end
Spec style is just sugar over the same assertion methods (must_equal → assert_equal, etc.) — pick one per project and stay consistent.
Common assertions
| Assertion | Checks |
|---|---|
assert x |
x is truthy |
refute x |
x is falsy |
assert_equal exp, act |
exp == act |
assert_nil x |
x.nil? |
assert_includes coll, x |
coll includes x |
assert_raises(ErrClass) { ... } |
block raises ErrClass |
assert_instance_of Klass, x |
x.instance_of?(Klass) |
assert_respond_to x, :foo |
x responds to :foo |
assert_in_delta exp, act, delta |
numeric closeness |
Every assert_* has a refute_* counterpart.
Rails integration
class PostTest < ActiveSupport::TestCase
test "requires a title" do
post = Post.new
assert_not post.valid?
end
end
ActiveSupport::TestCasegives you thetest "description" do ... endmacro (defines a method under the hood) and loads fixtures automatically.- Fixtures live in
test/fixtures/*.yml, referenced asposts(:one)in tests. - Controller/request tests:
ActionDispatch::IntegrationTest, withget,post,assert_response :success,assert_redirected_to. - System tests (real browser via Capybara):
ApplicationSystemTestCase.
Mocking & stubbing
mailer = Minitest::Mock.new
mailer.expect :deliver, true
UserMailer.stub :welcome, mailer do
# code that calls UserMailer.welcome
end
mailer.verify
obj.stub(:method, return_value) { ... }— temporarily replaces a method for the block’s duration.Minitest::Mock#expect(name, retval, args = [])then.verifyto assert it was called as expected.- Prefer real objects and fixtures where practical; reach for mocks mainly at slow/external boundaries (network calls, mailers, third-party APIs).
Running tests
rails test # whole suite
rails test test/models/post_test.rb
rails test test/models/post_test.rb:12 # single test by line number
rails test:models / :controllers / :system
ruby -Itest test/models/post_test.rb # plain Ruby project, no Rails
- Parallel test execution is on by default in Rails (
parallelize(workers: :number_of_processors)intest_helper.rb). bin/rails test --seed 1234reproduces a specific run order (Minitest randomizes by default).
Assertions vs expectations
Minitest deliberately keeps the API small compared to RSpec’s large matcher library. If you want richer custom matchers, minitest/spec plus a handful of custom Minitest::Assertions methods usually covers it without pulling in a bigger DSL.