Returning to MiniTest
Please note that all opinions are that of the author.
Last Updated On: 2025-10-13 07:27:39 -0400
A bunch of years ago, I took the heretical positions of:
- Returning to MiniTest from RSpec
- Rewriting an entire test suite from RSpec to MiniTest
- Using Factories NOT Fixtures
And, yet, I’ve never written about this. So I guess it is time.
Why MiniTest
One reason and one reason only: speed. MiniTest is faster than RSpec. And, no, I haven’t benchmarked it; I can’t give you numbers. What I can tell you is that even though MiniTest is slower to write, the execution time is faster and even in a world of CI systems, local test performance matters.
An Example MiniTest
The biggest thing I miss from RSpec are describe / context blocks. This is particularly true with respect to multiple login scenarios for controller tests (NOT logged in, Logged in with wrong user, Logged in correctly). Here’s a sample test for our Domains controller:
require "test_helper"
class DomainsControllerTest < ActionDispatch::IntegrationTest
setup do
@domain = FactoryBot.create(:domain)
@user_with_access = FactoryBot.create(:user)
@user_without_access = FactoryBot.create(:user)
role = FactoryBot.create(:role, name: 'admin')
user_role = FactoryBot.create(:user_role, user: @user_with_access, role: role)
end
test "should get index and then redirect if not logged in" do
get domains_url
assert_response :redirect
end
test "should get index and then redirect if not logged in as right user " do
sign_in @user_without_access
get domains_url
assert_response :redirect
end
test "should get index if logged in" do
sign_in @user_with_access
get domains_url
assert_response :success
end
test "should get new and then redirect if not logged in" do
get new_domain_url
assert_response :redirect
end
test "should get new and then redirect if not logged in as right user " do
sign_in @user_without_access
get new_domain_url
assert_response :redirect
end
test "should get new if logged in" do
sign_in @user_with_access
get new_domain_url
assert_response :success
end
test "should NOT create domain if not logged in" do
assert_no_difference("Domain.count") do
post domains_url, params: { domain: { name: @domain.name } }
end
assert_response :redirect
end
test "should NOT create domain if logged in as wrong user" do
sign_in @user_without_access
assert_no_difference("Domain.count") do
post domains_url, params: { domain: { name: @domain.name } }
end
assert_response :redirect
end
test "should create domain if logged in" do
sign_in @user_with_access
assert_difference("Domain.count", 1) do
post domains_url, params: { domain: { name: "foo.com" } }
end
assert_redirected_to domain_url(Domain.last)
end
test "should NOT show domain if NOT logged in" do
get domain_url(@domain)
assert_response :redirect
end
test "should NOT show domain if NOT logged in as right user " do
sign_in @user_without_access
get domain_url(@domain)
assert_response :redirect
end
test "should show domain if logged in" do
sign_in @user_with_access
get domain_url(@domain)
assert_response :success
end
test "should get edit if NOT logged in" do
get edit_domain_url(@domain)
assert_response :redirect
end
test "should NOT get edit if NOT logged in as right user " do
sign_in @user_without_access
get edit_domain_url(@domain)
assert_response :redirect
end
test "should get edit if logged in" do
sign_in @user_with_access
get edit_domain_url(@domain)
assert_response :success
end
test "should NOT update domain if not logged in" do
patch domain_url(@domain), params: { domain: { name: @domain.name } }
assert_response :redirect
end
test "should NOT update domain if not logged in as right user" do
sign_in @user_without_access
patch domain_url(@domain), params: { domain: { name: @domain.name } }
assert_response :redirect
end
test "should update domain if logged in" do
sign_in @user_with_access
patch domain_url(@domain), params: { domain: { name: @domain.name + "foo"} }
assert_redirected_to domain_url(@domain)
end
test "should NOT destroy domain if not logged in" do
assert_difference("Domain.count", 0) do
delete domain_url(@domain)
end
assert_response :redirect
end
test "should NOT destroy domain if not logged in as right user" do
sign_in @user_without_access
assert_difference("Domain.count", 0) do
delete domain_url(@domain)
end
assert_response :redirect
end
test "should destroy domain if logged in" do
sign_in @user_with_access
assert_difference("Domain.count", -1) do
delete domain_url(@domain)
end
assert_redirected_to domains_url
end
end
Conclusion
A couple of things to note:
- Note the setup block; this is pretty universal for almost all my tests
- Note the 5 blank lines between each test context; not as clean as a describe block but still makes the separation obvious
And I will freely admit that this test isn’t perfect (yet). Perfect is the enemy of good enough. This test functions for all the core aspects of a controller and can be readily extended as things like ajax actions are added to controllers.