Skip to content

Commit 3881518

Browse files
authored
Merge pull request rails#50281 from p8/activerecord/assert-queries
Expose `assert_queries` and `assert_no_queries` assertions
2 parents 109bb44 + 8392c54 commit 3881518

File tree

7 files changed

+85
-48
lines changed

7 files changed

+85
-48
lines changed

actiontext/test/test_helper.rb

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
ENV["RAILS_ENV"] = "test"
77

88
require_relative "../test/dummy/config/environment"
9+
require "active_record/testing/query_assertions"
910
ActiveRecord::Migrator.migrations_paths = [File.expand_path("../test/dummy/db/migrate", __dir__)]
1011
require "rails/test_help"
1112

@@ -26,23 +27,7 @@
2627
class ActiveSupport::TestCase
2728
module QueryHelpers
2829
include ActiveJob::TestHelper
29-
30-
def assert_queries(expected_count, &block)
31-
ActiveRecord::Base.connection.materialize_transactions
32-
33-
queries = []
34-
ActiveSupport::Notifications.subscribe("sql.active_record") do |*, payload|
35-
queries << payload[:sql] unless %w[ SCHEMA TRANSACTION ].include?(payload[:name])
36-
end
37-
38-
result = _assert_nothing_raised_or_warn("assert_queries", &block)
39-
assert_equal expected_count, queries.size, "#{queries.size} instead of #{expected_count} queries were executed. #{queries.inspect}"
40-
result
41-
end
42-
43-
def assert_no_queries(&block)
44-
assert_queries(0, &block)
45-
end
30+
include ActiveRecord::Assertions::QueryAssertions
4631
end
4732

4833
private
Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# frozen_string_literal: true
22

33
require "active_record_unit"
4+
require "active_record/testing/query_assertions"
45

56
class RelationCacheTest < ActionView::TestCase
67
tests ActionView::Helpers::CacheHelper
8+
include ActiveRecord::Assertions::QueryAssertions
79

810
def setup
911
super
@@ -24,17 +26,4 @@ def test_cache_relation_other
2426
end
2527

2628
def view_cache_dependencies; []; end
27-
28-
def assert_queries(num, &block)
29-
ActiveRecord::Base.connection.materialize_transactions
30-
count = 0
31-
32-
ActiveSupport::Notifications.subscribe("sql.active_record") do |_name, _start, _finish, _id, payload|
33-
count += 1 unless ["SCHEMA", "TRANSACTION"].include? payload[:name]
34-
end
35-
36-
result = _assert_nothing_raised_or_warn("assert_queries", &block)
37-
assert_equal num, count, "#{count} instead of #{num} queries were executed."
38-
result
39-
end
4029
end

activerecord/CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
* Make `assert_queries` and `assert_no_queries` assertions public.
2+
3+
To assert the expected number of queries are made, Rails internally uses
4+
`assert_queries` and `assert_no_queries`. These assertions can be now
5+
be used in applications as well.
6+
7+
```ruby
8+
class ArticleTest < ActiveSupport::TestCase
9+
test "queries are made" do
10+
assert_queries(1) { Article.first }
11+
end
12+
end
13+
```
14+
15+
*Petrik de Heus*
16+
117
* Fix `has_secure_token` calls the setter method on initialize.
218

