Assert_equal says <0.15> expected, but was <0.15>, but only if the method calculates 0.15 in a certain way

So, for this model method:

 def tax_rate tax_rate = 0.0 tax_rate += STATE_TAX if state_taxable? #STATE_TAX = 0.1 tax_rate += IMPORT_TAX if imported? #IMPORT_TAX = 0.05 tax_rate end 

This test fails:

 @item.update_attributes({:state_taxable => true, :imported => true, :price => 32.19}) assert_equal 0.15, @item.tax_rate 

I get this error:

 <0.15> expected but was <0.15>. 

However, this test will pass:

 @item.update_attributes({:state_taxable => true, :imported => false, :price => 14.99}) assert_equal 0.1, @item.tax_rate 

So, I get an error when tax_rate does 0.0 + 0.1 + 0.05, but not when 0.0 + 0.1, or 0.0 + 0.05. Both 0.15s are Float, so I don't see what could be causing this. I have been thinking about this for too long, I hope someone can indicate what kind of a criminal this is. Thanks in advance guys.

+4
source share
4 answers

IMHO, you should store things like integers (in cents).

+3
source

Floating point numbers cannot be represented exactly; you need to use assert_in_delta to verify that you are within the specified range.

Something like assert_in_delta 0.15, @item.tax_rate, 0.001 should do this: it will verify that you are within 0.001 of the expected value.

+9
source

I have had this error many times, and that is because they were different classes .

Try

 assert_equal 0.15.class, @item.tax_rate.class 

And I'm sure he will say something like

 <float> expected but was <double>. 

If you do

 assert_equal 0.15.to_float, @item.tax_rate.to_float 

He will probably pass

+1
source

0.1 , as well as other numbers, cannot be represented exactly in floating point arithmetic. Therefore, you should use something like (I'm not a guy from Ruby):

 assert_true abs(0.15 - @item.tax_rate) < 0.0001 

And in general, in fact, you should not use float for money / currency: there are many really unpleasant subtle problems that will lose money between cracks. See this question .

0
source

All Articles