Search code examples
pythonunit-testingassertscientific-computing

Assert equality of floating point values to a significant figure tolerance


I am trying to write a unittest to check the output of an engineering analysis. I have theoretical values which i want to check against the analysis to a certain number of significant figures. so, for example:

Ixx_ther = 0.000123
Iyy_ther = 0.0123

Ixx, Iyy = getI(*args, **kwargs)

self.assertAlmostEqual(Ixx_ther, Ixx, 6)
self.assertAlmostEqual(Iyy_ther, Iyy, 4)

In this case, i need to know the number i am trying to check as setting the tolerance to 6 in both cases would make the test too stringent and setting it to 4 would be too lax. What I need is a test for equality to the same number of significant figures. What would be ideal is to say:

Ixx_ther = 1.23E-4
Iyy_ther = 1.23E-2

Ixx, Iyy = getI(*args, **kwargs)

self.assertAlmostEqual(Ixx_ther, Ixx, 2)
self.assertAlmostEqual(Iyy_ther, Iyy, 2)

and have the assert statement drop exponent and check only the Significand for equality. I imagine this has been done before, but I have not been able to find a built-in function to assert equality in this manner. Has anyone had this problem before,

Questions

1) Has anyone had this problem before, and know of a general guide of unittests for engineering analysis

2) Is there a built-in solution. to this problem

3) Has someone already programmed a custom assert statement which works in this manner?


Solution

  • Re: is there a built-in solution for this: If you can have numpy as a dependency, have a look at numpy.testing.

    Here's an example ( verbatim from assert_allclose docs):

    >>> x = [1e-5, 1e-3, 1e-1]
    >>> y = np.arccos(np.cos(x))
    >>> assert_allclose(x, y, rtol=1e-5, atol=0)
    

    EDIT: For completeness, here's the link to the source code: assert_allclose forwards the real work to np.allclose. Which is nearly identical to @Mark Ransom's answer (plus handling of array arguments and infinities).