diff --git a/actionmailer/lib/action_mailer/test_case.rb b/actionmailer/lib/action_mailer/test_case.rb index 97afd87840e5b..1a07d8e79242e 100644 --- a/actionmailer/lib/action_mailer/test_case.rb +++ b/actionmailer/lib/action_mailer/test_case.rb @@ -74,6 +74,15 @@ def determine_default_mailer(name) end end + # Reads the fixture file for the given mailer. + # + # This is useful when testing mailers by being able to write the body of + # an email inside a fixture. See the testing guide for a concrete example: + # https://guides.rubyonrails.org/testing.html#revenge-of-the-fixtures + def read_fixture(action) + IO.readlines(File.join(Rails.root, "test", "fixtures", self.class.mailer_class.name.underscore, action)) + end + private def initialize_test_deliveries set_delivery_method :test @@ -110,10 +119,6 @@ def charset def encode(subject) Mail::Encodings.q_value_encode(subject, charset) end - - def read_fixture(action) - IO.readlines(File.join(Rails.root, "test", "fixtures", self.class.mailer_class.name.underscore, action)) - end end include Behavior diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index 444d95a6b3627..69b2181fd4a3f 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -19,10 +19,13 @@ 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 directories - # appointed by ActiveSupport::TestCase.fixture_paths=(path) (this is automatically - # configured for Rails, so you can just put your files in /test/fixtures/, - # or in the test/fixtures folder under any of your application's engines). + # They are stored in YAML files, one file per model, which are by default placed in either + # /test/fixtures/ or in the test/fixtures + # folder under any of your application's engines. + # + # The location can also be changed with ActiveSupport::TestCase.fixture_paths=, + # once you have require "rails/test_help" in your +test_helper.rb+. + # # The fixture file ends with the +.yml+ file extension, for example: # /test/fixtures/web_sites.yml). # @@ -42,10 +45,17 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc: # is followed by an indented list of key/value pairs in the "key: value" format. Records are # separated by a blank line for your viewing pleasure. # - # Note: Fixtures are unordered. If you want ordered fixtures, use the omap YAML type. - # See https://yaml.org/type/omap.html - # for the specification. You will need ordered fixtures when you have foreign key constraints - # on keys in the same table. This is commonly needed for tree structures. Example: + # == Ordering + # + # Fixtures by default are unordered. This is because the maps in YAML are unordered. + # + # If you want ordered fixtures, use the omap YAML type. + # See https://yaml.org/type/omap.html for the specification. + # + # You will need ordered fixtures when you have foreign key constraints + # on keys in the same table. This is commonly needed for tree structures. + # + # For example: # # --- !omap # - parent: @@ -57,7 +67,7 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc: # parent_id: 1 # title: Child # - # = Using Fixtures in Test Cases + # == Using Fixtures in Test Cases # # Since fixtures are a testing construct, we use them in our unit and functional tests. There # are two ways to use the fixtures, but first let's take a look at a sample unit test: @@ -127,7 +137,7 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc: # traversed in the database to create the fixture hash and/or instance variables. This is expensive for # large sets of fixtured data. # - # = Dynamic fixtures with ERB + # == Dynamic fixtures with \ERB # # Sometimes you don't care about the content of the fixtures as much as you care about the volume. # In these cases, you can mix ERB in with your YAML fixtures to create a bunch of fixtures for load @@ -165,7 +175,7 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc: # name: kitten.png # sha: <%= file_sha 'files/kitten.png' %> # - # = Transactional Tests + # == Transactional Tests # # Test cases can use begin+rollback to isolate their changes to the database instead of having to # delete+insert for every test case. @@ -201,7 +211,7 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc: # 2. Your database does not support transactions. Every Active Record database supports transactions except MySQL MyISAM. # Use InnoDB, MaxDB, or NDB instead. # - # = Advanced Fixtures + # == Advanced Fixtures # # Fixtures that don't specify an ID get some extra features: # @@ -215,7 +225,7 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc: # * Fixture label interpolation # * Support for YAML defaults # - # == Stable, Autogenerated IDs + # === Stable, Autogenerated IDs # # Here, have a monkey fixture: # @@ -244,13 +254,13 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc: # The generated ID for a given label is constant, so we can discover # any fixture's ID without loading anything, as long as we know the label. # - # == Label references for associations (+belongs_to+, +has_one+, +has_many+) + # === Label references for associations (+belongs_to+, +has_one+, +has_many+) # # Specifying foreign keys in fixtures can be very fragile, not to # mention difficult to read. Since Active Record can figure out the ID of # any fixture from its label, you can specify FK's by label instead of ID. # - # === +belongs_to+ + # ==== +belongs_to+ # # Let's break out some more monkeys and pirates. # @@ -314,9 +324,9 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc: # # Just provide the polymorphic target type and Active Record will take care of the rest. # - # === +has_and_belongs_to_many+ or has_many :through + # ==== +has_and_belongs_to_many+ or has_many :through # - # Time to give our monkey some fruit. + # \Time to give our monkey some fruit. # # ### in monkeys.yml # @@ -378,7 +388,7 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc: # the fixture's model class and discovers the +has_and_belongs_to_many+ # associations. # - # == Autofilled Timestamp Columns + # === Autofilled \Timestamp Columns # # If your table/model specifies any of Active Record's # standard timestamp columns (+created_at+, +created_on+, +updated_at+, +updated_on+), @@ -386,7 +396,7 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc: # # If you've set specific values, they'll be left alone. # - # == Fixture label interpolation + # === Fixture label interpolation # # The label of the current fixture is always available as a column value: # @@ -407,7 +417,7 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc: # # ActiveRecord::FixtureSet.identify(:boaty_mcboatface, :uuid) # - # == Support for YAML defaults + # === Support for YAML defaults # # You can set and reuse defaults in your fixtures YAML file. # This is the same technique used in the +database.yml+ file to specify @@ -583,7 +593,8 @@ def create_fixtures(fixtures_directories, fixture_set_names, class_names = {}, c end # Returns a consistent, platform-independent identifier for +label+. - # Integer identifiers are values less than 2^30. UUIDs are RFC 4122 version 5 SHA-1 hashes. + # + # \Integer identifiers are values less than 2^30. UUIDs are RFC 4122 version 5 SHA-1 hashes. def identify(label, column_type = :integer) if column_type == :uuid Digest::UUID.uuid_v5(Digest::UUID::OID_NAMESPACE, label.to_s) @@ -596,7 +607,8 @@ def identify(label, column_type = :integer) # between the label and the subcomponents of the provided composite key. # # Example: - # composite_identify("label", [:a, :b, :c]) => { a: hash_1, b: hash_2, c: hash_3 } + # + # composite_identify("label", [:a, :b, :c]) => { a: hash_1, b: hash_2, c: hash_3 } def composite_identify(label, key) key .index_with @@ -604,7 +616,7 @@ def composite_identify(label, key) .with_indifferent_access end - # Superclass for the evaluation contexts used by ERB fixtures. + # Superclass for the evaluation contexts used by \ERB fixtures. def context_class @context_class ||= Class.new end diff --git a/activerecord/lib/active_record/test_fixtures.rb b/activerecord/lib/active_record/test_fixtures.rb index e4a5c4356f70d..8173d9e895d39 100644 --- a/activerecord/lib/active_record/test_fixtures.rb +++ b/activerecord/lib/active_record/test_fixtures.rb @@ -17,6 +17,16 @@ def after_teardown # :nodoc: end included do + ## + # :singleton-method: fixture_paths + # + # Returns the ActiveRecord::FixtureSet collection + + ## + # :singleton-method: fixture_paths= + # + # :call-seq: + # fixture_paths=(fixture_paths) class_attribute :fixture_paths, instance_writer: false, default: [] class_attribute :fixture_table_names, default: [] class_attribute :fixture_class_names, default: {} @@ -42,7 +52,7 @@ def set_fixture_class(class_names = {}) self.fixture_class_names = fixture_class_names.merge(class_names.stringify_keys) end - def fixture_path + def fixture_path # :nodoc: ActiveRecord.deprecator.warn(<<~WARNING) TestFixtures.fixture_path is deprecated and will be removed in Rails 7.2. Use .fixture_paths instead. If multiple fixture paths have been configured with .fixture_paths, then .fixture_path will just return @@ -51,7 +61,7 @@ def fixture_path fixture_paths.first end - def fixture_path=(path) + def fixture_path=(path) # :nodoc: 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 @@ -99,7 +109,7 @@ def uses_transaction?(method) end end - def fixture_path + def fixture_path # :nodoc: ActiveRecord.deprecator.warn(<<~WARNING) TestFixtures#fixture_path is deprecated and will be removed in Rails 7.2. Use #fixture_paths instead. If multiple fixture paths have been configured with #fixture_paths, then #fixture_path will just return diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb index c28868bb0dd71..626d2087af1fa 100644 --- a/activesupport/lib/active_support/test_case.rb +++ b/activesupport/lib/active_support/test_case.rb @@ -120,6 +120,25 @@ def parallelize_setup(&block) def parallelize_teardown(&block) ActiveSupport::Testing::Parallelization.run_cleanup_hook(&block) end + + # :singleton-method: fixture_paths + # + # Returns the ActiveRecord::FixtureSet collection. + # + # In your +test_helper.rb+ you must have require "rails/test_help". + + # :singleton-method: fixture_paths= + # + # :call-seq: + # fixture_paths=(fixture_paths) + # + # Sets the given path to the fixture set. + # + # Can also append multiple paths. + # + # ActiveSupport::TestCase.fixture_paths << "component1/test/fixtures" + # + # In your +test_helper.rb+ you must have require "rails/test_help". end alias_method :method_name, :name