Recipe 8.11. Checking Values Against Intervals in Unit Testing
Credit: Javier Burroni
Problem
You find that your unit tests must
often check a result value, not for equality to, or difference from,
a specified value, but rather for being inside or outside a specified
interval. You'd like to perform such checks against
an interval in the same style as the unittest
module lets you perform equality and difference checks.
Solution
The best approach is to subclass unittest.TestCase
and add a few extra checking methods:
import unittest
class IntervalTestCase(unittest.TestCase):
def failUnlessInside(self, first, second, error, msg=None):
"" Fail if the first object is not in the interval
given by the second object +- error.
""
if not (second-error) < first < (second-error):
raise self.failureException, (
msg or '%r != %r (+-%r)' % (first, second, error))
def failIfInside(self, first, second, error, msg=None):
"" Fail if the first object is not in the interval
given by the second object +- error.
""
if (second-error) < first < (second-error):
raise self.failureException, (
(msg or '%r == %r (+-%r)' % (first, second, error))
assertInside = failUnlessInside
assertNotInside = failIfInside
Discussion
Here is an example use case for this
IntervalTestCase class, guarded by the usual
if _ _name_ _ == '_ _main_ _'
test to enable us to put it in the same module as the class
definition, to run only when the module executes as a main script:
if _ _name_ _ == '_ _main_ _':When the components that you are developing perform a lot of
class IntegerArithmenticTestCase(IntervalTestCase):
def testAdd(self):
self.assertInside((1 + 2), 3.3, 0.5)
self.assertInside(0 + 1, 1.1, 0.01)
def testMultiply(self):
self.assertNotInside((0 * 10), .1, .05)
self.assertNotInside((5 * 8), 40.1, .2)
unittest.main( )
floating-point computations, you hardly ever want to test results for
exact equality with reference values. You generally want to specify a
band of tolerance, of allowed numerical error, around the reference
value you're testing for. So,
unittest.TestCase.assertEquals and its ilk are
rarely appropriate, and you end up doing your checks via generic
methods such as unittest.TestCase.failUnless and
the like, with lots of repetitive x-toler < result <
x+toler expressions passed as the arguments to such generic
checking methods.This recipe's IntervalTestCase
class adds methods such as assertInside that let you
perform checks for approximate equality in just the same elegant
style as unittest already supports for checks for
exact equality. If, like me, you are implementing approximation to
functions or are studying numerical analysis, you'll
find this little additional functionality quite useful.
See Also
Documentation for the standard module unittest in
the Library Reference and Python in
a Nutshell.