In the process of writing my own version of PerlUnit, I've uncovered what appear to be some bugs in the existing Test::Unit code, specifically the behavior of assert_equal. What isn't clear to me is whether they are bugs in the test code, design problems in PerlLanguage itself, or just fuzzy thinking on my part.
One failure condition is that is_numeric appears to answer "true" when passed an array. I would think this is a bug.
Similarly, it appears that the code as written is unable to distinguish a number from a stringified number -- in other words,
$a = 3; $b = "3"; if ($a == $b) { print "equal"; } else print "not equal"; }will test as equal.
In fact, I see no way within perl to distinguish 3 from "3". While I understand that Perl attempts to coerce numbers to strings and vice-versa, it seems to me that a test harness really DOES need to be able to differentiate them. The rub is I see no way to accomplish the feat.
Am I missing something basic here?
If there's no way to distinguish between the two, then why do you care?
Here is a simple Perl program:
use strict; my $a = 3.0; my $b = '3.0'; my $stringCompareResult = $a eq $b?'true':'false'; my $numberCompareResult = $a == $b?'true':'false'; print ("\$stringCompareResult: $stringCompareResult\n"); print ("\$numberCompareResult: $numberCompareResult\n");This program produces the following output:
$stringCompareResult: false $numberCompareResult: trueThese two values -- 3.0 and '3.0' -- clearly produce different results when compared via eq and ==. This means that I need a way to distinguish the two.
How shall the test harness distinguish a number (3.0) from a stringified number ("3.0")?
Surely the language or interpreter provides such a mechanism. If not, it is surely broken.
There is a "mechanism" -- exploit the difference in the way "~" acts on numbers versus strings. The following sub works (as compared to the version in Test::Unit::Assert.pm):
sub is_numeric { my $anArgument = shift; my $answer = ($anArgument & ~ $anArgument) eq "0"; return $answer; }I believe it is important to shift in $anArgument, so that the routine does not operate on $_[0], because it will numberfy a string.
One failure condition is that is_numeric appears to answer "true" when passed an array. I would think this is a bug.
Apparently, is_numeric expects a scalar. When you "pass" an array to something expecting a scalar, perl assumes you want the length of the array, which is numeric.
Yes, apparently the original Test::Unit::Assert.pm code special-cases arrays before calling the code that invokes this.