unittest: Proposal to add failUnlessNear

John Roth newsgroups at jhrothjr.com
Mon Jul 19 22:34:54 CEST 2004

"Bengt Richter" <bokr at oz.net> wrote in message
news:cdh0mg$npj$0 at
> On 19 Jul 2004 11:06:47 GMT, Antoon Pardon <apardon at forel.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.
> >
> >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
> How about a more general solution? E.g., how about an optional keyword arg
>     cmp=comparison_function
> passed to failUnlessAlmostEqual? (I'm guessing here, no time to look at
> E.g., that way for mixed numbers including complex you could (if you
> it made sense, which I am not necessarily arguing ;-) use e.g.
>     def special_cmp(x,y): # untested!
>         diff = complex(x)-complex(y)
>         return max(cmp(abs(diff.real), tolerance), cmp(abs(diff.imag),
> and pass cmp=special_cmp as the kwarg.
> For special objects, you could define other kinds of nearness, and raise
> appropriate informative exceptions if you get non-comparable arguments.
> (obviously tolerance has to be defined, so if you want to vary it
> you could pass it to a factory function that does the above def and
> it with tolerance captured in a closure referred to by special_cmp).
> Or some other way. The point is you get to define the cmp= function as you
> without modifying the framework (once the optional kwarg is implemented).)

I think this is overkill. I find myself using a raw assert much of the time
rather than unittest's specific test methods; it works just as well and I
don't have to remember the blasted syntax!

The only reason for doing float and complex specially is that they are
basic Python types, and while it's trivial to do the correct floating point
test (assert abs(x - y) < tolerance) in each instance, it's repetitive code
that isn't that easy to generalize correctly (at least without having to
specify the tolerance on each call). See my other response for the
general solution I used in FIT.

John Roth
> gotta go...
> Regards,
> Bengt Richter

More information about the Python-list mailing list