|
View:
New views
20 Messages
—
Rating Filter:
Alert me
|
| < Prev | 1 - 2 | Next > |
|
|
What is expected behavior on Assert.assertEquals on Number object?Hi, When i try to make an assertion on Number object, e.g. Double the result always assertion successful. Even i try to compare by org.junit.Assert.assertEquals(123456789.345, 123456789.34), it still success. (I'm expecting failure) I've consult with Eclipse team and they suggest me to ask for help on this place. Best regards, Nattapong Sirilappanich Engineer, National Language Development - GCoC & TSC Thailand Software Group, IBM Thailand Co., Ltd. National Phone: 02-273-4715, Fax: 02-619-2030 International Phone: +66 2 273 4715, Fax: +66 2 619 2030 e-mail: natta@... [Non-text portions of this message have been removed] |
|
|
Re: What is expected behavior on Assert.assertEquals on Number object?On Jun 3, 2008, at 22:41 , Nattapong Sirilappanich wrote: > > > Hi, > > When i try to make an assertion on Number object, e.g. Double the > result > always assertion successful. > Even i try to compare by org.junit.Assert.assertEquals(123456789.345, > 123456789.34), it still success. (I'm expecting failure) > public class DoubleTest { @Test public void unequalDoubleValueObjectsShouldBeUnequal() { Assert.assertFalse(new Double(3).equals(new Double(4))); Assert.assertFalse(new Double(3.1d).equals(new Double(3.2d))); Assert.assertFalse(new Double(123456789.345d).equals(new Double( 123456789.34d))); Assert.assertEquals(new Double(123456789.345d), new Double( 123456789.34d)); Assert.assertEquals(new Double(3.1d), new Double(3.2d)); Assert.assertEquals(new Double(3), new Double(4)); } } Only the last assertion fails. ---- J. B. (Joe) Rainsberger :: http://www.jbrains.ca Your guide to software craftsmanship JUnit Recipes: Practical Methods for Programmer Testing 2005 Gordon Pask Award for contributions to Agile Software Practice |
|
|
Re: What is expected behavior on Assert.assertEquals on Number object?Hi, I forgot to mention the version number of JUnit. I'm using JUnit 4.3.1 which is part of Eclipse 3.3.2 Best regards, Nattapong Sirilappanich Engineer, National Language Development - GCoC & TSC Thailand Software Group, IBM Thailand Co., Ltd. National Phone: 02-273-4715, Fax: 02-619-2030 International Phone: +66 2 273 4715, Fax: +66 2 619 2030 e-mail: natta@... "J. B. Rainsberger" <jbrains762@gmail To .com> junit@... Sent by: cc junit@yahoogroups Suwit .com Srivilairith/Thailand/IBM@IBMTH Subject Re: [junit] What is expected 04/06/2008 21:34 behavior on Assert.assertEquals on Number object? Please respond to junit@yahoogroups .com On Jun 3, 2008, at 22:41 , Nattapong Sirilappanich wrote: > > > Hi, > > When i try to make an assertion on Number object, e.g. Double the > result > always assertion successful. > Even i try to compare by org.junit.Assert.assertEquals(123456789.345, > 123456789.34), it still success. (I'm expecting failure) > Weird. assertEquals() appears only to compare the whole parts. public class DoubleTest { @Test public void unequalDoubleValueObjectsShouldBeUnequal() { Assert.assertFalse(new Double(3).equals(new Double(4))); Assert.assertFalse(new Double(3.1d).equals(new Double(3.2d))); Assert.assertFalse(new Double(123456789.345d).equals(new Double( 123456789.34d))); Assert.assertEquals(new Double(123456789.345d), new Double( 123456789.34d)); Assert.assertEquals(new Double(3.1d), new Double(3.2d)); Assert.assertEquals(new Double(3), new Double(4)); } } Only the last assertion fails. ---- J. B. (Joe) Rainsberger :: http://www.jbrains.ca Your guide to software craftsmanship JUnit Recipes: Practical Methods for Programmer Testing 2005 Gordon Pask Award for contributions to Agile Software Practice [Non-text portions of this message have been removed] |
|
|
Re: What is expected behavior on Assert.assertEquals on Number object?--- In junit@..., "J. B. Rainsberger" <jbrains762@...> wrote: On Jun 3, 2008, at 22:41 , Nattapong Sirilappanich wrote: Hi, When i try to make an assertion on Number object, e.g. Double the result always assertion successful. Even i try to compare by org.junit.Assert.assertEquals(123456789.345,123456789.34) it still success. (I'm expecting failure) This is not a good way to compare floating point numbers. You should actually use: Assert.assertEquals(expected, actual, delta) where expected and actual are as in the form you did use, but there is a third "delta" argument (also a double). This argument provides a tolerance value by which to judge "equality". basically the assertion fails if: Math.abs(expected - actual) > delta Thus, working from your failing example: Assert.assertEquals(123456789.345, 123456789.34, 0.5); // PASS Assert.assertEquals(123456789.345, 123456789.34, 0.0005); // FAIL By the way, this usage really makes the name of the method a misnomer. It should really be called "assertClose" (as in "close, but no cigar", not "close the door; it's cold"). But that should be okay if you are using double the way it is meant to be used, because, as the old saying goes, close only counts in horseshoes, hand grenades, and limited precision floating point operations. In other words, the idea is that after even a few operations (or even after none in some cases) it is unreasonable to expect floating point quantities to be exactly equal to their unlimited precision real number counterparts (even when an exact match exists). So you aim for "close" instead. "How close can you get" is itself a black art that combines roughly equal portions of operation counting, number magnitude tracking, operation order tracking, and wild-ass guessing. Now back to the problem at hand. Just for grins I compiled Nattapong's original assert under a J2SE 1.4 compiler and it gave a syntax error, saying that essentially that the third double argument was missing. It appears that this is one of those rare-but-not-rare-enough cases when autoboxing is actually working against you. And now J.B.'s response... Weird. assertEquals() appears only to compare the whole parts. public class DoubleTest { @Test public void unequalDoubleValueObjectsShouldBeUnequal() { Assert.assertFalse(new Double(3).equals(new Double(4))); Assert.assertFalse(new Double(3.1d).equals(new Double(3.2d))); Assert.assertFalse(new Double(123456789.345d).equals(new Double(123456789.34d))); So far so good... Assert.assertEquals(new Double(123456789.345d), new Double(123456789.34d)); When compiled under J2SE 1.4 the above assertEquals() fails. So, once again, I suspect autoboxing is the culprit. In this case I suspect the Doubles are being "unboxed" into longs, since there is a two-long assertEquals() but not a two-double assertEquals(). Assert.assertEquals(new Double(3.1d), new Double(3.2d)); Same with the above. Assert.assertEquals(new Double(3), new Double(4)); Same with the above, but if I am right this one fails (as J.B. noted) because the integral parts are different, so you get different longs. } } Only the last assertion fails. This behavior makes me wonder if in Nattapong's original case the primitive doubles are being boxed into object Doubles which are, in turn, being unboxed into primitive longs. If that is not what is happening, something even stranger is going on. Either way, I don't like it. -- Roger Glover Object Partners, Inc. [Non-text portions of this message have been removed] |
|
|
Re: What is expected behavior on Assert.assertEquals on Number object?Sorry about how hosed my last message looked. I used the new "Rich
Text Editor (Beta)", which apparently did not play nicely with whatever the moderator was using to review messages and push them through to the group. Here it is again, hopefully in a better format. --- In junit@..., "J. B. Rainsberger" <jbrains762@> wrote: > On Jun 3, 2008, at 22:41 , Nattapong Sirilappanich wrote: > > Hi, > > > > When i try to make an assertion on Number object, e.g. > > Double the result always assertion successful. Even i try > > to compare by > > > > org.junit.Assert.assertEquals(123456789.345,123456789.34) > > > > it still success. (I'm expecting failure) This is not a good way to compare floating point numbers. You should actually use: Assert.assertEquals(expected, actual, delta) where "expected" and "actual" are as in the form you did use, but there is a third "delta" argument (also a double). This argument provides a tolerance value by which to judge "equality". Basically the assertion fails if: Math.abs(expected - actual) > delta Thus, working from your failing example and adding the "delta" argument: Assert.assertEquals(123456789.345, 123456789.34, 0.5); // PASS Assert.assertEquals(123456789.345, 123456789.34, 0.0005); // FAIL By the way, this usage really makes the name of the method a misnomer. It should really be called "assertClose()" (as in "close, but no cigar", not as in "close the door; it's cold"). But that should be okay if you are using double the way it is meant to be used, because, as the old saying goes, "close" only counts in horseshoes, hand grenades, and limited precision floating point operations. In other words, the idea is that after even a few operations (or even after no operations in some cases) it is unreasonable to expect floating point quantities to be exactly equal to their unlimited precision real number counterparts (even when an exact match exists). So you aim for "close" instead. "How close can you get" is itself a black art that combines roughly equal portions of operation counting, number magnitude tracking, operation order tracking, and wild-ass guessing. Now back to the problem at hand. Just for grins I compiled Nattapong's original assert under a J2SE 1.4 compiler and it gave a syntax error, saying that essentially that the third double argument was missing. It appears that this is one of those rare-but-not-rare-enough cases when autoboxing is actually working against you. And now J.B.'s response... > Weird. assertEquals() appears only to compare the whole parts. > > public class DoubleTest { > @Test > public void unequalDoubleValueObjectsShouldBeUnequal() { > Assert.assertFalse(new Double(3).equals(new Double(4))); > Assert.assertFalse(new Double(3.1d).equals(new Double(3.2d))); > Assert.assertFalse(new Double(123456789.345d).equals( > new Double(123456789.34d))); So far so good... > Assert.assertEquals(new Double(123456789.345d), > new Double(123456789.34d)); When compiled under J2SE 1.4 the above "assertEquals()" fails. So, once again, I suspect autoboxing is the culprit. In this case I suspect the Doubles are being "unboxed" into longs, since there is a two-long "assertEquals()" method but not a two-double "assertEquals()" method. > Assert.assertEquals(new Double(3.1d), new Double(3.2d)); Same as with the above. > Assert.assertEquals(new Double(3), new Double(4)); Same as with the above, but if I am right this one fails (as J.B. noted) because the integral parts are different, so you get different longs. > } > } > > Only the last assertion fails. This behavior makes me wonder anew about in Nattapong's original case. My best guess is that the primitive doubles are being boxed into object Doubles which are, in turn, being unboxed into primitive longs (to match the two-long overload). Strange but perhaps true. If that is not what is happening, something *even stranger* is going on. Either way, I don't particularly like it. But, truth to tell you really should be using the three-double overload of the "assertEquals()" method. Then you would not be having this problem. -- Roger Glover Object Partners, Inc. |
|
|
Re: Re: What is expected behavior on Assert.assertEquals on Number object?Actually, my point here is i'm expecting org.junit.Assert.assertEquals(Object obj1, Object obj2) to call its obj1.equals(obj2) or something like this. However, the outcome surprise me. Assertion success but obj1.equals(obj2) return false. What's going on inside assertEquals() operation? Is this what it's suppose to be? Best regards, Nattapong Sirilappanich Engineer, National Language Development - GCoC & TSC Thailand Software Group, IBM Thailand Co., Ltd. National Phone: 02-273-4715, Fax: 02-619-2030 International Phone: +66 2 273 4715, Fax: +66 2 619 2030 e-mail: natta@... "Roger Glover" <glover_roger@yah oo.com> To Sent by: junit@... junit@yahoogroups cc .com Subject [junit] Re: What is expected 06/06/2008 01:43 behavior on Assert.assertEquals on Number object? Please respond to junit@yahoogroups .com --- In junit@..., "J. B. Rainsberger" <jbrains762@...> wrote: On Jun 3, 2008, at 22:41 , Nattapong Sirilappanich wrote: Hi, When i try to make an assertion on Number object, e.g. Double the result always assertion successful. Even i try to compare by org.junit.Assert.assertEquals(123456789.345,123456789.34) it still success. (I'm expecting failure) This is not a good way to compare floating point numbers. You should actually use: Assert.assertEquals(expected, actual, delta) where expected and actual are as in the form you did use, but there is a third "delta" argument (also a double). This argument provides a tolerance value by which to judge "equality". basically the assertion fails if: Math.abs(expected - actual) > delta Thus, working from your failing example: Assert.assertEquals(123456789.345, 123456789.34, 0.5); // PASS Assert.assertEquals(123456789.345, 123456789.34, 0.0005); // FAIL By the way, this usage really makes the name of the method a misnomer. It should really be called "assertClose" (as in "close, but no cigar", not "close the door; it's cold"). But that should be okay if you are using double the way it is meant to be used, because, as the old saying goes, close only counts in horseshoes, hand grenades, and limited precision floating point operations. In other words, the idea is that after even a few operations (or even after none in some cases) it is unreasonable to expect floating point quantities to be exactly equal to their unlimited precision real number counterparts (even when an exact match exists). So you aim for "close" instead. "How close can you get" is itself a black art that combines roughly equal portions of operation counting, number magnitude tracking, operation order tracking, and wild-ass guessing. Now back to the problem at hand. Just for grins I compiled Nattapong's original assert under a J2SE 1.4 compiler and it gave a syntax error, saying that essentially that the third double argument was missing. It appears that this is one of those rare-but-not-rare-enough cases when autoboxing is actually working against you. And now J.B.'s response... Weird. assertEquals() appears only to compare the whole parts. public class DoubleTest { @Test public void unequalDoubleValueObjectsShouldBeUnequal() { Assert.assertFalse(new Double(3).equals(new Double(4))); Assert.assertFalse(new Double(3.1d).equals(new Double(3.2d))); Assert.assertFalse(new Double(123456789.345d).equals(new Double(123456789.34d))); So far so good... Assert.assertEquals(new Double(123456789.345d), new Double(123456789.34d)); When compiled under J2SE 1.4 the above assertEquals() fails. So, once again, I suspect autoboxing is the culprit. In this case I suspect the Doubles are being "unboxed" into longs, since there is a two-long assertEquals() but not a two-double assertEquals(). Assert.assertEquals(new Double(3.1d), new Double(3.2d)); Same with the above. Assert.assertEquals(new Double(3), new Double(4)); Same with the above, but if I am right this one fails (as J.B. noted) because the integral parts are different, so you get different longs. } } Only the last assertion fails. This behavior makes me wonder if in Nattapong's original case the primitive doubles are being boxed into object Doubles which are, in turn, being unboxed into primitive longs. If that is not what is happening, something even stranger is going on. Either way, I don't like it. -- Roger Glover Object Partners, Inc. [Non-text portions of this message have been removed] [Non-text portions of this message have been removed] |
|
|
Re: What is expected behavior on Assert.assertEquals on Number object?--- In junit@..., Nattapong Sirilappanich <natta@...> wrote:
> Actually, my point here is i'm expecting > org.junit.Assert.assertEquals(Object obj1, Object obj2) to call > its obj1.equals(obj2) or something like this. However, the > outcome surprise me. Assertion success but obj1.equals(obj2) > return false. > > What's going on inside assertEquals() operation? Is this what > it's suppose to be? As I stated, albeit not very clearly the first time (Curse you "Rich Text Editor(Beta)"!), I suspect that the culprit here is that "Assert.assertEquals(Object, Object)" is not being called at all. This is borne out by the fact that a J2SE 1.4 compiler and a JavaSE 1.5 compiler treat the same call completely differently. I *SUSPECT* that the 1.5 compiler is unboxing the Double objects into primitive longs and that the method that is *ACTUALLY* called is "Assert.assertEquals(long,long)". This accounts for the behavior since the integer parts of your two numbers are the same. "Assert.assertEquals(long,long)" yields is successful after the Doubles are converted (truncated) to longs. -- Roger Glover Object Partners, Inc. |
|
|
Re: Re: What is expected behavior on Assert.assertEquals on Number object?On 2008-06-06, at 08:45 , Roger Glover wrote:
> --- In junit@..., Nattapong Sirilappanich <natta@...> > wrote: > > Actually, my point here is i'm expecting > > org.junit.Assert.assertEquals(Object obj1, Object obj2) to call > > its obj1.equals(obj2) or something like this. However, the > > outcome surprise me. Assertion success but obj1.equals(obj2) > > return false. > > > > What's going on inside assertEquals() operation? Is this what > > it's suppose to be? > > As I stated, albeit not very clearly the first time (Curse you "Rich > Text Editor(Beta)"!), I suspect that the culprit here is that > "Assert.assertEquals(Object, Object)" is not being called at all. This > is borne out by the fact that a J2SE 1.4 compiler and a JavaSE 1.5 > compiler treat the same call completely differently. > > I *SUSPECT* that the 1.5 compiler is unboxing the Double objects into > primitive longs and that the method that is *ACTUALLY* called is > "Assert.assertEquals(long,long)". This accounts for the behavior since > the integer parts of your two numbers are the same. > "Assert.assertEquals(long,long)" yields is successful after the > Doubles are converted (truncated) to longs. > ask the question, what's the better answer? Defeat the purpose of assertEquals(Object,Object) or letting programmers hoist themselves on their own petards? JUnit could detect this situation, but if it did, I'd prefer it to warn the programmer rather than fix the problem, because I want to encourage programmers to improve their design: either the test should compare the Double values with a tolerance, or perhaps the production code ought not to use Doubles. Take care. ---- J. B. (Joe) Rainsberger :: http://www.jbrains.ca Your guide to software craftsmanship JUnit Recipes: Practical Methods for Programmer Testing 2005 Gordon Pask Award for contributions to Agile Software Practice |
|
|
Re: What is expected behavior on Assert.assertEquals on Number object?--- In junit@..., "J. B. Rainsberger" <jbrains762@...> wrote:
> > On 2008-06-06, at 08:45 , Roger Glover wrote: > > --- In junit@..., Nattapong Sirilappanich <natta@> > > wrote: > > > Actually, my point here is i'm expecting > > > org.junit.Assert.assertEquals(Object obj1, Object obj2) to > > > call its obj1.equals(obj2) or something like this. However, > > > the outcome surprise me. Assertion success but > > > obj1.equals(obj2) return false. > > > > > > What's going on inside assertEquals() operation? Is this > > > what it's suppose to be? > > > > As I stated, albeit not very clearly the first time (Curse you > > "Rich Text Editor(Beta)"!), I suspect that the culprit here is > > that "Assert.assertEquals(Object, Object)" is not being called > > at all. This is borne out by the fact that a J2SE 1.4 compiler > > and a JavaSE 1.5 compiler treat the same call completely > > differently. > > > > I *SUSPECT* that the 1.5 compiler is unboxing the Double > > objects into primitive longs and that the method that is > > *ACTUALLY* called is "Assert.assertEquals(long,long)". This > > accounts for the behavior since the integer parts of your two > > numbers are the same. "Assert.assertEquals(long,long)" yields > > successful after the Doubles are converted (truncated) to > > longs. > > > That's almost certainly what is happening, and good deduction. Thank you very much! > Now we ask the question, what's the better answer? Defeat the > purpose of assertEquals(Object,Object) or letting programmers > hoist themselves on their own petards? > > JUnit could detect this situation, but if it did, I'd prefer > it to warn the programmer rather than fix the problem, because > I want to encourage programmers to improve their design: > either the test should compare the Double values with a > tolerance, or perhaps the production code ought not to use > Doubles. Well if that is the best solution (and I must say that I like it better than the status quo) then the easiest way to do that would probably be to create a bogus "Assert.assertEquals(double,double)" that: A) is deprecated (Yes, I mean it. A new method that is deprecated and with no intent ever to remove it). The javadoc should point to the 3-double overload as the preferred alternative and explain why. *AND* B) is implemented to unconditionally throw "UnsupportedOperationException" (or similar unchecked standard exception) with a message that indicates that you should use the 3-double overload instead. -- Roger Glover Object Partners, Inc. |
|
|
Re: What is expected behavior on Assert.assertEquals on Number object?--- In junit@..., "Roger Glover" <glover_roger@...>
wrote: > > --- In junit@..., "J. B. Rainsberger" <jbrains762@> wrote: > > > > On 2008-06-06, at 08:45 , Roger Glover wrote: > > > --- In junit@..., Nattapong Sirilappanich <natta@> > > > wrote: > > > > Actually, my point here is i'm expecting > > > > org.junit.Assert.assertEquals(Object obj1, Object obj2) to > > > > call its obj1.equals(obj2) or something like this. However, > > > > the outcome surprise me. Assertion success but > > > > obj1.equals(obj2) return false. > > > > > > > > What's going on inside assertEquals() operation? Is this > > > > what it's suppose to be? > > > > > > As I stated, albeit not very clearly the first time (Curse you > > > "Rich Text Editor(Beta)"!), I suspect that the culprit here is > > > that "Assert.assertEquals(Object, Object)" is not being called > > > at all. This is borne out by the fact that a J2SE 1.4 compiler > > > and a JavaSE 1.5 compiler treat the same call completely > > > differently. > > > > > > I *SUSPECT* that the 1.5 compiler is unboxing the Double > > > objects into primitive longs and that the method that is > > > *ACTUALLY* called is "Assert.assertEquals(long,long)". This > > > accounts for the behavior since the integer parts of your two > > > numbers are the same. "Assert.assertEquals(long,long)" yields > > > successful after the Doubles are converted (truncated) to > > > longs. > > > > > That's almost certainly what is happening, and good deduction. > > Thank you very much! > > > Now we ask the question, what's the better answer? Defeat the > > purpose of assertEquals(Object,Object) or letting programmers > > hoist themselves on their own petards? > > > > JUnit could detect this situation, but if it did, I'd prefer > > it to warn the programmer rather than fix the problem, because > > I want to encourage programmers to improve their design: > > either the test should compare the Double values with a > > tolerance, or perhaps the production code ought not to use > > Doubles. > > Well if that is the best solution (and I must say that I like it > better than the status quo) then the easiest way to do that would > probably be to create a bogus "Assert.assertEquals(double,double)" > > A) is deprecated (Yes, I mean it. A new method that is deprecated and > with no intent ever to remove it). The javadoc should point to the > 3-double overload as the preferred alternative and explain why. > > *AND* > > B) is implemented to unconditionally throw > "UnsupportedOperationException" (or similar unchecked standard > exception) with a message that indicates that you should use the > 3-double overload instead. Double so some Exception should be threw. > > -- Roger Glover > Object Partners, Inc. > ------------------------------------ Nattapong Sirilappanich Engineer, National Language Development - GCoC & TSC Thailand Software Group, IBM Thailand Co., Ltd. e-mail: natta@... |
|
|
RE: Re: What is expected behavior on Assert.assertEquals on Number object?Nattapong,
The situation is confusing. AssertEquals() started out just using equals(). Then people were surprised by this behavior for a variety of special cases, so we started making assertEquals() smarter. Then people were surprised by this behavior for a variety of special cases (strange how that works out...), so we've gone back to simpler behavior for assertEquals. Special cases were handled by special assertions, like assertArrayEquals(). In future, they will be handled using special Matchers and assertThat(). Regards, Kent Beck Three Rivers Institute _____ From: |