unittest: Proposal to add failUnlessNear

John Roth newsgroups at jhrothjr.com
Mon Jul 19 22:26:41 CEST 2004

"Antoon Pardon" <apardon at forel.vub.ac.be> wrote in message
news:slrncfnaq7.kj.apardon at trout.vub.ac.be...
> I have been working with unittests lately and found that the
> self.failUnlessAlmostEqual, isn't as usefull as it could be.
> My main problem is, that it is only usefull with objects
> that can be converted to floats, while there are a whole
> bunch of objects that can be almost equal but not so
> convertable. The first example coming to mind being
> complex numbers.
> A secondary objection is that you are limited to
> a very specific set of tolerances. If for instance
> you want to verify that two numbers differ at most
> by 0.0003 you can't specify that.

Float and complex have two very different issues.
Since I'm maintaining the Python port of FIT, I
had to deal with them. What I did for float was
use the character form of the float to determine
the precision. The default routine appends a
character 5 and then uses this to calculate the
bounds within which the other value must be found.

An example may help. Let's say I want to
test against '6.23e14'. This method would
establish bounds of 6.235e14 and 6.225e14
and then test whether the other number was
within those bounds. (Note that the '5' is
appended before the numbers are converted
to float, however the second bound is calculated
after the conversion.)

There's also a way of prescribing something other
than '5' to append. This approach is due to
Ward Cunningham; what I did was move it
from the ScientificDouble class to the base
float type adapter. (The Java source can be
located in a number of places, including
fit.c2.com and www.fitnesse.org. The Python
source is in the files section of the Extremeprogramming
and fitnesse Yahoo groups. You're welcome
to copy the approach, but since Ward put it
under the GPL, I don't think it can be directly
dropped into unittest.)

Complex, on the other hand, should be dealt
with by calculating the distance between the
two values in the i,j plane
and then seeing if this distance is within a given
bound. The bound should, of course, be a
separately specifiable parameter.

One major issue is that these are very type specific;
the methods should be called something like
"failUnlessFloatWithinTolerance" and

John Roth

> So I propose to add the following
>   def failUnlessNear(self, first, second, tolerance=1e-7, msg=None,
>       """Fail if the two objects are too far appart as determined
>          by the distance between them and the tolerance allowed.
>       """
>       if norm(second-first) > tolerance:
>           raise self.failureException, \
>                 (msg or '%s != %s within %s tolerance' % (`first`,
`second`, `tolerance`))
> -- 
> Antoon Pardon

More information about the Python-list mailing list