Testing with Minitest
Reviewed & published by Brayan K
Minitest is Ruby's built-in testing framework that lets you verify your code automatically with concise assertions, so you catch bugs before your users do.
Part of the free Ruby course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.
You'll write test classes and assertions, use setup, check for raised errors, and try the spec style.
What You'll Learn in This Lesson
- Writing a Minitest::Test with test_ methods
- require 'minitest/autorun' to run tests
- assert, assert_equal, assert_nil, assert_includes
- assert_raises for expected exceptions
- setup for fresh state before each test
- Spec style with describe/it, and Minitest vs RSpec
1️⃣ Your First Test
A Minitest test is a class that inherits from Minitest::Test. Every method whose name starts with test_ is a test. Inside, call assertions like assert_equal(expected, actual) or assert(condition). The line require 'minitest/autorun' makes the file run its tests automatically.
2️⃣ More Assertions, setup & assert_raises
setup runs before every test_ method, giving each test fresh, isolated state. Beyond assert_equal there's assert_nil, assert_includes, and assert_raises, which passes only if the block raises the expected exception.
require 'minitest/autorun'
class Calculator
def divide(a, b)
raise ArgumentError, "cannot divide by zero" if b.zero?
a / b
end
end
class CalculatorTest < Minitest::Test
def setup
# Runs before EVERY test_ method — fresh state each time.
@calc = Calculator.new
end
def test_divide
assert_equal 4, @calc.divide(8, 2)
end
def test_divide_by_zero_raises
# assert_raises checks that the block raises the given error.
assert_raises(ArgumentError) { @calc.divide(1, 0) }
end
def test_nil_and_includes
assert_nil [1, 2].find { |n| n > 9 }
assert_includes [1, 2, 3], 2
end
end3️⃣ Spec Style & Minitest vs RSpec
Minitest also offers a spec style that reads like a sentence: describe groups tests, it defines one, and expectations use _(value).must_equal expected. It's a lighter alternative to RSpec's expect(...).to DSL, with no extra gem to install.
require 'minitest/autorun'
# Spec style reads like a sentence — describe/it instead of test_ methods.
describe "String" do
it "knows its length" do
_("hello".length).must_equal 5
end
it "can upcase" do
_("ruby".upcase).must_equal "RUBY"
end
it "reverses" do
_("abc".reverse).must_equal "cba"
end
end
# Run it with: ruby test_spec.rbYour turn. Complete two assertions about strings so the suite passes. Fill in each ___.
require 'minitest/autorun'
# 🎯 YOUR TURN — replace each ___ then run with: ruby test_str.rb
class StringTest < Minitest::Test
def test_upcase
assert_equal "HELLO", "hello".___ # 👉 method that uppercases
end
def test_length
assert_equal ___, "ruby".length # 👉 how many letters in "ruby"?
end
end
# ✅ Expected summary line:
# 2 runs, 2 assertions, 0 failures, 0 errors, 0 skipsMini-Challenge: Test a Stack
Build a tiny Stack and write a Minitest suite for it with a setup, an equality assertion, and an assert_raises. This mirrors how you'd test a real class. Run with ruby test_stack.rb.
# 🎯 MINI-CHALLENGE: test a Stack class.
# Save as test_stack.rb and run with: ruby test_stack.rb
#
# 1. Define a small Stack with push, pop, and empty?.
# 2. Write a Minitest::Test with a setup that makes a fresh stack.
# 3. Test that a new stack is empty, that push then pop returns the
# item, and that popping an empty stack raises an error.
#
# ✅ Expected summary line:
# 3 runs, 4 assertions, 0 failures, 0 errors, 0 skips
# your code hereCommon Errors (and the fix)
- No tests run — ❌ Method names don't start with test_. ✅ Minitest only runs test_-prefixed methods.
- "uninitialized constant Minitest" — ❌ Missing the require. ✅ Add require 'minitest/autorun' at the top.
- Args backwards — ❌ assert_equal actual, expected. ✅ Order is assert_equal(expected, actual).
- assert_raises without a block — ❌ Passing a value instead of code. ✅ Give it a block: assert_raises(E) { ... }.
Pro Tips
- 💡 One behaviour per test: small focused tests give clearer failure messages.
- 💡 teardown too: pair setup with teardown for cleanup after each test.
- 💡 Floats: use assert_in_delta instead of assert_equal for floating-point results.
📋 Quick Reference — Minitest
| Concept | Ruby |
|---|---|
| Load + run | require 'minitest/autorun' |
| Test class | < Minitest::Test |
| A test | def test_thing |
| Equality | assert_equal exp, act |
| Raises | assert_raises(E) { } |
| Before each | def setup |
🎉 Lesson Complete!
- ✅ A test is a test_ method in a Minitest::Test class
- ✅ require 'minitest/autorun' runs everything
- ✅ assert, assert_equal, assert_raises
- ✅ setup gives each test fresh state
- ✅ Spec style (describe/it) is a lighter alternative to RSpec
Practice quiz
How is Minitest distributed?
- a paid gem
- part of Rails only
- built into Ruby, no install needed
- a separate download
Answer: built into Ruby, no install needed. Minitest ships with Ruby itself.
What does require 'minitest/autorun' do?
- registers an at_exit hook that runs the tests automatically
- installs Minitest
- imports assertions only
- starts a web server
Answer: registers an at_exit hook that runs the tests automatically. autorun runs all defined tests when the file finishes loading.
A classic-style test class inherits from:
- Minitest::Spec
- Test::Unit
- RSpec::Test
- Minitest::Test
Answer: Minitest::Test. xUnit-style tests subclass Minitest::Test.
Which method names are run as tests in a Minitest::Test class?
- any method
- methods starting with test_
- methods ending in _test
- methods named check
Answer: methods starting with test_. Only methods whose names start with test_ are run.
What is the correct argument order for assert_equal?
- assert_equal expected, actual
- assert_equal actual, expected
- order does not matter
- assert_equal value only
Answer: assert_equal expected, actual. assert_equal takes expected first, then actual.
When does plain assert(value) pass?
- when value is nil
- only when value is true
- when value is truthy (not nil or false)
- when value is zero
Answer: when value is truthy (not nil or false). assert passes for any truthy value.
Which assertion checks that a block raises an error?
- assert_error
- assert_raises
- assert_throws
- assert_fails
Answer: assert_raises. assert_raises(Error) { ... } passes when the block raises that error.
What does the setup method do?
- runs once before all tests
- runs after each test
- configures the seed
- runs before every test_ method for fresh state
Answer: runs before every test_ method for fresh state. setup runs before each test, giving isolated state.
In Minitest spec style, which pair defines a test group and a test?
- context / specify
- describe / it
- suite / case
- group / test
Answer: describe / it. Spec style uses describe to group and it to define a test.
Compared to RSpec, Minitest is generally:
- larger with a big matcher DSL
- browser-based
- small, built-in, and dependency-free
- only for Rails
Answer: small, built-in, and dependency-free. Minitest favours simplicity and ships with Ruby; RSpec is a larger external gem.
Continue this course
- Previous: JSON & YAML
- Next: Checkpoint: OOP & Stdlib — Combine inheritance, custom errors and JSON in a build — then a quiz
- Quick reference: Ruby cheat sheet
Frequently asked questions
What is Minitest and why is it popular?
Minitest is Ruby's lightweight testing framework, and it ships with Ruby itself — no gem to install. It's tiny, fast, and supports two styles: a classic xUnit style (classes that subclass Minitest::Test with test_ methods and assertions) and a spec style (describe/it blocks). Because it's built in and dependency-free, it's the default for many libraries and a great place to learn testing.
How does require 'minitest/autorun' work?
Adding require 'minitest/autorun' at the top of a test file registers an at_exit hook that runs all defined tests when the file finishes loading. That's why you can just execute ruby test_file.rb and see results — there's no separate test runner command needed. Each test_ method (or it block) is discovered and run automatically, in a randomized order controlled by the seed.
What's the difference between assert and assert_equal?
assert(value) passes when value is truthy (anything but nil or false) — use it for boolean conditions. assert_equal(expected, actual) passes when the two are equal, and prints a helpful diff when they aren't, so it's better for value comparisons. There are many specialized assertions too: assert_nil, assert_includes, assert_raises (for exceptions), and assert_in_delta for floats. Use the most specific one for the clearest failure messages.
How is Minitest different from RSpec?
Both are popular Ruby test frameworks. Minitest is small, built into Ruby, and uses plain assertions (or a light spec layer). RSpec is a larger external gem with an expressive expect(...).to matcher DSL, rich built-in matchers, and lots of conventions. Minitest favours simplicity and speed; RSpec favours readability and a big ecosystem. Many projects are happy with Minitest's spec style, which gives describe/it without the extra dependency.