File: helper.rb

package info (click to toggle)
ruby-ffaker 2.23.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,776 kB
  • sloc: ruby: 12,788; makefile: 8; sh: 1
file content (87 lines) | stat: -rw-r--r-- 2,590 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# frozen_string_literal: true

require 'test/unit'
require 'ffaker'

# Helpers for checking if a method is deterministic -- e.g., that the Random
# results are repeatable given the same random seed.
module DeterministicHelper
  def self.included(base)
    base.extend ClassMethods
  end

  # Accepts a block. Executes the block multiple times after resetting
  # the internal Random Number Generator state and compared the results of
  # each execution to make sure they are the same.
  def assert_deterministic(options = {}, &block)
    raise ArgumentError, 'Must pass a block' unless block

    options = { message: 'Results are not repeatable' }.merge(options)

    returns = Array.new(2) do
      FFaker::Random.reset!
      Array.new(5, &block)
    end

    assert(returns.uniq.length == 1, options[:message])
  end

  %w[< > <= >=].each do |operator|
    operator_name =
      case operator[0]
      when '<' then 'less_than'
      when '>' then 'greater_than'
      else raise 'Unexpected operator'
      end
    operator_name += '_or_equal_to' if operator[1] == '='

    define_method "assert_#{operator_name}" do |got, expected|
      assert(
        got.public_send(operator, expected),
        "Expected #{operator} \"#{expected}\", but got #{got}"
      )
    end
  end

  def assert_between(got, range)
    assert_greater_than_or_equal_to got, range.begin
    public_send "assert_less_than#{'_or_equal_to' unless range.exclude_end?}", got, range.end
  end

  def assert_random(original_block, *args)
    100.times do
      yield(*args)
      assert_deterministic(&original_block)
    end
  end

  %w[less_than_or_equal_to between].each do |method_name|
    define_method "assert_random_#{method_name}" do |*args, &block|
      assert_random(block) { send "assert_#{method_name}", block.call, *args }
    end
  end

  # Methods to be called outside of individual examples.
  module ClassMethods
    # Shorthand method to quickly test the determinability of multiple methods.
    #
    #  assert_methods_are_deterministic(
    #    <faker module under test>,
    #    <method names to test, as array of symbols>
    #  )
    #
    #  assert_methods_are_deterministic(
    #    FFaker::SomeModule,
    #    :some_method, :some_other_method
    #  }
    def assert_methods_are_deterministic(klass, *methods)
      Array(methods).each do |meth|
        define_method "test_#{meth}_is_deterministic" do
          assert_deterministic(message: "Results from `#{klass}.#{meth}` are not repeatable") do
            klass.send(meth)
          end
        end
      end
    end
  end
end