class RSpec::Benchmark::ComparisonMatcher::Matcher

Implements the `perform_faster_than` and `perform_slower_than` matchers

@api private

Public Class Methods

new(expected, comparison_type, **options) click to toggle source
# File lib/rspec/benchmark/comparison_matcher.rb, line 12
def initialize(expected, comparison_type, **options)
  check_comparison(comparison_type)
  @expected = expected
  @comparison_type = comparison_type
  @count      = 1
  @count_type = :at_least
  @time       = options.fetch(:time) { 0.2 }
  @warmup     = options.fetch(:warmup) { 0.1 }
  @bench      = ::Benchmark::Perf::Iteration
end

Public Instance Methods

at_least(n) click to toggle source

Specify the minimum number of times a block is faster/slower than other. @api public

# File lib/rspec/benchmark/comparison_matcher.rb, line 83
def at_least(n)
  set_expected_times_count(:at_least, n)
  self
end
at_most(n) click to toggle source

Specify the maximum number of times a block is faster/slower than another. @api public

# File lib/rspec/benchmark/comparison_matcher.rb, line 91
def at_most(n)
  set_expected_times_count(:at_most, n)
  self
end
description() click to toggle source

@api private

# File lib/rspec/benchmark/comparison_matcher.rb, line 141
def description
  if @count == 1
    "perform #{@comparison_type} than comparison block"
  else
    "perform #{@comparison_type} than comparison block " \
    "by #{@count_type} #{@count} times"
  end
end
exactly(n) click to toggle source

Specify exact number of times a block is faster/slower than another. @api public

# File lib/rspec/benchmark/comparison_matcher.rb, line 99
def exactly(n)
  set_expected_times_count(:exactly, n)
  self
end
failure_message() click to toggle source

@api private

# File lib/rspec/benchmark/comparison_matcher.rb, line 131
def failure_message
  "expected given block to #{description}, but #{failure_reason}"
end
failure_message_when_negated() click to toggle source

@api private

# File lib/rspec/benchmark/comparison_matcher.rb, line 136
def failure_message_when_negated
  "expected given block not to #{description}, but #{failure_reason}"
end
failure_reason() click to toggle source

@api private

# File lib/rspec/benchmark/comparison_matcher.rb, line 151
def failure_reason
  return "was not a block" unless @actual.is_a?(Proc)

  if @ratio < 1
    "performed slower by #{format("%.2f", (@ratio**-1))} times"
  elsif @ratio > 1
    "performed faster by #{format("%.2f", @ratio)} times"
  else
    "performed by the same time"
  end
end
matcher_name() click to toggle source
# File lib/rspec/benchmark/comparison_matcher.rb, line 32
def matcher_name
  "perform_#{@comparison_type}_than"
end
matches?(block) click to toggle source

@return [Boolean]

@api private

# File lib/rspec/benchmark/comparison_matcher.rb, line 39
def matches?(block)
  @actual = block
  return false unless @actual.is_a?(Proc)

  @expected_ips, @expected_stdev, = @bench.run(time: @time, warmup: @warmup, &@expected)
  @actual_ips, @actual_stdev, = @bench.run(time: @time, warmup: @warmup, &@actual)

  @ratio = @actual_ips / @expected_ips.to_f

  case @count_type
  when :at_most
    at_most_comparison
  when :exactly
    exact_comparison
  else
    default_comparison
  end
end
once() click to toggle source

Specify that the code runs faster/slower exactly once. @api public

# File lib/rspec/benchmark/comparison_matcher.rb, line 106
def once
  exactly(1)
  self
end
supports_block_expectations?() click to toggle source

Indicates this matcher matches against a block

@return [True]

@api private

# File lib/rspec/benchmark/comparison_matcher.rb, line 28
def supports_block_expectations?
  true
end
thrice() click to toggle source

Specify that the code runs faster/slower exactly thrice. @api public

# File lib/rspec/benchmark/comparison_matcher.rb, line 119
def thrice
  exactly(3)
  self
end
times() click to toggle source

No-op, syntactic sugar. @api public

# File lib/rspec/benchmark/comparison_matcher.rb, line 126
def times
  self
end
twice() click to toggle source

Specify that the code runs faster/slower exactly twice.

# File lib/rspec/benchmark/comparison_matcher.rb, line 112
def twice
  exactly(2)
  self
end
warmup(value) click to toggle source

The time before measurements are taken

@param [Numeric] value

the time before measurements are taken

@api public

# File lib/rspec/benchmark/comparison_matcher.rb, line 64
def warmup(value)
  @warmup = value
  self
end
within(value) click to toggle source

Time to measure iteration for

@param [Numeric] value

the time to take measurements for

@api public

# File lib/rspec/benchmark/comparison_matcher.rb, line 75
def within(value)
  @time = value
  self
end

Private Instance Methods

at_most_comparison() click to toggle source

At most comparison

@example

@ratio = 3
@count = 4
perform_faster_than { ... }.at_most(@count).times # => true

@ratio = 3
@count = 2
perform_faster_than { ... }.at_most(@count).times # => false

@ratio = 1/4
@count = 5
perform_slower_than { ... }.at_most(@count).times # => true

@ratio = 1/4
@count = 3
perform_slower_than { ... }.at_most(@count).times # => false

@return [Boolean]

@api private

# File lib/rspec/benchmark/comparison_matcher.rb, line 204
def at_most_comparison
  if @comparison_type == :faster
    1 < @ratio && @ratio < @count
  else
    @count**-1 < @ratio && @ratio < 1
  end
end
check_comparison(type) click to toggle source
# File lib/rspec/benchmark/comparison_matcher.rb, line 265
def check_comparison(type)
  [:slower, :faster].include?(type) ||
    (raise ArgumentError, "comparison_type must be " \
           ":faster or :slower, not `:#{type}`")
end
convert_count(n) click to toggle source
# File lib/rspec/benchmark/comparison_matcher.rb, line 165
def convert_count(n)
  case n
  when Numeric then n
  when :once then 1
  when :twice then 2
  when :thrice then 3
  else
    raise "The #{matcher_name} matcher is not designed to be used " \
          "with #{n} count type."
  end
end
default_comparison() click to toggle source

At least comparison, meaning more than expected count

@example

@ratio = 4
@count = 3
perform_faster_than { ... } # => true

@ratio = 4
@count = 3
perform_faster_than { ... }.at_least(@count).times # => true

@ratio = 1/4
@count = 3
perform_slower_than { ... }.at_least(@count).times # => false

@ratio = 1/3
@count = 4
perform_slower_than { ... }.at_least(@count).times # => true

@return [Boolean]

@api private

# File lib/rspec/benchmark/comparison_matcher.rb, line 257
def default_comparison
  if @comparison_type == :faster
    @ratio > @count
  else
    @ratio < (1.0 / @count)
  end
end
exact_comparison() click to toggle source

Check if expected ips is faster/slower than actual ips exactly number of counts.

@example

@ratio = 3.5
@count = 3
perform_faster_than { ... }.exact(@count).times # => true

@ratio = 1/4
@count = 4
perform_slower_than { ... }.exact(@count).times # => true

@return [Boolean]

@api private

# File lib/rspec/benchmark/comparison_matcher.rb, line 227
def exact_comparison
  if @comparison_type == :faster
    @count == @ratio.round
  else
    @count == (1.0 / @ratio).round
  end
end
set_expected_times_count(type, n) click to toggle source
# File lib/rspec/benchmark/comparison_matcher.rb, line 177
def set_expected_times_count(type, n)
  @count_type = type
  @count = convert_count(n)
end