Skip to content

Commit 74be4d6

Browse files
authored
Merge pull request #638 from gmcgibbon/controller_testing_cop
Add Rails/ControllerTesting cop
2 parents 73b6947 + 4fd37fd commit 74be4d6

File tree

5 files changed

+111
-0
lines changed

5 files changed

+111
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* [#638](https://github.com/rubocop/rubocop-rails/pull/638): Add new `Rails/ActionControllerTestCase` cop. ([@gmcgibbon][])

config/default.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ Lint/NumberConversion:
3838
- fortnights
3939
- in_milliseconds
4040

41+
Rails/ActionControllerTestCase:
42+
Description: 'Use `ActionDispatch::IntegrationTest` instead of `ActionController::TestCase`.'
43+
StyleGuide: 'https://rails.rubystyle.guide/#integration-testing'
44+
Reference: 'https://api.rubyonrails.org/classes/ActionController/TestCase.html'
45+
Enabled: 'pending'
46+
SafeAutocorrect: false
47+
VersionAdded: '<<next>>'
48+
Include:
49+
- '**/test/**/*.rb'
50+
4151
Rails/ActionFilter:
4252
Description: 'Enforces consistent use of action filter methods.'
4353
Enabled: true
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# frozen_string_literal: true
2+
3+
module RuboCop
4+
module Cop
5+
module Rails
6+
# Using `ActionController::TestCase`` is discouraged and should be replaced by
7+
# `ActionDispatch::IntegrationTest``. Controller tests are too close to the
8+
# internals of a controller whereas integration tests mimic the browser/user.
9+
#
10+
# @safety
11+
# This cop's autocorrection is unsafe because the API of each test case class is different.
12+
# Make sure to update each test of your controller test cases after changing the superclass.
13+
#
14+
# @example
15+
# # bad
16+
# class MyControllerTest < ActionController::TestCase
17+
# end
18+
#
19+
# # good
20+
# class MyControllerTest < ActionDispatch::IntegrationTest
21+
# end
22+
#
23+
class ActionControllerTestCase < Base
24+
extend AutoCorrector
25+
extend TargetRailsVersion
26+
27+
MSG = 'Use `ActionDispatch::IntegrationTest` instead.'
28+
29+
minimum_target_rails_version 5.0
30+
31+
def_node_matcher :action_controller_test_case?, <<~PATTERN
32+
(class
33+
(const nil? _)
34+
(const (const {nil? cbase} :ActionController) :TestCase) nil?)
35+
PATTERN
36+
37+
def on_class(node)
38+
return unless action_controller_test_case?(node)
39+
40+
add_offense(node.parent_class) do |corrector|
41+
corrector.replace(node.parent_class, 'ActionDispatch::IntegrationTest')
42+
end
43+
end
44+
end
45+
end
46+
end
47+
end

lib/rubocop/cop/rails_cops.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
require_relative 'mixin/migrations_helper'
88
require_relative 'mixin/target_rails_version'
99

10+
require_relative 'rails/action_controller_test_case'
1011
require_relative 'rails/action_filter'
1112
require_relative 'rails/active_record_aliases'
1213
require_relative 'rails/active_record_callbacks_order'
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe RuboCop::Cop::Rails::ActionControllerTestCase, :config do
4+
context 'Rails 4.2', :rails42 do
5+
it 'does not add offense when extending `ActionController::TestCase`' do
6+
expect_no_offenses(<<~RUBY)
7+
class MyControllerTest < ActionController::TestCase
8+
end
9+
RUBY
10+
end
11+
end
12+
13+
it 'adds offense when extending `ActionController::TestCase`' do
14+
expect_offense(<<~RUBY)
15+
class MyControllerTest < ActionController::TestCase
16+
^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `ActionDispatch::IntegrationTest` instead.
17+
end
18+
RUBY
19+
20+
expect_correction(<<~RUBY)
21+
class MyControllerTest < ActionDispatch::IntegrationTest
22+
end
23+
RUBY
24+
end
25+
26+
it 'adds offense when extending `::ActionController::TestCase`' do
27+
expect_offense(<<~RUBY)
28+
class MyControllerTest < ::ActionController::TestCase
29+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `ActionDispatch::IntegrationTest` instead.
30+
end
31+
RUBY
32+
33+
expect_correction(<<~RUBY)
34+
class MyControllerTest < ActionDispatch::IntegrationTest
35+
end
36+
RUBY
37+
end
38+
39+
it 'does not add offense when extending `ActionDispatch::IntegrationTest`' do
40+
expect_no_offenses(<<~RUBY)
41+
class MyControllerTest < ActionDispatch::IntegrationTest
42+
end
43+
RUBY
44+
end
45+
46+
it 'does not add offense when extending custom superclass' do
47+
expect_no_offenses(<<~RUBY)
48+
class MyControllerTest < SuperControllerTest
49+
end
50+
RUBY
51+
end
52+
end

0 commit comments

Comments
 (0)