Merge pull request #42465 from ricardotk002/extract-assert-queries

Extract methods `assert_queries` and `assert_no_queries`
This commit is contained in:
Andrew White 2021-06-14 19:56:40 +01:00 committed by GitHub
commit 26c00cb3da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 59 additions and 86 deletions

View File

@ -10,6 +10,8 @@ require "rails/test_help"
require "rails/test_unit/reporter" require "rails/test_unit/reporter"
Rails::TestUnitReporter.executable = "bin/test" Rails::TestUnitReporter.executable = "bin/test"
require "active_record/testing/query_assertions"
# Disable available locale checks to allow to add locale after initialized. # Disable available locale checks to allow to add locale after initialized.
I18n.enforce_available_locales = false I18n.enforce_available_locales = false
@ -22,22 +24,7 @@ if ActiveSupport::TestCase.respond_to?(:fixture_path=)
end end
class ActiveSupport::TestCase class ActiveSupport::TestCase
def assert_queries(expected_count) include ActiveRecord::Testing::QueryAssertions
ActiveRecord::Base.connection.materialize_transactions
queries = []
ActiveSupport::Notifications.subscribe("sql.active_record") do |*, payload|
queries << payload[:sql] unless %w[ SCHEMA TRANSACTION ].include?(payload[:name])
end
yield.tap do
assert_equal expected_count, queries.size, "#{queries.size} instead of #{expected_count} queries were executed. #{queries.inspect}"
end
end
def assert_no_queries(&block)
assert_queries(0, &block)
end
private private
def create_file_blob(filename:, content_type:, metadata: nil) def create_file_blob(filename:, content_type:, metadata: nil)

View File

@ -1,8 +1,11 @@
# frozen_string_literal: true # frozen_string_literal: true
require "active_record_unit" require "active_record_unit"
require "active_record/testing/query_assertions"
class RelationCacheTest < ActionView::TestCase class RelationCacheTest < ActionView::TestCase
include ActiveRecord::Testing::QueryAssertions
tests ActionView::Helpers::CacheHelper tests ActionView::Helpers::CacheHelper
def setup def setup
@ -24,17 +27,4 @@ class RelationCacheTest < ActionView::TestCase
end end
def view_cache_dependencies; []; end def view_cache_dependencies; []; end
def assert_queries(num)
ActiveRecord::Base.connection.materialize_transactions
count = 0
ActiveSupport::Notifications.subscribe("sql.active_record") do |_name, _start, _finish, _id, payload|
count += 1 unless ["SCHEMA", "TRANSACTION"].include? payload[:name]
end
result = yield
assert_equal num, count, "#{count} instead of #{num} queries were executed."
result
end
end end

View File

@ -0,0 +1,47 @@
# frozen_string_literal: true
module ActiveRecord
module Testing
module QueryAssertions # :nodoc:
def assert_queries(expected_count = 1, options = {})
ignore_none = options.fetch(:ignore_none) { expected_count == :any }
ActiveRecord::Base.connection.materialize_transactions
SQLCounter.clear_log
result = yield
the_log = ignore_none ? SQLCounter.log_all : SQLCounter.log
if expected_count == :any
assert_operator the_log.size, :>=, 1, "1 or more queries expected, but none were executed."
else
message = "#{the_log.size} instead of #{expected_count} queries were executed.#{the_log.size == 0 ? '' : "\nQueries:\n#{the_log.join("\n")}"}"
assert_equal expected_count, the_log.size, message
end
result
end
def assert_no_queries(&block)
assert_queries(0, &block)
end
class SQLCounter # :nodoc:
class << self
attr_accessor :ignored_sql, :log, :log_all
def clear_log; self.log = []; self.log_all = []; end
end
clear_log
def call(*, values)
return if values[:cached]
sql = values[:sql]
self.class.log_all << sql
self.class.log << sql unless ["SCHEMA", "TRANSACTION"].include? values[:name]
end
end
ActiveSupport::Notifications.subscribe("sql.active_record", SQLCounter.new)
end
end
end

View File

@ -649,7 +649,7 @@ class DirtyTest < ActiveRecord::TestCase
jon = Person.create! first_name: "Jon" jon = Person.create! first_name: "Jon"
end end
assert ActiveRecord::SQLCounter.log_all.none? { |sql| sql.include?("followers_count") } assert SQLCounter.log_all.none? { |sql| sql.include?("followers_count") }
jon.reload jon.reload
assert_equal "Jon", jon.first_name assert_equal "Jon", jon.first_name

View File

