diff --git a/changelog/new_hidden_test_method_cop.md b/changelog/new_hidden_test_method_cop.md new file mode 100644 index 00000000..35f83ba9 --- /dev/null +++ b/changelog/new_hidden_test_method_cop.md @@ -0,0 +1 @@ +* [#220](/~https://github.com/rubocop/rubocop-minitest/issues/220): Add new `Minitest/HiddenTestMethod` cop. ([@fatkodima][]) diff --git a/config/default.yml b/config/default.yml index f49a550f..d0ad02a3 100644 --- a/config/default.yml +++ b/config/default.yml @@ -158,6 +158,11 @@ Minitest/GlobalExpectations: VersionAdded: '0.7' VersionChanged: '0.26' +Minitest/HiddenTestMethod: + Description: 'Detects hidden (marked as `private` or `protected`) test methods.' + Enabled: pending + VersionAdded: '<>' + Minitest/LiteralAsActualArgument: Description: 'This cop enforces correct order of `expected` and `actual` arguments for `assert_equal`.' StyleGuide: 'https://minitest.rubystyle.guide/#assert-equal-arguments-order' diff --git a/lib/rubocop/cop/minitest/hidden_test_method.rb b/lib/rubocop/cop/minitest/hidden_test_method.rb new file mode 100644 index 00000000..ef1eccdd --- /dev/null +++ b/lib/rubocop/cop/minitest/hidden_test_method.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Minitest + # Detects hidden (marked as `private` or `protected`) test methods. Minitest runs only + # test methods which are `public`. + # + # @example + # # bad + # class FooTest + # private # or protected + # def test_does_something + # assert_equal 42, do_something + # end + # end + # + # # good + # class FooTest + # def test_does_something + # assert_equal 42, do_something + # end + # end + # + # # good (not a test case name) + # class FooTest + # private # or protected + # def does_something + # assert_equal 42, do_something + # end + # end + # + # # good (no assertions) + # class FooTest + # private # or protected + # def test_does_something + # do_something + # end + # end + # + class HiddenTestMethod < Base + include MinitestExplorationHelpers + include DefNode + + MSG = 'Hidden test method detected. Make it public for it to run.' + + def on_class(node) + test_cases(node).each do |test_case| + add_offense(test_case) if non_public?(test_case) && assertions(test_case).any? + end + end + end + end + end +end diff --git a/lib/rubocop/cop/minitest_cops.rb b/lib/rubocop/cop/minitest_cops.rb index c2abc39b..a2478366 100644 --- a/lib/rubocop/cop/minitest_cops.rb +++ b/lib/rubocop/cop/minitest_cops.rb @@ -28,6 +28,7 @@ require_relative 'minitest/assert_truthy' require_relative 'minitest/duplicate_test_run' require_relative 'minitest/empty_line_before_assertion_methods' +require_relative 'minitest/hidden_test_method' require_relative 'minitest/test_file_name' require_relative 'minitest/global_expectations' require_relative 'minitest/literal_as_actual_argument' diff --git a/test/rubocop/cop/minitest/hidden_test_method_test.rb b/test/rubocop/cop/minitest/hidden_test_method_test.rb new file mode 100644 index 00000000..f863cbc8 --- /dev/null +++ b/test/rubocop/cop/minitest/hidden_test_method_test.rb @@ -0,0 +1,75 @@ +# frozen_string_literal: true + +require 'test_helper' + +class HiddenTestMethodTest < Minitest::Test + def test_registers_offense_when_using_private_test_method + assert_offense(<<~RUBY) + class FooTest < Minitest::Test + private + def test_does_something + ^^^^^^^^^^^^^^^^^^^^^^^ Hidden test method detected. Make it public for it to run. + assert_equal 42, do_something + end + end + RUBY + end + + def test_registers_offense_when_using_protected_test_method + assert_offense(<<~RUBY) + class FooTest < Minitest::Test + protected + def test_does_something + ^^^^^^^^^^^^^^^^^^^^^^^ Hidden test method detected. Make it public for it to run. + assert_equal 42, do_something + end + end + RUBY + end + + def test_registers_offense_when_using_private_test_method_outside_of_test_class + assert_offense(<<~RUBY) + class FooTest + private + def test_does_something + ^^^^^^^^^^^^^^^^^^^^^^^ Hidden test method detected. Make it public for it to run. + assert_equal 42, do_something + end + end + RUBY + end + + def test_registers_offense_when_using_private_active_support_test_method + assert_offense(<<~RUBY) + class FooTest + private + test "does something" do + ^^^^^^^^^^^^^^^^^^^^^^^^^ Hidden test method detected. Make it public for it to run. + assert_equal 42, do_something + end + end + RUBY + end + + def test_does_not_register_offense_when_using_private_non_test_method_with_assertions + assert_no_offenses(<<~RUBY) + class FooTest < Minitest::Test + private + def does_something + assert_equal 42, do_something + end + end + RUBY + end + + def test_does_not_register_offense_when_using_private_test_method_without_assertions + assert_no_offenses(<<~RUBY) + class FooTest < Minitest::Test + private + def test_does_something + do_something + end + end + RUBY + end +end