lib/rspec/benchmark/matchers.rb
# frozen_string_literal: true
require_relative "allocation_matcher"
require_relative "comparison_matcher"
require_relative "complexity_matcher"
require_relative "iteration_matcher"
require_relative "timing_matcher"
module RSpec
module Benchmark
# Provides a number of useful performance testing expectations
#
# These matchers can be exposed by including the this module in
# a spec:
#
# RSpec.describe "Performance testing" do
# include RSpec::Benchmark::Matchers
# end
#
# or you can include in globablly in a spec_helper.rb file:
#
# RSpec.configure do |config|
# config.include(RSpec::Benchmark::Matchers)
# end
#
# @api public
module Matchers
# Passes if code block performs at least iterations
#
# @param [Integer] iterations
#
# @example
# expect { ... }.to perform_allocation(10000)
# expect { ... }.to perform_allocation(10000)
#
# @api public
def perform_allocation(objects, **options)
AllocationMatcher::Matcher.new(objects, **options)
end
# Passes if code block performs at least iterations
#
# @param [Integer] iterations
#
# @example
# expect { ... }.to perform_at_least(10000)
# expect { ... }.to perform_at_least(10000).ips
#
# @api public
def perform_at_least(iterations, **options)
IterationMatcher::Matcher.new(iterations, **options)
end
# Passes if code block performs under threshold
#
# @param [Float] threshold
#
# @example
# expect { ... }.to peform_under(0.001)
# expect { ... }.to peform_under(0.001).sec
# expect { ... }.to peform_under(10).ms
#
# @api public
def perform_under(threshold, **options)
TimingMatcher::Matcher.new(threshold, **options)
end
# Passes if code block performs faster than sample block
#
# @param [Proc] sample
#
# @example
# expect { ... }.to peform_faster_than { ... }
# expect { ... }.to peform_faster_than { ... }.at_least(5).times
#
# @api public
def perform_faster_than(**options, &sample)
ComparisonMatcher::Matcher.new(sample, :faster, **options)
end
# Passes if code block performs slower than sample block
#
# @param [Proc] sample
#
# @example
# expect { ... }.to peform_slower_than { ... }
# expect { ... }.to peform_slower_than { ... }.at_most(5).times
#
# @api public
def perform_slower_than(**options, &sample)
ComparisonMatcher::Matcher.new(sample, :slower, **options)
end
# Pass if code block performs constant
#
# @example
# expect { ... }.to perform_constant
# expect { ... }.to perform_constant.within(1, 100_000)
# expect { ... }.to perform_constant.within(1, 100_000, ratio: 4)
#
# @api public
def perform_constant(**options)
ComplexityMatcher::Matcher.new(:constant, **options)
end
# Pass if code block performs logarithmic
#
# @example
# expect { ... }.to perform_logarithmic
# expect { ... }.to perform_logarithmic
# expect { ... }.to perform_logarithmic.within(1, 100_000)
# expect { ... }.to perform_logarithimic.within(1, 100_000, ratio: 4)
#
# @api public
def perform_logarithmic(**options)
ComplexityMatcher::Matcher.new(:logarithmic, **options)
end
alias perform_log perform_logarithmic
# Pass if code block performs linear
#
# @example
# expect { ... }.to perform_linear
# expect { ... }.to perform_linear.within(1, 100_000)
# expect { ... }.to perform_linear.within(1, 100_000, ratio: 4)
#
# @api public
def perform_linear(**options)
ComplexityMatcher::Matcher.new(:linear, **options)
end
# Pass if code block performs power
#
# @example
# expect { ... }.to perform_power
# expect { ... }.to perform_power.within(1, 100_000)
# expect { ... }.to perform_power.within(1, 100_000, ratio: 4)
#
# @api public
def perform_power(**options)
ComplexityMatcher::Matcher.new(:power, **options)
end
# Pass if code block performs exponential
#
# @example
# expect { ... }.to perform_exponential
# expect { ... }.to perform_exponential.within(1, 100_000)
# expect { ... }.to perform_exponential.within(1, 100_000, ratio: 4)
#
# @api public
def perform_exponential(**options)
ComplexityMatcher::Matcher.new(:exponential, **options)
end
alias perform_exp perform_exponential
# Generate a geometric progression of inputs
#
# The default range is generated in the multiples of 8.
#
# @example
# bench_range(8, 8 << 10)
# # => [8, 64, 512, 4096, 8192]
#
# @param [Integer] start
# @param [Integer] limit
# @param [Integer] ratio
#
# @api public
def bench_range(*args)
::Benchmark::Trend.range(*args)
end
end # Matchers
end # Benchmark
end # RSpec