@ -4,6 +4,7 @@ require "active_support"
require "active_support/testing/autorun" require "active_support/testing/autorun"
require "active_support/testing/method_call_assertions" require "active_support/testing/method_call_assertions"
require "active_support/testing/stream" require "active_support/testing/stream"
require "active_record/testing/query_assertions"
require "active_record/fixtures" require "active_record/fixtures"
require "cases/validations_repair_helper" require "cases/validations_repair_helper"
@ -14,6 +15,7 @@ module ActiveRecord
# Defines some test assertions to test against SQL queries. # Defines some test assertions to test against SQL queries.
class TestCase < ActiveSupport::TestCase #:nodoc: class TestCase < ActiveSupport::TestCase #:nodoc:
include ActiveSupport::Testing::MethodCallAssertions include ActiveSupport::Testing::MethodCallAssertions
include ActiveRecord::Testing::QueryAssertions
include ActiveSupport::Testing::Stream include ActiveSupport::Testing::Stream
include ActiveRecord::TestFixtures include ActiveRecord::TestFixtures
include ActiveRecord::ValidationsRepairHelper include ActiveRecord::ValidationsRepairHelper
@ -47,26 +49,6 @@ module ActiveRecord
assert failed_patterns.empty?, "Query pattern(s) #{failed_patterns.map(&:inspect).join(', ')} not found.#{SQLCounter.log.size == 0 ? '' : "\nQueries:\n#{SQLCounter.log.join("\n")}"}" assert failed_patterns.empty?, "Query pattern(s) #{failed_patterns.map(&:inspect).join(', ')} not found.#{SQLCounter.log.size == 0 ? '' : "\nQueries:\n#{SQLCounter.log.join("\n")}"}"
end end
def assert_queries(num = 1, options = {})
ignore_none = options.fetch(:ignore_none) { num == :any }
ActiveRecord::Base.connection.materialize_transactions
SQLCounter.clear_log
x = yield
the_log = ignore_none ? SQLCounter.log_all : SQLCounter.log
if num == :any
assert_operator the_log.size, :>=, 1, "1 or more queries expected, but none were executed."
else
mesg = "#{the_log.size} instead of #{num} queries were executed.#{the_log.size == 0 ? '' : "\nQueries:\n#{the_log.join("\n")}"}"
assert_equal num, the_log.size, mesg
end
x
end
def assert_no_queries(options = {}, &block)
options.reverse_merge! ignore_none: true
assert_queries(0, options, &block)
end
def assert_column(model, column_name, msg = nil) def assert_column(model, column_name, msg = nil)
assert has_column?(model, column_name), msg assert has_column?(model, column_name), msg
end end
@ -135,23 +117,4 @@ module ActiveRecord
super if current_adapter?(:SQLite3Adapter) super if current_adapter?(:SQLite3Adapter)
end end
end end
class SQLCounter
class << self
attr_accessor :ignored_sql, :log, :log_all
def clear_log; self.log = []; self.log_all = []; end
end
clear_log
def call(name, start, finish, message_id, values)
return if values[:cached]
sql = values[:sql]
self.class.log_all << sql
self.class.log << sql unless ["SCHEMA", "TRANSACTION"].include? values[:name]
end
end
ActiveSupport::Notifications.subscribe("sql.active_record", SQLCounter.new)
end end

View File

@ -9,6 +9,7 @@ require "active_support/test_case"
require "active_support/core_ext/object/try" require "active_support/core_ext/object/try"
require "active_support/testing/autorun" require "active_support/testing/autorun"
require "active_support/configuration_file" require "active_support/configuration_file"
require "active_record/testing/query_assertions"
require "active_storage/service/mirror_service" require "active_storage/service/mirror_service"
require "image_processing/mini_magick" require "image_processing/mini_magick"
@ -46,6 +47,8 @@ ActiveStorage.verifier = ActiveSupport::MessageVerifier.new("Testing")
ActiveStorage::FixtureSet.file_fixture_path = File.expand_path("fixtures/files", __dir__) ActiveStorage::FixtureSet.file_fixture_path = File.expand_path("fixtures/files", __dir__)
class ActiveSupport::TestCase class ActiveSupport::TestCase
include ActiveRecord::Testing::QueryAssertions
self.file_fixture_path = ActiveStorage::FixtureSet.file_fixture_path self.file_fixture_path = ActiveStorage::FixtureSet.file_fixture_path
include ActiveRecord::TestFixtures include ActiveRecord::TestFixtures
@ -60,23 +63,6 @@ class ActiveSupport::TestCase
ActiveStorage::Current.reset ActiveStorage::Current.reset
end end
def assert_queries(expected_count)
ActiveRecord::Base.connection.materialize_transactions
queries = []
ActiveSupport::Notifications.subscribe("sql.active_record") do |*, payload|
queries << payload[:sql] unless %w[ SCHEMA TRANSACTION ].include?(payload[:name])
end
yield.tap do
assert_equal expected_count, queries.size, "#{queries.size} instead of #{expected_count} queries were executed. #{queries.inspect}"
end
end
def assert_no_queries(&block)
assert_queries(0, &block)
end
private private
def create_blob(key: nil, data: "Hello world!", filename: "hello.txt", content_type: "text/plain", identify: true, service_name: nil, record: nil) def create_blob(key: nil, data: "Hello world!", filename: "hello.txt", content_type: "text/plain", identify: true, service_name: nil, record: nil)
ActiveStorage::Blob.create_and_upload! key: key, io: StringIO.new(data), filename: filename, content_type: content_type, identify: identify, service_name: service_name, record: record ActiveStorage::Blob.create_and_upload! key: key, io: StringIO.new(data), filename: filename, content_type: content_type, identify: identify, service_name: service_name, record: record