Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce BundlerSetupInTests cop #18

Merged
merged 4 commits into from Aug 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions config/default.yml
@@ -1,5 +1,10 @@
# This is the default configuration file.

Packaging/BundlerSetupInTests:
Description: 'Avoid using `bundler/setup` in your tests.'
Enabled: true
VersionAdded: '0.4'

Packaging/GemspecGit:
Description: 'Use pure Ruby alternative instead of `git ls-files`.'
Enabled: true
Expand Down
1 change: 1 addition & 0 deletions docs/modules/ROOT/pages/cops.adoc
Expand Up @@ -2,6 +2,7 @@

=== Department xref:cops_packaging.adoc[Packaging]

* xref:cops_packaging.adoc#packagingbundlersetupintests[Packaging/BundlerSetupInTests]
* xref:cops_packaging.adoc#packaginggemspecgit[Packaging/GemspecGit]
* xref:cops_packaging.adoc#packagingrequirerelativehardcodinglib[Packaging/RequireRelativeHardcodingLib]

Expand Down
27 changes: 27 additions & 0 deletions docs/modules/ROOT/pages/cops_packaging.adoc
@@ -1,5 +1,32 @@
= Packaging

== Packaging/BundlerSetupInTests

|===
| Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged

| Enabled
| Yes
| No
| 0.4
| -
|===

This cop flags the `require "bundler/setup"` calls if they're
made from inside the tests directory.

=== Examples

[source,ruby]
----
# bad
require "foo"
require "bundler/setup"

# good
require "foo"
----

== Packaging/GemspecGit

|===
Expand Down
65 changes: 65 additions & 0 deletions lib/rubocop/cop/packaging/bundler_setup_in_tests.rb
@@ -0,0 +1,65 @@
# frozen_string_literal: true

require "rubocop/packaging/lib_helper_module"

module RuboCop # :nodoc:
module Cop # :nodoc:
module Packaging # :nodoc:
# This cop flags the `require "bundler/setup"` calls if they're
# made from inside the tests directory.
#
# @example
#
# # bad
# require "foo"
# require "bundler/setup"
#
# # good
# require "foo"
#
class BundlerSetupInTests < Base
include RuboCop::Packaging::LibHelperModule

# This is the message that will be displayed when RuboCop::Packaging finds
# an offense of using `require "bundler/setup"` in the tests directory.
MSG = "Avoid using `bundler/setup` in your tests."

def_node_matcher :bundler_setup?, <<~PATTERN
(send nil? :require
(str #bundler_setup_in_test_dir?))
PATTERN

# Extended from the Base class.
# More about the `#on_new_investigation` method can be found here:
# https://github.com/rubocop-hq/rubocop/blob/343f62e4555be0470326f47af219689e21c61a37/lib/rubocop/cop/base.rb
#
# Processing of the AST happens here.
def on_new_investigation
@file_path = processed_source.file_path
@file_directory = File.dirname(@file_path)
end

# Extended from AST::Traversal.
# More about the `#on_send` method can be found here:
# https://github.com/rubocop-hq/rubocop-ast/blob/08d0f49a47af1e9a30a6d8f67533ba793c843d67/lib/rubocop/ast/traversal.rb#L112
def on_send(node)
return unless bundler_setup?(node)

add_offense(node)
end

# This method is called from inside `#def_node_matcher`.
# It flags an offense if the `require "bundler/setup"`
# call is made from the tests directory.
def bundler_setup_in_test_dir?(str)
str.eql?("bundler/setup") && falls_in_test_dir?
end

# This method determines if the call is made *from* the tests directory.
def falls_in_test_dir?
%w[spec specs test tests].any? { |dir| File.expand_path(@file_directory).start_with?("#{root_dir}/#{dir}") }
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/rubocop/cop/packaging_cops.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true

require_relative "packaging/bundler_setup_in_tests"
require_relative "packaging/gemspec_git"
require_relative "packaging/require_relative_hardcoding_lib"
53 changes: 53 additions & 0 deletions spec/rubocop/cop/packaging/bundler_setup_in_tests_spec.rb
@@ -0,0 +1,53 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Packaging::BundlerSetupInTests, :config do
let(:message) { RuboCop::Cop::Packaging::BundlerSetupInTests::MSG }

let(:project_root) { RuboCop::ConfigLoader.project_root }

context "when `require bundler/setup` is used in specs/" do
let(:filename) { "#{project_root}/spec/spec_helper.rb" }
let(:source) { "require 'bundler/setup'" }

it "registers an offense" do
expect_offense(<<~RUBY, filename)
#{source}
#{"^" * source.length} #{message}
RUBY
end
end

context "when `require bundler/setup` is used in test/foo" do
let(:filename) { "#{project_root}/tests/foo/test_bar.rb" }
let(:source) { "require 'bundler/setup'" }

it "registers an offense" do
expect_offense(<<~RUBY, filename)
#{source}
#{"^" * source.length} #{message}
RUBY
end
end

context "when `require bundler/setup` is used in a Rakefile" do
let(:filename) { "#{project_root}/Rakefile" }
let(:source) { "require 'bundler/setup'" }

it "does not register an offense" do
expect_no_offenses(<<~RUBY, filename)
#{source}
RUBY
end
end

context "when `require bundler/setup` is used in bin/console" do
let(:filename) { "#{project_root}/bin/console" }
let(:source) { "require 'bundler/setup'" }

it "does not register an offense" do
expect_no_offenses(<<~RUBY, filename)
#{source}
RUBY
end
end
end