Merge pull request #50281 from p8/activerecord/assert-queries

Expose `assert_queries` and `assert_no_queries` assertions
This commit is contained in:
Jean Boussier 2023-12-12 00:29:45 +01:00 committed by GitHub
commit 3881518c47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 85 additions and 48 deletions

@ -6,6 +6,7 @@
ENV["RAILS_ENV"] = "test"
require_relative "../test/dummy/config/environment"
require "active_record/testing/query_assertions"
ActiveRecord::Migrator.migrations_paths = [File.expand_path("../test/dummy/db/migrate", __dir__)]
require "rails/test_help"
@ -26,23 +27,7 @@
class ActiveSupport::TestCase
module QueryHelpers
include ActiveJob::TestHelper
def assert_queries(expected_count, &block)
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
result = _assert_nothing_raised_or_warn("assert_queries", &block)
assert_equal expected_count, queries.size, "#{queries.size} instead of #{expected_count} queries were executed. #{queries.inspect}"
result
end
def assert_no_queries(&block)
assert_queries(0, &block)
end
include ActiveRecord::Assertions::QueryAssertions
end
private

@ -1,9 +1,11 @@
# frozen_string_literal: true
require "active_record_unit"
require "active_record/testing/query_assertions"
class RelationCacheTest < ActionView::TestCase
tests ActionView::Helpers::CacheHelper
include ActiveRecord::Assertions::QueryAssertions
def setup
super
@ -24,17 +26,4 @@ def test_cache_relation_other
end
def view_cache_dependencies; []; end
def assert_queries(num, &block)
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 = _assert_nothing_raised_or_warn("assert_queries", &block)
assert_equal num, count, "#{count} instead of #{num} queries were executed."
result
end
end

@ -1,3 +1,19 @@
* Make `assert_queries` and `assert_no_queries` assertions public.
To assert the expected number of queries are made, Rails internally uses
`assert_queries` and `assert_no_queries`. These assertions can be now
be used in applications as well.
```ruby
class ArticleTest < ActiveSupport::TestCase
test "queries are made" do
assert_queries(1) { Article.first }
end
end
```
*Petrik de Heus*
* Fix `has_secure_token` calls the setter method on initialize.
*Abeid Ahmed*

@ -0,0 +1,24 @@
# frozen_string_literal: true
module ActiveRecord
module Assertions
module QueryAssertions
def assert_queries(expected_count, matcher: nil, &block)
ActiveRecord::Base.connection.materialize_transactions
queries = []
ActiveSupport::Notifications.subscribe("sql.active_record") do |*, payload|
queries << payload[:sql] if %w[ SCHEMA TRANSACTION ].exclude?(payload[:name]) && (matcher.nil? || payload[:sql].match(matcher))
end
result = _assert_nothing_raised_or_warn("assert_queries", &block)
assert_equal expected_count, queries.size, "#{queries.size} instead of #{expected_count} queries were executed. Queries: #{queries.join("\n\n")}"
result
end
def assert_no_queries(&block)
assert_queries(0, &block)
end
end
end
end

@ -0,0 +1,36 @@
# frozen_string_literal: true
require "cases/helper"
require "models/post"
require "active_record/testing/query_assertions"
module ActiveRecord
module Assertions
class QueryAssertionsTest < ActiveSupport::TestCase
include QueryAssertions
def test_assert_queries
assert_queries(1) { Post.first }
error = assert_raises(Minitest::Assertion) {
assert_queries(2) { Post.first }
}
assert_match(/1 instead of 2 queries/, error.message)
error = assert_raises(Minitest::Assertion) {
assert_queries(0) { Post.first }
}
assert_match(/1 instead of 0 queries/, error.message)
end
end
def test_assert_no_queries
assert_no_queries { Post.none }
error = assert_raises(Minitest::Assertion) {
assert_no_queries { Post.first }
}
assert_match(/1 .* instead of 2/, error.message)
end
end
end

@ -12,6 +12,8 @@
require "active_support/testing/autorun"
require "image_processing/mini_magick"
require "active_record/testing/query_assertions"
require "active_job"
ActiveJob::Base.queue_adapter = :test
ActiveJob::Base.logger = ActiveSupport::Logger.new(nil)
@ -24,6 +26,7 @@ class ActiveSupport::TestCase
self.file_fixture_path = ActiveStorage::FixtureSet.file_fixture_path
include ActiveRecord::TestFixtures
include ActiveRecord::Assertions::QueryAssertions
self.fixture_paths = [File.expand_path("fixtures", __dir__)]
@ -35,23 +38,6 @@ class ActiveSupport::TestCase
ActiveStorage::Current.reset
end
def assert_queries(expected_count, matcher: nil, &block)
ActiveRecord::Base.connection.materialize_transactions
queries = []
ActiveSupport::Notifications.subscribe("sql.active_record") do |*, payload|
queries << payload[:sql] if %w[ SCHEMA TRANSACTION ].exclude?(payload[:name]) && (matcher.nil? || payload[:sql].match(matcher))
end
result = _assert_nothing_raised_or_warn("assert_queries", &block)
assert_equal expected_count, queries.size, "#{queries.size} instead of #{expected_count} queries were executed. Queries: #{queries.join("\n\n")}"
result
end
def assert_no_queries(&block)
assert_queries(0, &block)
end
private
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

@ -11,15 +11,16 @@
require "action_controller/test_case"
require "action_dispatch/testing/integration"
require "rails/generators/test_case"
require "active_support/testing/autorun"
require "rails/testing/maintain_test_schema"
if defined?(ActiveRecord::Base)
require "active_record/testing/query_assertions"
ActiveSupport.on_load(:active_support_test_case) do
include ActiveRecord::TestDatabases
include ActiveRecord::TestFixtures
include ActiveRecord::Assertions::QueryAssertions
self.fixture_paths << "#{Rails.root}/test/fixtures/"
self.file_fixture_path = "#{Rails.root}/test/fixtures/files"