Introducs TestFixtures#fixture_paths.

Multiple fixture paths can now be specified using the `#fixture_paths` accessor.
This commit is contained in:
Andrew Novoselac 2023-03-13 15:06:31 -04:00
parent fdceee8d78
commit 6902cbce1b
14 changed files with 97 additions and 49 deletions

@ -14,10 +14,10 @@
require "rails/test_unit/reporter"
Rails::TestUnitReporter.executable = "bin/test"
if ActiveSupport::TestCase.respond_to?(:fixture_path=)
ActiveSupport::TestCase.fixture_path = File.expand_path("fixtures", __dir__)
ActionDispatch::IntegrationTest.fixture_path = ActiveSupport::TestCase.fixture_path
ActiveSupport::TestCase.file_fixture_path = ActiveSupport::TestCase.fixture_path + "/files"
if ActiveSupport::TestCase.respond_to?(:fixture_paths=)
ActiveSupport::TestCase.fixture_paths = [File.expand_path("fixtures", __dir__)]
ActionDispatch::IntegrationTest.fixture_paths = ActiveSupport::TestCase.fixture_paths
ActiveSupport::TestCase.file_fixture_path = File.expand_path("fixtures", __dir__) + "/files"
ActiveSupport::TestCase.fixtures :all
end

@ -6,7 +6,10 @@
require "rails/engine"
class TestCaseTest < ActionController::TestCase
def self.fixture_path; end
def self.fixture_paths
[]
end
self.file_fixture_path = File.expand_path("../fixtures/multipart", __dir__)
class TestController < ActionController::Base
@ -931,14 +934,14 @@ def test_fixture_file_upload
assert_equal "45142", @response.body
end
def test_fixture_file_upload_ignores_fixture_path_given_full_path
TestCaseTest.stub :fixture_path, __dir__ do
def test_fixture_file_upload_ignores_fixture_paths_given_full_path
TestCaseTest.stub :fixture_paths, __dir__ do
uploaded_file = fixture_file_upload("#{FILES_DIR}/ruby_on_rails.jpg", "image/jpeg")
assert_equal File.open("#{FILES_DIR}/ruby_on_rails.jpg", READ_PLAIN).read, uploaded_file.read
end
end
def test_fixture_file_upload_ignores_nil_fixture_path
def test_fixture_file_upload_ignores_empty_fixture_paths
uploaded_file = fixture_file_upload("#{FILES_DIR}/ruby_on_rails.jpg", "image/jpeg")
assert_equal File.open("#{FILES_DIR}/ruby_on_rails.jpg", READ_PLAIN).read, uploaded_file.read
end

@ -16,10 +16,10 @@
I18n.enforce_available_locales = false
# Load fixtures from the engine
if ActiveSupport::TestCase.respond_to?(:fixture_path=)
ActiveSupport::TestCase.fixture_path = File.expand_path("fixtures", __dir__)
ActionDispatch::IntegrationTest.fixture_path = ActiveSupport::TestCase.fixture_path
ActiveSupport::TestCase.file_fixture_path = ActiveSupport::TestCase.fixture_path + "/files"
if ActiveSupport::TestCase.respond_to?(:fixture_paths=)
ActiveSupport::TestCase.fixture_paths = [File.expand_path("fixtures", __dir__)]
ActionDispatch::IntegrationTest.fixture_paths = ActiveSupport::TestCase.fixture_paths
ActiveSupport::TestCase.file_fixture_path = File.expand_path("fixtures", __dir__) + "/files"
ActiveSupport::TestCase.fixtures :all
end

@ -94,7 +94,7 @@ def self.tests(controller)
# Set our fixture path
if ActiveRecordTestConnector.able_to_connect
self.fixture_path = [FIXTURE_LOAD_PATH]
self.fixture_paths = [FIXTURE_LOAD_PATH]
self.use_transactional_tests = false
end

