Getting Past Lack of Describe Blocks in MiniTest by Using Multiple Test Files
When you are using RSpec for testing in rails, you can easily use describe blocks to bundle up an overall context. I am, for example, a firm believer in making ABSOLUTELY sure that access control is always covered in my Rails apps that host user data. I would normally do this with a structure like this
describe "not logged in" do
# index action
# show action
# ...
end
describe "logged in" do
# index action
# show action
...
end
As of late, however, I’m not using RSpec – I’m doing more and more with Vanilla rails and that means MiniTest and a consequent lack of describe blocks means that for a single controller you have a combination of logged in and logged out tests. And, given that you have only a single setup block, you either have a sign_out call in every logged out test -or- a sign_in call in every logged in test. Neither is good and neither feels right.
And, as I sit here in Dallas Fort Worth Airport, waiting on a plane to Colorado, I realized the solution:
Why does all test code for a given controller have to live in the same file?
I was working on a test file called:
images_controller_test.rb
So I copied all the code and created the file below (where I then pasted it in):
images_controller_nologin_test.rb
and this test looks as follows:
require "test_helper"
class ImagesControllerTest < ActionDispatch::IntegrationTest
setup do
@image = images(:one)
end
test "should redirect on index when no sign_in" do
get images_url
assert_redirected_to new_user_session_path
end
test "should redirect on show when no sign_in" do
get image_url(@image)
assert_redirected_to new_user_session_path
end
test "should redirect on edit when no sign_in" do
get edit_image_url(@image)
assert_redirected_to new_user_session_path
end
test "should redirect on new when no sign_in" do
get new_image_url
assert_redirected_to new_user_session_path
end
test "should redirect on destroy when no sign_in" do
delete image_url(@image)
assert_redirected_to new_user_session_path
end
test "should redirect on update when no sign_in" do
patch image_url(@image), params: { image: { name: "New Name" } }
assert_redirected_to new_user_session_path
end
test "should redirect on create when no sign_in" do
assert_no_difference("Image.count", 1) do
post images_url, params: { image: { }}
end
assert_response :redirect
end
end
That’s incredibly clean and obvious and that means my normal images_controller_test.rb can be the default state (logged in). I honestly don’t know why I never thought of this before given that it is such a simple concept … Sheesh.