diff --git a/Changelog.md b/Changelog.md index 2af015279f..d1b001c4f7 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ Enhancements: * Allow `ActiveJob` matchers `#on_queue` modifier to take symbolic queue names. (Nils Sommer, #2283) * The scaffold generator now generates request specs in preference to controller specs. (Luka Lüdicke, #2288) +* Add configuration option to disable ActiveRecord. (Jon Rowe, Phil Pirozhkov, Hermann Mayer, #2266) Bug Fixes: diff --git a/example_app_generator/generate_stuff.rb b/example_app_generator/generate_stuff.rb index 999b987651..59a2082ddb 100644 --- a/example_app_generator/generate_stuff.rb +++ b/example_app_generator/generate_stuff.rb @@ -44,6 +44,7 @@ def setup_tasks def final_tasks copy_file 'spec/verify_no_active_record_spec.rb' + copy_file 'spec/verify_no_fixture_setup_spec.rb' end def skip_active_record? diff --git a/example_app_generator/no_active_record/spec/verify_no_fixture_setup_spec.rb b/example_app_generator/no_active_record/spec/verify_no_fixture_setup_spec.rb new file mode 100644 index 0000000000..d3ec9b7e6b --- /dev/null +++ b/example_app_generator/no_active_record/spec/verify_no_fixture_setup_spec.rb @@ -0,0 +1,22 @@ +# Pretend that ActiveRecord::Rails is defined and this doesn't blow up +# with `config.use_active_record = false`. +# Trick the other spec that checks that ActiveRecord is +# *not* defined by wrapping it in RSpec::Rails namespace +# so that it's reachable from RSpec::Rails::FixtureSupport. +# NOTE: this has to be defined before requiring `rails_helper`. +module RSpec + module Rails + module ActiveRecord + module TestFixtures + end + end + end +end + +require 'rails_helper' + +RSpec.describe 'Example App', :use_fixtures, type: :model do + it "does not set up fixtures" do + expect(defined?(fixtures)).not_to be + end +end diff --git a/lib/generators/rspec/install/templates/spec/rails_helper.rb b/lib/generators/rspec/install/templates/spec/rails_helper.rb index f13aeef783..5433bc026f 100644 --- a/lib/generators/rspec/install/templates/spec/rails_helper.rb +++ b/lib/generators/rspec/install/templates/spec/rails_helper.rb @@ -42,6 +42,20 @@ # instead of true. config.use_transactional_fixtures = true + # You can uncomment this line to turn off ActiveRecord support entirely. + # config.use_active_record = false + +<% else -%> + # Remove this line to enable support for ActiveRecord + config.use_active_record = false + + # If you enable ActiveRecord support you should unncomment these lines, + # note if you'd prefer not to run each example within a transaction, you + # should set use_transactional_fixtures to false. + # + # config.fixture_path = "#{::Rails.root}/spec/fixtures" + # config.use_transactional_fixtures = true + <% end -%> # RSpec Rails can automatically mix in different behaviours to your tests # based on their file location, for example enabling you to call `get` and diff --git a/lib/rspec/rails/configuration.rb b/lib/rspec/rails/configuration.rb index b79e02ad77..735ec2d9dd 100644 --- a/lib/rspec/rails/configuration.rb +++ b/lib/rspec/rails/configuration.rb @@ -63,6 +63,7 @@ def self.initialize_configuration(config) # rubocop:disable Metrics/MethodLength config.add_setting :infer_base_class_for_anonymous_controllers, default: true # fixture support + config.add_setting :use_active_record, default: true config.add_setting :use_transactional_fixtures, alias_with: :use_transactional_examples config.add_setting :use_instantiated_fixtures config.add_setting :global_fixtures diff --git a/lib/rspec/rails/fixture_support.rb b/lib/rspec/rails/fixture_support.rb index 75df4b914e..2161b115c6 100644 --- a/lib/rspec/rails/fixture_support.rb +++ b/lib/rspec/rails/fixture_support.rb @@ -10,42 +10,53 @@ module FixtureSupport include ActiveRecord::TestFixtures included do - self.fixture_path = RSpec.configuration.fixture_path - if ::Rails::VERSION::STRING > '5' - self.use_transactional_tests = RSpec.configuration.use_transactional_fixtures - else - self.use_transactional_fixtures = RSpec.configuration.use_transactional_fixtures + if RSpec.configuration.use_active_record? + include Fixtures + + self.fixture_path = RSpec.configuration.fixture_path + if ::Rails::VERSION::STRING > '5' + self.use_transactional_tests = RSpec.configuration.use_transactional_fixtures + else + self.use_transactional_fixtures = RSpec.configuration.use_transactional_fixtures + end + self.use_instantiated_fixtures = RSpec.configuration.use_instantiated_fixtures + + fixtures RSpec.configuration.global_fixtures if RSpec.configuration.global_fixtures end - self.use_instantiated_fixtures = RSpec.configuration.use_instantiated_fixtures + end - def self.fixtures(*args) - orig_methods = private_instance_methods - super.tap do - new_methods = private_instance_methods - orig_methods - new_methods.each do |method_name| - proxy_method_warning_if_called_in_before_context_scope(method_name) + module Fixtures + extend ActiveSupport::Concern + + class_methods do + def fixtures(*args) + orig_methods = private_instance_methods + super.tap do + new_methods = private_instance_methods - orig_methods + new_methods.each do |method_name| + proxy_method_warning_if_called_in_before_context_scope(method_name) + end end end - end - def self.proxy_method_warning_if_called_in_before_context_scope(method_name) - orig_implementation = instance_method(method_name) - define_method(method_name) do |*args, &blk| - if inspect.include?("before(:context)") - RSpec.warn_with("Calling fixture method in before :context ") - else - orig_implementation.bind(self).call(*args, &blk) + def proxy_method_warning_if_called_in_before_context_scope(method_name) + orig_implementation = instance_method(method_name) + define_method(method_name) do |*args, &blk| + if inspect.include?("before(:context)") + RSpec.warn_with("Calling fixture method in before :context ") + else + orig_implementation.bind(self).call(*args, &blk) + end end end end if ::Rails.version.to_f >= 6.1 + # @private return the example name for TestFixtures def name @example end end - - fixtures RSpec.configuration.global_fixtures if RSpec.configuration.global_fixtures end end end diff --git a/spec/generators/rspec/install/install_generator_spec.rb b/spec/generators/rspec/install/install_generator_spec.rb index cc71b5879e..dda4e2cb62 100644 --- a/spec/generators/rspec/install/install_generator_spec.rb +++ b/spec/generators/rspec/install/install_generator_spec.rb @@ -12,7 +12,7 @@ def content_for(file_name) end def have_a_fixture_path - match(/config\.fixture_path/m) + match(/^ config\.fixture_path = /m) end def maintain_test_schema @@ -23,8 +23,16 @@ def require_rspec_rails match(/^require 'rspec\/rails'$/m) end - def have_transactional_fixtures_enabled? - match(/config\.use_transactional_fixtures/m) + def have_active_record_enabled + match(/^\ # config\.use_active_record = false/m) + end + + def have_active_record_disabled + match(/^\ config\.use_active_record = false/m) + end + + def have_transactional_fixtures_enabled + match(/^ config\.use_transactional_fixtures = true/m) end def filter_rails_from_backtrace @@ -59,19 +67,24 @@ def filter_rails_from_backtrace expect(rails_helper).to require_rspec_rails end - specify "with transactional fixtures" do + specify "with ActiveRecord" do run_generator - expect(rails_helper).to have_a_fixture_path + expect(rails_helper).to have_active_record_enabled + expect(rails_helper).not_to have_active_record_disabled end specify "with default fixture path" do run_generator - expect(rails_helper).to have_transactional_fixtures_enabled? + expect(rails_helper).to have_a_fixture_path end - specify "excluding rails gems from the backtrace" do + specify "with transactional fixtures" do run_generator + expect(rails_helper).to have_transactional_fixtures_enabled + end + specify "excluding rails gems from the backtrace" do + run_generator expect(rails_helper).to filter_rails_from_backtrace end @@ -86,26 +99,31 @@ def filter_rails_from_backtrace hide_const("ActiveRecord") end - it "requires rspec/rails" do + specify "requiring rspec/rails" do run_generator expect(rails_helper).to require_rspec_rails end - it "does not include config.fixture_path" do + specify "without ActiveRecord" do + run_generator + expect(rails_helper).not_to have_active_record_enabled + expect(rails_helper).to have_active_record_disabled + end + + specify "without fixture path" do run_generator expect(rails_helper).not_to have_a_fixture_path end - it "does not include config.use_transactional_fixtures" do + specify "without transactional fixtures" do run_generator - expect(rails_helper).not_to have_transactional_fixtures_enabled? + expect(rails_helper).not_to have_transactional_fixtures_enabled end - it "does not check use active record migration options" do + specify "without schema maintenance checks" do run_generator expect(rails_helper).not_to use_active_record_migration expect(rails_helper).not_to maintain_test_schema end end - end