Module: Test::Unit::Assertions
- Defined in:
- lib/assert_statistically.rb
Constant Summary collapse
- ASSERT_STATISTICALLY_DEFAULT_FAILURE_MESSAGE =
'The block returned false on iteration %d'
Instance Method Summary collapse
-
#assert_statistically(options = {}, &test_block) ⇒ Object
This is the main method of this library.
-
#can_short_circuit?(range, completed, total, successes, short_circuit = true) ⇒ Boolean
This method is used to determine whether we can short circuit and quit the iterations early.
Instance Method Details
#assert_statistically(options = {}, &test_block) ⇒ Object
This is the main method of this library. It takes a hash of options and a block. Based on the options, the block will be run some number of times, possibly zero. If the criteria are met, assert_statistically is in a passing state. If assert_statistically enters a passing state and determines that it can never leave, it will be default short_circuit and run no more iterations. You can override this behavior by passing :short_circuit => false in the options Hash. Other keys uses in the options Hash
:message => The message to report on failure. Takes a %d string format directive,
which is populated with the failing iteration number.
:of => The maximum number of times the test will be run (default = 1) :min => The minimum number of times the test needs to pass (default = 1) :max => The maximum number of times the test can pass (defaults to the value of of) :short_circuit => A flag determining whether to short circuit (defaults to true) :before => An optional Proc that will be called before each iteration :after => An optional Proc that will be called after each iteration
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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/assert_statistically.rb', line 42 def assert_statistically( ={}, &test_block ) # If options is not a Hash, make it a hash, assuming that options.to_s is the message = { :message => .to_s } unless .is_a?( Hash ) # The number of times to call the block; default is 1 of = [:of].to_i > 0 ? [:of].to_i : 1 # Set min ; default is 1 (when :min is not present) # Note that if you pass a :min <= 0, the assertion will always pass, # unless max is less than min # Note that :min => nil is the same as :min => 0 # Note that !defined( :min ) is the same as :min => 1 min = .has_key?( :min ) && [:min].respond_to?( :to_i ) ? [:min].to_i : 1 # Set max ; default is :of # Note that you can pass a :max > :of, in which case # :min will be the only determinant of success # (since you can't have more than :of succcesses in :of attempts) max = .has_key?( :max ) && [:max].respond_to?( :to_i ) ? [:max].to_i : of # Fail if min is greater than max raise AssertionFailedError.new( "Impossible range: [#{min}..#{max}]" ) if min > max # Set short_circuit ; default is true short_circuit = .has_key?( :short_circuit ) && ![:short_circuit] ? false : true # Create the range within which the number of successful runs must fall successful_range = Range.new( min, max ) # Set up the before and after blocks before = .has_key?( :before ) && [:before].respond_to?( :call ) ? [:before] : false after = .has_key?( :after ) && [:after].respond_to?( :call ) ? [:after] : false # Set up the failure message = [:message].to_s.empty? ? ASSERT_STATISTICALLY_DEFAULT_FAILURE_MESSAGE : [:message].to_s = '' successes = 0 1.upto( of ) do |i| # Check for short circuit eligibility (1 of 2) break if can_short_circuit?( successful_range, i - 1, of, successes, short_circuit ) # Call any before block before.call( i, successes ) if before # Call the test block if test_block.call( i, successes ) successes += 1 else << "#{ % i}\n" end # Check for short circuit eligibility (2 of 2) break if can_short_circuit?( successful_range, i, of, successes, short_circuit ) # Call any after block after.call( i, successes ) if after end # Fail if the number of successes is not in the successful range raise AssertionFailedError.new( ) unless successful_range.include?( successes ) # Pass true end |
#can_short_circuit?(range, completed, total, successes, short_circuit = true) ⇒ Boolean
This method is used to determine whether we can short circuit and quit the iterations early. It is called once before the “before” block (if any), and once before the “after” block (if any). This means that if we can short circuit after the test block is called, but before the after block is called, we will. I.E., the after block will not be invoked in such a case.
11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/assert_statistically.rb', line 11 def can_short_circuit?( range, completed, total, successes, short_circuit=true) short_circuit && #first, be sure we can short circuit ( # Are there enough successes, and is it impossible to get too many? ( range.include?( successes ) && range.include?( total - completed + successes ) ) || # Are there too many successes? successes > range.last || # Are there too few successes, and is it impossible to have enough? total - completed + successes < range.first ) end |