Skip to content

Commit

Permalink
Add new Rails/ControllerTesting 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 4, 2022
1 parent 73b6947 commit b7046b9
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 0 deletions.
1 change: 1 addition & 0 deletions changelog/new_rails_controller_testing_cop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#638](https://github.com/rubocop/rubocop-rails/pull/614): Add new `Rails/ControllerTesting` cop. ([@gmcgibbon][])
10 changes: 10 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,16 @@ Rails/ContentTag:
Exclude:
- app/models/**/*.rb

Rails/ControllerTesting:
Description: 'Use `ActionDispatch::IntegrationTest` instead of `ActionController::TestCase`.'
Reference:
- 'https://api.rubyonrails.org/classes/ActionController/TestCase.html'
Enabled: true
VersionAdded: '<<next>>'
Include:
- test/**/*.rb


Rails/CreateTableWithTimestamps:
Description: >-
Checks the migration for which timestamps are not included
Expand Down
47 changes: 47 additions & 0 deletions lib/rubocop/cop/rails/controller_testing.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 mimick 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 ControllerTesting < Base
extend AutoCorrector
extend TargetRailsVersion

MSG = 'Use ActionDispatch::IntegrationTest instead. See https://api.rubyonrails.org/classes/ActionController/TestCase.html'

minimum_target_rails_version 5.0

def_node_matcher :controller_test_case?, <<~PATTERN
(class
(const nil? _)
(const (const nil? :ActionController) :TestCase) nil?)
PATTERN

def on_class(node)
return unless 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 @@ -26,6 +26,7 @@
require_relative 'rails/bulk_change_table'
require_relative 'rails/compact_blank'
require_relative 'rails/content_tag'
require_relative 'rails/controller_testing'
require_relative 'rails/create_table_with_timestamps'
require_relative 'rails/date'
require_relative 'rails/default_scope'
Expand Down
31 changes: 31 additions & 0 deletions spec/rubocop/cop/rails/controller_testing_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Rails::ControllerTesting, :config do
context 'Rails 4.2', :rails42, :config 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. See https://api.rubyonrails.org/classes/ActionController/TestCase.html
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
end

0 comments on commit b7046b9

Please sign in to comment.