Tuesday, April 07, 2009

assert_equal_float : assert_equal between two float objects with precision

In doing rails unit testing, sometime you need to assert the equality between two float objects in the following fashion

assert_equal 32.8, object_under_test.method_returning_float

The internal storage of float objects sometimes will contain 32.8 with additional lower precision decimal points and hence the assert may fail although the significant digits may be same. For example, the value of object_under_test.method_returning_float may be stored as 32.80000001 in memory and the above call may fail.

To solve this problem, you may wish to use the round method of Float class in the following way

assert_equal 32.8, object_under_test.method_returning_float.round(1)

The above line will evaluate true since it will round up to one decimal points. However, be careful about cases where you may have a value greater than 5 in the second decimal place! because (32.86).to_f.round(1) will become 32.9!

However, when you are talking about insignificant digits, this rounding should work fine for you.

Next step is to define a new assert_equal_float method that takes the precision as an argument. Adding this method will save you from code duplication and will improve readability.

def assert_equal_float(expected, actual, precision)
assert_equal expected.to_f.round(precision), actual.to_f.round(precision)
end

Happy float asserting!