319
*Abeid Ahmed*
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# frozen_string_literal: true
2+
3+
module ActiveRecord
4+
module Assertions
5+
module QueryAssertions
6+
def assert_queries(expected_count, matcher: nil, &block)
7+
ActiveRecord::Base.connection.materialize_transactions
8+
9+
queries = []
10+
ActiveSupport::Notifications.subscribe("sql.active_record") do |*, payload|
11+
queries << payload[:sql] if %w[ SCHEMA TRANSACTION ].exclude?(payload[:name]) && (matcher.nil? || payload[:sql].match(matcher))
12+
end
13+
14+
result = _assert_nothing_raised_or_warn("assert_queries", &block)
15+
assert_equal expected_count, queries.size, "#{queries.size} instead of #{expected_count} queries were executed. Queries: #{queries.join("\n\n")}"
16+
result
17+
end
18+
19+
def assert_no_queries(&block)
20+
assert_queries(0, &block)
21+
end
22+
end
23+
end
24+
end
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# frozen_string_literal: true
2+
3+
require "cases/helper"
4+
require "models/post"
5+
require "active_record/testing/query_assertions"
6+
7+
module ActiveRecord
8+
module Assertions
9+
class QueryAssertionsTest < ActiveSupport::TestCase
10+
include QueryAssertions
11+
12+
def test_assert_queries
13+
assert_queries(1) { Post.first }
14+
15+
error = assert_raises(Minitest::Assertion) {
16+
assert_queries(2) { Post.first }
17+
}
18+
assert_match(/1 instead of 2 queries/, error.message)
19+
20+
error = assert_raises(Minitest::Assertion) {
21+
assert_queries(0) { Post.first }
22+
}
23+
assert_match(/1 instead of 0 queries/, error.message)
24+
end
25+
end
26+
27+
def test_assert_no_queries
28+
assert_no_queries { Post.none }
29+
30+
error = assert_raises(Minitest::Assertion) {
31+
assert_no_queries { Post.first }
32+
}
33+
assert_match(/1 .* instead of 2/, error.message)
34+
end
35+
end
36+
end

activestorage/test/test_helper.rb

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
require "active_support/testing/autorun"
1313
require "image_processing/mini_magick"
1414

15+
require "active_record/testing/query_assertions"
16+
1517
require "active_job"
1618
ActiveJob::Base.queue_adapter = :test
1719
ActiveJob::Base.logger = ActiveSupport::Logger.new(nil)
@@ -24,6 +26,7 @@ class ActiveSupport::TestCase
2426
self.file_fixture_path = ActiveStorage::FixtureSet.file_fixture_path
2527

2628
include ActiveRecord::TestFixtures
29+
include ActiveRecord::Assertions::QueryAssertions
2730

2831
self.fixture_paths = [File.expand_path("fixtures", __dir__)]
2932

@@ -35,23 +38,6 @@ class ActiveSupport::TestCase
3538
ActiveStorage::Current.reset
3639
end
3740

38-
def assert_queries(expected_count, matcher: nil, &block)
39-
ActiveRecord::Base.connection.materialize_transactions
40-
41-
queries = []
42-
ActiveSupport::Notifications.subscribe("sql.active_record") do |*, payload|
43-
queries << payload[:sql] if %w[ SCHEMA TRANSACTION ].exclude?(payload[:name]) && (matcher.nil? || payload[:sql].match(matcher))
44-
end
45-
46-
result = _assert_nothing_raised_or_warn("assert_queries", &block)
47-
assert_equal expected_count, queries.size, "#{queries.size} instead of #{expected_count} queries were executed. Queries: #{queries.join("\n\n")}"
48-
result
49-
end
50-
51-
def assert_no_queries(&block)
52-
assert_queries(0, &block)
53-
end
54-
5541
private
5642
def create_blob(key: nil, data: "Hello world!", filename: "hello.txt", content_type: "text/plain", identify: true, service_name: nil, record: nil)
5743
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

railties/lib/rails/test_help.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,16 @@
1111
require "action_controller/test_case"
1212
require "action_dispatch/testing/integration"
1313
require "rails/generators/test_case"
14-
1514
require "active_support/testing/autorun"
1615

1716
require "rails/testing/maintain_test_schema"
1817

1918
if defined?(ActiveRecord::Base)
19+
require "active_record/testing/query_assertions"
2020
ActiveSupport.on_load(:active_support_test_case) do
2121
include ActiveRecord::TestDatabases
2222
include ActiveRecord::TestFixtures
23+
include ActiveRecord::Assertions::QueryAssertions
2324

2425
self.fixture_paths << "#{Rails.root}/test/fixtures/"
2526
self.file_fixture_path = "#{Rails.root}/test/fixtures/files"

0 commit comments

Comments
 (0)