@ -1,3 +1,18 @@
* Introduce `TestFixtures#fixture_paths`.
Multiple fixture paths can now be specified using the `#fixture_paths` accessor.
Apps will continue to have `test/fixtures` as their one fixture path by default,
but additional fixture paths can be specified.
```ruby
ActiveSupport::TestCase.fixture_paths << "component1/test/fixtures"
ActiveSupport::TestCase.fixture_paths << "component2/test/fixtures"
```
`TestFixtures#fixture_path` is now deprecated.
*Andrew Novoselac*
* Respect `foreign_type` option to `delegated_type` for `{role}_class` method.
Usage of `delegated_type` with non-conventional `{role}_type` column names can now be specified with `foreign_type` option.

@ -17,8 +17,8 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc:
# \Fixtures are a way of organizing data that you want to test against; in short, sample data.
#
# They are stored in YAML files, one file per model, which are placed in the directory
# appointed by <tt>ActiveSupport::TestCase.fixture_path=(path)</tt> (this is automatically
# They are stored in YAML files, one file per model, which are placed in the directories
# appointed by <tt>ActiveSupport::TestCase.fixture_paths=(path)</tt> (this is automatically
# configured for Rails, so you can just put your files in <tt><your-rails-app>/test/fixtures/</tt>).
# The fixture file ends with the +.yml+ file extension, for example:
# <tt><your-rails-app>/test/fixtures/web_sites.yml</tt>).
@ -552,7 +552,7 @@ def instantiate_all_loaded_fixtures(object, load_instances = true)
end
end
def create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base, &block)
def create_fixtures(fixtures_directories, fixture_set_names, class_names = {}, config = ActiveRecord::Base, &block)
fixture_set_names = Array(fixture_set_names).map(&:to_s)
class_names = ClassCache.new class_names, config
@ -565,7 +565,7 @@ def create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, con
if fixture_files_to_read.any?
fixtures_map = read_and_insert(
fixtures_directory,
Array(fixtures_directories),
fixture_files_to_read,
class_names,
connection,
@ -591,15 +591,16 @@ def context_class
end
private
def read_and_insert(fixtures_directory, fixture_files, class_names, connection) # :nodoc:
def read_and_insert(fixtures_directories, fixture_files, class_names, connection) # :nodoc:
fixtures_map = {}
directory_glob = "{#{fixtures_directories.join(",")}}"
fixture_sets = fixture_files.map do |fixture_set_name|
klass = class_names[fixture_set_name]
fixtures_map[fixture_set_name] = new( # ActiveRecord::FixtureSet.new
nil,
fixture_set_name,
klass,
::File.join(fixtures_directory, fixture_set_name)
::File.join(directory_glob, fixture_set_name)
)
end
update_all_loaded_fixtures(fixtures_map)
@ -715,10 +716,13 @@ def ignored_fixtures=(base)
# Loads the fixtures from the YAML file at +path+.
# If the file sets the +model_class+ and current instance value is not set,
# it uses the file value.
def read_fixture_files(path)
yaml_files = Dir["#{path}/{**,*}/*.yml"].select { |f|
yaml_files = Dir["#{path}{.yml,/{**,*}/*.yml}"].select { |f|
::File.file?(f)
} + [yaml_file_path(path)]
}
raise ArgumentError, "No fixture files found for #{@name}" if yaml_files.empty?
yaml_files.each_with_object({}) do |file, fixtures|
FixtureSet::File.open(file) do |fh|
@ -730,10 +734,6 @@ def read_fixture_files(path)
end
end
end
def yaml_file_path(path)
"#{path}.yml"
end
end
class Fixture # :nodoc:

@ -17,7 +17,7 @@ def after_teardown # :nodoc:
end
included do
class_attribute :fixture_path, instance_writer: false
class_attribute :fixture_paths, instance_writer: false, default: []
class_attribute :fixture_table_names, default: []
class_attribute :fixture_class_names, default: {}
class_attribute :use_transactional_tests, default: true
@ -40,12 +40,24 @@ def set_fixture_class(class_names = {})
self.fixture_class_names = fixture_class_names.merge(class_names.stringify_keys)
end
def fixture_path
ActiveRecord.deprecator.warn("TestFixtures#fixture_path is deprecated and will be removed in Rails 7.2. Use #fixture_paths instead.")
fixture_paths
end
def fixture_path=(path)
ActiveRecord.deprecator.warn("TestFixtures#fixture_path is deprecated and will be removed in Rails 7.2. Use #fixture_paths instead.")
self.fixture_paths = Array(path)
end
def fixtures(*fixture_set_names)
if fixture_set_names.first == :all
raise StandardError, "No fixture path found. Please set `#{self}.fixture_path`." if fixture_path.blank?
fixture_set_names = Dir[::File.join(fixture_path, "{**,*}/*.{yml}")].uniq
fixture_set_names.reject! { |f| f.start_with?(file_fixture_path.to_s) } if defined?(file_fixture_path) && file_fixture_path
fixture_set_names.map! { |f| f[fixture_path.to_s.size..-5].delete_prefix("/") }
raise StandardError, "No fixture path found. Please set `#{self}.fixture_paths`." if fixture_paths.blank?
fixture_set_names = fixture_paths.flat_map do |path|
names = Dir[::File.join(path, "{**,*}/*.{yml}")].uniq
names.reject! { |f| f.start_with?(file_fixture_path.to_s) } if defined?(file_fixture_path) && file_fixture_path
names.map! { |f| f[path.to_s.size..-5].delete_prefix("/") }
end.uniq
else
fixture_set_names = fixture_set_names.flatten.map(&:to_s)
end
@ -81,6 +93,11 @@ def uses_transaction?(method)
end
end
def fixture_path
ActiveRecord.deprecator.warn("TestFixtures#fixture_path is deprecated and will be removed in Rails 7.2. Use #fixture_paths instead.")
fixture_paths
end
def run_in_transaction?
use_transactional_tests &&
!self.class.uses_transaction?(name)
@ -215,7 +232,7 @@ def teardown_shared_connection_pool
end
def load_fixtures(config)
ActiveRecord::FixtureSet.create_fixtures(fixture_path, fixture_table_names, fixture_class_names, config).index_by(&:name)
ActiveRecord::FixtureSet.create_fixtures(fixture_paths, fixture_table_names, fixture_class_names, config).index_by(&:name)
end
def instantiate_fixtures

@ -482,7 +482,7 @@ def test_nonexistent_fixture_file
# Ensure that this file never exists
assert_empty Dir[nonexistent_fixture_path + "*"]
assert_raise(Errno::ENOENT) do
assert_raise(ArgumentError) do
ActiveRecord::FixtureSet.new(nil, "companies", Company, nonexistent_fixture_path)
end
end
@ -1125,7 +1125,7 @@ def load_fixtures(config)
class LoadAllFixturesTest < ActiveRecord::TestCase
def test_all_there
self.class.fixture_path = FIXTURES_ROOT + "/all"
self.class.fixture_paths = [FIXTURES_ROOT + "/all"]
self.class.fixtures :all
if File.symlink? FIXTURES_ROOT + "/all/admin"
@ -1136,9 +1136,22 @@ def test_all_there
end
end
class LoadAllFixturesWithArrayTest < ActiveRecord::TestCase
def test_all_there
self.class.fixture_paths = [FIXTURES_ROOT + "/all", FIXTURES_ROOT + "/categories"]
self.class.fixtures :all
if File.symlink? FIXTURES_ROOT + "/all/admin"
assert_equal %w(admin/accounts admin/users developers namespaced/accounts people special_categories subsubdir/arbitrary_filename tasks), fixture_table_names.sort
end
ensure
ActiveRecord::FixtureSet.reset_cache
end
end
class LoadAllFixturesWithPathnameTest < ActiveRecord::TestCase
def test_all_there
self.class.fixture_path = Pathname.new(FIXTURES_ROOT).join("all")
self.class.fixture_paths = [Pathname.new(FIXTURES_ROOT).join("all")]
self.class.fixtures :all
if File.symlink? FIXTURES_ROOT + "/all/admin"
@ -1482,13 +1495,13 @@ class NilFixturePathTest < ActiveRecord::TestCase
error = assert_raises(StandardError) do
TestCase = Class.new(ActiveRecord::TestCase)
TestCase.class_eval do
self.fixture_path = nil
self.fixture_paths = nil
fixtures :all
end
end
assert_equal <<~MSG.squish, error.message
No fixture path found.
Please set `NilFixturePathTest::TestCase.fixture_path`.
Please set `NilFixturePathTest::TestCase.fixture_paths`.
MSG
end
end
@ -1499,7 +1512,7 @@ def self.file_fixture_path
end
test "ignores file fixtures" do
self.class.fixture_path = FIXTURES_ROOT + "/all"
self.class.fixture_paths = [FIXTURES_ROOT + "/all"]
self.class.fixtures :all
assert_equal %w(developers namespaced/accounts people tasks), fixture_table_names.sort

@ -27,12 +27,12 @@ class TestCase < ActiveSupport::TestCase # :nodoc:
include LoadSchemaHelper
extend LoadSchemaHelper
self.fixture_path = FIXTURES_ROOT
self.fixture_paths = [FIXTURES_ROOT]
self.use_instantiated_fixtures = false
self.use_transactional_tests = true
def create_fixtures(*fixture_set_names, &block)
ActiveRecord::FixtureSet.create_fixtures(ActiveRecord::TestCase.fixture_path, fixture_set_names, fixture_class_names, &block)
ActiveRecord::FixtureSet.create_fixtures(ActiveRecord::TestCase.fixture_paths, fixture_set_names, fixture_class_names, &block)
end
def teardown

@ -32,7 +32,7 @@ def test_doesnt_rely_on_active_support_test_case_specific_methods
klass = Class.new(Minitest::Test) do
include ActiveRecord::TestFixtures
self.fixture_path = tmp_dir
self.fixture_paths = [tmp_dir]
self.use_transactional_tests = true
fixtures :all

@ -25,7 +25,7 @@ class ActiveSupport::TestCase
include ActiveRecord::TestFixtures
self.fixture_path = File.expand_path("fixtures", __dir__)
self.fixture_paths = [File.expand_path("fixtures", __dir__)]
setup do
ActiveStorage::Current.url_options = { protocol: "https://", host: "example.com", port: nil }

@ -12,10 +12,10 @@ require "rails/test_help"
<% unless options[:skip_active_record] -%>
# Load fixtures from the engine
if ActiveSupport::TestCase.respond_to?(:fixture_path=)
ActiveSupport::TestCase.fixture_path = File.expand_path("fixtures", __dir__)
ActionDispatch::IntegrationTest.fixture_path = ActiveSupport::TestCase.fixture_path
ActiveSupport::TestCase.file_fixture_path = ActiveSupport::TestCase.fixture_path + "/files"
if ActiveSupport::TestCase.respond_to?(:fixture_paths=)
ActiveSupport::TestCase.fixture_paths = [File.expand_path("fixtures", __dir__)]
ActionDispatch::IntegrationTest.fixture_paths = ActiveSupport::TestCase.fixture_paths
ActiveSupport::TestCase.file_fixture_path = File.expand_path("fixtures", __dir__) + "/files"
ActiveSupport::TestCase.fixtures :all
end
<% end -%>

@ -24,12 +24,12 @@
include ActiveRecord::TestDatabases
include ActiveRecord::TestFixtures
self.fixture_path = "#{Rails.root}/test/fixtures/"
self.file_fixture_path = fixture_path + "files"
self.fixture_paths << "#{Rails.root}/test/fixtures/"
self.file_fixture_path = "#{Rails.root}/test/fixtures/files"
end
ActiveSupport.on_load(:action_dispatch_integration_test) do
self.fixture_path = ActiveSupport::TestCase.fixture_path
self.fixture_paths += ActiveSupport::TestCase.fixture_paths
end
else
ActiveSupport.on_load(:active_support_test_case) do

@ -373,7 +373,7 @@ def test_create_mountable_application_with_mountable_option
assert_file "test/test_helper.rb" do |content|
assert_match(/ActiveRecord::Migrator\.migrations_paths.+\.\.\/test\/dummy\/db\/migrate/, content)
assert_match(/ActiveRecord::Migrator\.migrations_paths.+<<.+\.\.\/db\/migrate/, content)
assert_match(/ActionDispatch::IntegrationTest\.fixture_path = ActiveSupport::TestCase\.fixture_pat/, content)
assert_match(/ActionDispatch::IntegrationTest\.fixture_paths = ActiveSupport::TestCase\.fixture_pat/, content)
assert_no_match(/Rails::TestUnitReporter\.executable = "bin\/test"/, content)
end
assert_no_file "bin/test"