# Copy/paste of koans assert code
#----------------------------------------------------
FailedAssertionError = Class.new(StandardError)
def flunk(msg)
raise FailedAssertionError, msg
end
def assert(condition, msg=nil)
msg ||= "Failed assertion."
flunk(msg) unless condition
true
end
def assert_not_equal(expected, actual, msg=nil)
msg ||= "Expected #{expected.inspect} to not equal #{actual.inspect}"
assert(expected != actual, msg)
end
#----------------------------------------------------
# so for this let's say that you're not modeling dice, you're moding something that returns a randomized set of N
# values for an array, and it's normalized, from [0.0 to 1.0] in value
# This set always returns [0,0,0,0,...]
class FalsePositiveDiceSet
attr_reader :values
def roll(numberToRoll)
#oops, I meant to type rand(1.0)
@values = Array.new(numberToRoll){Random.rand(1)}
end
end
# This set returns something like [0.12870590894540357, 0.1339125315088633, 0.256765300105959, ...]
class TruePositiveDiceSet
attr_reader :values
def roll(numberToRoll)
@values = Array.new(numberToRoll){Random.rand(1.0)}
end
end
class TrueNegativeDiceSet
attr_reader :values
def initialize()
@values = [0.0, 0.0, 0.0]
end
def roll(numberToRoll)
#whoops, I forgot to roll
end
end
# false negative implementation
class SingleDiceArrayGoodSet
attr_reader :values
# Alternative, but still technically valid implementation of the same class.
# If you knew you only wanted to have one set of dice at a time, per class,
# you could store the array in a field, and just return the same array every time,
# though I generally wouldn't recommend this unless you have a good reason to, it's weirder to use.
def initialize()
@values = []
end
def roll(numberToRoll)
@values.clear
numberToRoll.times{@values << Random.rand(1.0)}
end
end
# test code
#----------------------------------------------------
def TestDiceObject(dice)
dice.roll(3)
first_time = dice.values
puts("First roll is #{dice.values}")
dice.roll(3)
puts("Second roll is #{dice.values}")
# NOTE: for SingleDiceArrayGoodSet, since it's the same array first_time and second_time are the same array.
second_time = dice.values
# breaking up the statement into parts
left = [first_time, first_time.object_id]
right = [second_time, second_time.object_id]
puts("first time side of assert is #{left.inspect}")
puts("second time side of assert is #{right.inspect}")
assert_statement = (left != right)
puts("Assert statement is: #{assert_statement}")
puts("first_time and second_time object_ids do not match: #{first_time.object_id != second_time.object_id}")
begin
assert_not_equal [first_time, first_time.object_id], [second_time, second_time.object_id], "Two rolls should not be equal"
rescue FailedAssertionError => ex
puts("[NOT OK] This dice set was detected as bad by the unit tests. Assert tripped with error: #{ex.to_s}")
else
puts("[OK] The unit tests think this dice set is good!")
end
end
puts("True positive dice set:")
puts("-------------------------------------------------------------------------------")
TestDiceObject(TruePositiveDiceSet.new)
puts
puts("True negative dice set:")
puts("-------------------------------------------------------------------------------")
TestDiceObject(TrueNegativeDiceSet.new)
puts
puts("False positive dice set:")
puts("-------------------------------------------------------------------------------")
puts
TestDiceObject(FalsePositiveDiceSet.new)
puts
puts("False Negative SingleDiceArrayGoodSet dice set:")
puts("-------------------------------------------------------------------------------")
puts
TestDiceObject(SingleDiceArrayGoodSet.new)
# So as other answers have mentioned, it would be pretty hard to test for this kind of error.
# I'd personally run through the program and read its "random" values for a quick check to make sure something like this didn't happen.