Scott's Recipes Logo

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:

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:

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.