Minitest Basics — Your First Ruby Tests

· 3 min read · Updated March 16, 2026 · beginner
minitest testing tdd ruby beginner

Minitest is Ruby’s built-in testing framework. Unlike RSpec’s BDD style, Minitest stays close to Ruby’s core, making it lighter and faster. If you’re new to testing or want a minimal setup, Minitest is perfect.

Why Minitest?

Minitest ships with Ruby—no extra installation needed. It provides everything you need: unit tests, spec-style tests, mocking, and benchmarking. Many gems use Minitest for their own test suites because it’s fast and integrates seamlessly.

Your First Minitest

Create a test file and write your first test:

# test/calculator_test.rb
require 'minitest/autorun'

class CalculatorTest < Minitest::Test
  def test_add_returns_sum_of_two_numbers
    calculator = Calculator.new
    assert_equal 5, calculator.add(2, 3)
  end
end

Run it with ruby test/calculator_test.rb. Minitest automatically runs any method starting with test_.

Assertions

Minitest provides plain assertions that read like method calls:

def test_assertions
  # Equality
  assert_equal expected, actual
  
  # Truthiness
  assert true
  refute false
  
  # Nil checks
  assert_nil nil
  refute_nil "hello"
  
  # Type checks
  assert_instance_of String, "hello"
  assert_kind_of Numeric, 42
  
  # Collection checks
  assert_includes [1, 2, 3], 2
  assert_respond_to "hello", :upcase
end

Expectations (Spec Style)

If you prefer RSpec’s expect syntax, enable expectations:

require 'minitest/autorun'
require 'minitest/spec'

describe Calculator do
  it 'adds two numbers' do
    calculator = Calculator.new
    _(calculator.add(2, 3)).must_equal 5
  end
  
  it 'raises on invalid input' do
    calculator = Calculator.new
    _(-> { calculator.add("a", "b") }).must_raise TypeError
  end
end

The _() wrapper converts values into Minitest::Spec expectations.

Setup and Teardown

Use setup and teardown for common test preparation:

class UserTest < Minitest::Test
  def setup
    @user = User.new(name: "Alice", email: "alice@example.com")
  end
  
  def teardown
    User.delete_all
  end
  
  def test_user_has_name
    assert_equal "Alice", @user.name
  end
end

Test Fixtures

For more complex setup, define fixtures:

class OrderTest < Minitest::Test
  fixtures :users, :products
  
  def test_order_belongs_to_user
    order = Order.create(user: users(:alice), product: products(:book))
    assert_equal users(:alice), order.user
  end
end

Mocking and Stubbing

Minitest includes mocking support:

def test_charges_payment_gateway
  payment_gateway = Minitest::Mock.new
  payment_gateway.expect :charge, true, [100]
  
  processor = OrderProcessor.new(payment_gateway)
  processor.charge_order(order_with_total(100))
  
  payment_gateway.verify
end

Stub methods with stub:

def test_uses_cached_data
  Cache.stub :get, "cached value" do
    result = DataFetcher.fetch(:users)
    assert_equal "cached value", result
  end
end

Test Organization

Group related tests in classes. Each class is a test suite:

# test/models/
require 'minitest/autorun'

class UserTest < Minitest::Test
  # Tests for User model
end

class ProductTest < Minitest::Test
  # Tests for Product model
end

Run specific test classes:

ruby test/user_test.rb
ruby test/models/product_test.rb

Running Tests

Minitest runs tests automatically when you require ‘minitest/autorun’. Customize output with flags:

# Verbose output
ruby test/test.rb -v

# Run specific test method
ruby test/test.rb -n test_add_returns_sum

# Run tests matching a pattern
ruby test/test.rb -n /test_add/

Continuous Testing

Speed up your development with continuous testing. The minitest-reporters gem gives you color-coded output and progress indicators:

# Gemfile
group :test do
  gem 'minitest-reporters'
end

Configure it in your test helper:

require 'minitest/reporters'
Minitest::Reporters.use!

Now you’ll see green dots for passing tests and red F’s for failures, plus execution time for each test.

Testing Strategies

Good tests follow the FIRST principles: Fast, Independent, Repeatable, Self-validating, Timely. Minitest helps you achieve these by keeping tests simple and fast.

Write tests before code (TDD) to clarify what you’re building. Start with a failing test, then write the minimum code to pass it. This approach often reveals design issues early.

Minitest vs RSpec

Choose Minitest when:

  • You want minimal dependencies
  • Speed matters for large test suites
  • You prefer assertion-style tests
  • You’re testing simple scripts or gems

Choose RSpec when:

  • You prefer behavior-driven syntax
  • Your team already knows RSpec
  • You need advanced mocking features
  • Readable specs are more important than speed

Summary

Minitest gives you a lightweight, fast testing foundation. Its assertion style is explicit and easy to understand. Start with Minitest to build testing habits, then explore RSpec if you need more expressive syntax later.

See Also