diff options
Diffstat (limited to 'spec/support/matchers/exceed_query_limit.rb')
-rw-r--r-- | spec/support/matchers/exceed_query_limit.rb | 101 |
1 files changed, 95 insertions, 6 deletions
diff --git a/spec/support/matchers/exceed_query_limit.rb b/spec/support/matchers/exceed_query_limit.rb index b9630b00038..cc0abfa0dd6 100644 --- a/spec/support/matchers/exceed_query_limit.rb +++ b/spec/support/matchers/exceed_query_limit.rb @@ -59,11 +59,15 @@ module ExceedQueryLimitHelpers def verify_count(&block) @subject_block = block - actual_count > expected_count + threshold + actual_count > maximum + end + + def maximum + expected_count + threshold end def failure_message - threshold_message = threshold > 0 ? " (+#{@threshold})" : '' + threshold_message = threshold > 0 ? " (+#{threshold})" : '' counts = "#{expected_count}#{threshold_message}" "Expected a maximum of #{counts} queries, got #{actual_count}:\n\n#{log_message}" end @@ -73,6 +77,55 @@ module ExceedQueryLimitHelpers end end +RSpec::Matchers.define :issue_fewer_queries_than do + supports_block_expectations + + include ExceedQueryLimitHelpers + + def control + block_arg + end + + def control_recorder + @control_recorder ||= ActiveRecord::QueryRecorder.new(&control) + end + + def expected_count + control_recorder.count + end + + def verify_count(&block) + @subject_block = block + + # These blocks need to be evaluated in an expected order, in case + # the events in expected affect the counts in actual + expected_count + actual_count + + actual_count < expected_count + end + + match do |block| + verify_count(&block) + end + + def failure_message + <<~MSG + Expected to issue fewer than #{expected_count} queries, but got #{actual_count} + + #{log_message} + MSG + end + + failure_message_when_negated do |actual| + <<~MSG + Expected query count of #{actual_count} to be less than #{expected_count} + + #{log_message} + MSG + end +end + RSpec::Matchers.define :issue_same_number_of_queries_as do supports_block_expectations @@ -82,30 +135,66 @@ RSpec::Matchers.define :issue_same_number_of_queries_as do block_arg end + chain :or_fewer do + @or_fewer = true + end + + chain :ignoring_cached_queries do + @skip_cached = true + end + def control_recorder @control_recorder ||= ActiveRecord::QueryRecorder.new(&control) end def expected_count - @expected_count ||= control_recorder.count + control_recorder.count end def verify_count(&block) @subject_block = block - (expected_count - actual_count).abs <= threshold + # These blocks need to be evaluated in an expected order, in case + # the events in expected affect the counts in actual + expected_count + actual_count + + if @or_fewer + actual_count <= expected_count + else + (expected_count - actual_count).abs <= threshold + end end match do |block| verify_count(&block) end + def failure_message + <<~MSG + Expected #{expected_count_message} queries, but got #{actual_count} + + #{log_message} + MSG + end + failure_message_when_negated do |actual| - failure_message + <<~MSG + Expected #{actual_count} not to equal #{expected_count_message} + + #{log_message} + MSG + end + + def expected_count_message + or_fewer_msg = "or fewer" if @or_fewer + threshold_msg = "(+/- #{threshold})" unless threshold.zero? + + ["#{expected_count}", or_fewer_msg, threshold_msg].compact.join(' ') end def skip_cached - false + @skip_cached || false end end |