Skip to content

Commit

Permalink
Add new Rails/ActionControllerTestCase cop
Browse files Browse the repository at this point in the history
Add controller testing cop to discourage use of
ActionController::TestCase. ActionDispatch::IntegrationTest should be
used instead to test controllers.
  • Loading branch information
gmcgibbon committed Feb 9, 2022
1 parent 73b6947 commit 4fd37fd
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 0 deletions.
1 change: 1 addition & 0 deletions changelog/new_rails_action_controller_test_case_cop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#638](https://github.com/rubocop/rubocop-rails/pull/638): Add new `Rails/ActionControllerTestCase` cop. ([@gmcgibbon][])
10 changes: 10 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ Lint/NumberConversion:
- fortnights
- in_milliseconds

Rails/ActionControllerTestCase:
Description: 'Use `ActionDispatch::IntegrationTest` instead of `ActionController::TestCase`.'
StyleGuide: 'https://rails.rubystyle.guide/#integration-testing'
Reference: 'https://api.rubyonrails.org/classes/ActionController/TestCase.html'
Enabled: 'pending'
SafeAutocorrect: false
VersionAdded: '<<next>>'
Include:
- '**/test/**/*.rb'

Rails/ActionFilter:
Description: 'Enforces consistent use of action filter methods.'
Enabled: true
Expand Down
47 changes: 47 additions & 0 deletions lib/rubocop/cop/rails/action_controller_test_case.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Rails
# Using `ActionController::TestCase`` is discouraged and should be replaced by
# `ActionDispatch::IntegrationTest``. Controller tests are too close to the
# internals of a controller whereas integration tests mimic the browser/user.
#
# @safety
# This cop's autocorrection is unsafe because the API of each test case class is different.
# Make sure to update each test of your controller test cases after changing the superclass.
#
# @example
# # bad
# class MyControllerTest < ActionController::TestCase
# end
#
# # good
# class MyControllerTest < ActionDispatch::IntegrationTest
# end
#
class ActionControllerTestCase < Base
extend AutoCorrector
extend TargetRailsVersion

MSG = 'Use `ActionDispatch::IntegrationTest` instead.'

minimum_target_rails_version 5.0

def_node_matcher :action_controller_test_case?, <<~PATTERN
(class
(const nil? _)
(const (const {nil? cbase} :ActionController) :TestCase) nil?)
PATTERN

def on_class(node)
return unless action_controller_test_case?(node)

add_offense(node.parent_class) do |corrector|
corrector.replace(node.parent_class, 'ActionDispatch::IntegrationTest')
end
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/rubocop/cop/rails_cops.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
require_relative 'mixin/migrations_helper'
require_relative 'mixin/target_rails_version'

require_relative 'rails/action_controller_test_case'
require_relative 'rails/action_filter'
require_relative 'rails/active_record_aliases'
require_relative 'rails/active_record_callbacks_order'
Expand Down
52 changes: 52 additions & 0 deletions spec/rubocop/cop/rails/action_controller_test_case_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Rails::ActionControllerTestCase, :config do
context 'Rails 4.2', :rails42 do
it 'does not add offense when extending `ActionController::TestCase`' do
expect_no_offenses(<<~RUBY)
class MyControllerTest < ActionController::TestCase
end
RUBY
end
end

it 'adds offense when extending `ActionController::TestCase`' do
expect_offense(<<~RUBY)
class MyControllerTest < ActionController::TestCase
^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `ActionDispatch::IntegrationTest` instead.
end
RUBY

expect_correction(<<~RUBY)
class MyControllerTest < ActionDispatch::IntegrationTest
end
RUBY
end

it 'adds offense when extending `::ActionController::TestCase`' do
expect_offense(<<~RUBY)
class MyControllerTest < ::ActionController::TestCase
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `ActionDispatch::IntegrationTest` instead.
end
RUBY

expect_correction(<<~RUBY)
class MyControllerTest < ActionDispatch::IntegrationTest
end
RUBY
end

it 'does not add offense when extending `ActionDispatch::IntegrationTest`' do
expect_no_offenses(<<~RUBY)
class MyControllerTest < ActionDispatch::IntegrationTest
end
RUBY
end

it 'does not add offense when extending custom superclass' do
expect_no_offenses(<<~RUBY)
class MyControllerTest < SuperControllerTest
end
RUBY
end
end

0 comments on commit 4fd37fd

Please sign in to comment.