4

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 the error when tax_rate does 0.0 + 0.1 + 0.05, but not when it does 0.0 + 0.1, or 0.0 + 0.05. Both 0.15s are Floats, so I don't see what could be causing this. I've spent too long mulling over this, hopefully someone can point out what the culprit is. Thanks in advance guys.

solidcell
  • 7,639
  • 4
  • 40
  • 59

4 Answers4

8

Floating-point numbers can't be represented exactly; what you need to do is use assert_in_delta to check you're within a specified range.

Something like assert_in_delta 0.15, @item.tax_rate, 0.001 should do it: it'll check you're within 0.001 of the expected value.

John Y
  • 1,161
  • 12
  • 23
3

IMHO, you should store such things as a integer numbers (in cents).

taro
  • 5,772
  • 2
  • 30
  • 34
1

I have had this error many times and it's been because they were different classes.

Try

assert_equal 0.15.class, @item.tax_rate.class

And I am sure it will say something like

<float> expected but was <double>.

If you do

assert_equal 0.15.to_float, @item.tax_rate.to_float

It'll probably pass

Jonas Söderström
  • 4,856
  • 2
  • 36
  • 45
0

0.1, along with other numbers, cannot be represented exactly in floating-point arithmetics. Hence, you should use something like (I'm no Ruby guy):

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

And generally speaking, you shouldn't really be using floats for money/currency: there are a lot of really nasty subtle issues that will lose money between the cracks. See this question.

Community
  • 1
  • 1
Anton Gogolev
  • 113,561
  • 39
  • 200
  • 288
  • But tax_rate is still returning 0.15, not 0.149999 or something similar, so why is it causing this problem? Any suggestions on a way I could do it? – solidcell Aug 16 '10 at 08:01
  • It may well be 0.14999999999999998 or 0.15000000000000002; those bits at the end get rounded off normally on display, but they're still there in the IEEE representation. Don't compare floating-point numbers (unless you **really** know what you're doing). – Donal Fellows Aug 16 '10 at 13:11