diff options
author | Hernan Grecco <hernan.grecco@gmail.com> | 2014-06-10 23:18:42 -0300 |
---|---|---|
committer | Hernan Grecco <hernan.grecco@gmail.com> | 2014-06-11 01:55:22 -0300 |
commit | afbac103c66710fbd2cb123d0bd418850b9548ca (patch) | |
tree | 5c631593a1255685a34691f36132580cf633d0d0 | |
parent | 4d338c1fbc812d46d4fe472bc4e3124a046ea210 (diff) | |
download | pint-afbac103c66710fbd2cb123d0bd418850b9548ca.tar.gz |
Improved testing
- added docs to ufunc testing helper funcs
- changed ufunc testing helper funcs to rely on base
testing classes for Quantity comparison
- fixed a few tests
- Changed test asanyarray bug from skip to expectedFailure
-rw-r--r-- | pint/testsuite/test_numpy.py | 39 | ||||
-rw-r--r-- | pint/testsuite/test_umath.py | 123 |
2 files changed, 113 insertions, 49 deletions
diff --git a/pint/testsuite/test_numpy.py b/pint/testsuite/test_numpy.py index 3b753d4..a8dc3c5 100644 --- a/pint/testsuite/test_numpy.py +++ b/pint/testsuite/test_numpy.py @@ -4,6 +4,7 @@ from __future__ import division, unicode_literals, print_function, absolute_impo from pint.compat import np, unittest from pint.testsuite import QuantityTestCase, helpers +from pint.testsuite.test_umath import TestUFuncs @helpers.requires_numpy() @@ -189,9 +190,11 @@ class TestNumpyMethods(QuantityTestCase): q[0] = 1*self.ureg.m self.assertQuantityEqual(q, [[1,1],[3,4]]*self.ureg.m) - q[0] = (1,2)*self.ureg.m - self.assertQuantityEqual(q, self.q) + q = self.q.copy() + q.__setitem__(Ellipsis, 1*self.ureg.m) + self.assertQuantityEqual(q, [[1,1],[1,1]]*self.ureg.m) + q = self.q.copy() q[:] = 1*self.ureg.m self.assertQuantityEqual(q, [[1,1],[1,1]]*self.ureg.m) @@ -239,23 +242,25 @@ class TestNumpyMethods(QuantityTestCase): self.assertQuantityEqual(u == 1, u.magnitude == 1) -from pint.testsuite.test_umath import TestUFuncs -@unittest.skip -class TestNumpyNotSupported(TestUFuncs): +@unittest.expectedFailure +class TestNumpyNeedsSubclassing(TestUFuncs): FORCE_NDARRAY = True + @property + def q(self): + return [1. ,2., 3., 4.] * self.ureg.J def test_unwrap(self): """unwrap depends on diff """ - self.assertEqual(np.unwrap([0,3*np.pi]*self.ureg.radians), [0,np.pi]) - self.assertEqual(np.unwrap([0,540]*self.ureg.deg), [0,180]*self.ureg.deg) + self.assertQuantityEqual(np.unwrap([0,3*np.pi]*self.ureg.radians), [0,np.pi]) + self.assertQuantityEqual(np.unwrap([0,540]*self.ureg.deg), [0,180]*self.ureg.deg) def test_trapz(self): """Units are erased by asanyarray, Quantity does not inherit from NDArray """ - self.assertEqual(np.trapz(self.q, dx = 1*self.ureg.m), 7.5 * self.ureg.J*self.ureg.m) + self.assertQuantityEqual(np.trapz(self.q, dx=1*self.ureg.m), 7.5 * self.ureg.J*self.ureg.m) def test_diff(self): """Units are erased by asanyarray, Quantity does not inherit from NDArray @@ -265,13 +270,13 @@ class TestNumpyNotSupported(TestUFuncs): def test_ediff1d(self): """Units are erased by asanyarray, Quantity does not inherit from NDArray """ - self.assertEqual(np.ediff1d(self.q, 1), [1, 1, 1] * self.ureg.J) + self.assertQuantityEqual(np.ediff1d(self.q, 1 * self.ureg.J), [1, 1, 1] * self.ureg.J) def test_fix(self): """Units are erased by asanyarray, Quantity does not inherit from NDArray """ - self.assertEqual(np.fix(3.14 * self.ureg.m), 3.0 * self.ureg.m) - self.assertEqual(np.fix(3.0 * self.ureg.m), 3.0 * self.ureg.m) + self.assertQuantityEqual(np.fix(3.14 * self.ureg.m), 3.0 * self.ureg.m) + self.assertQuantityEqual(np.fix(3.0 * self.ureg.m), 3.0 * self.ureg.m) self.assertQuantityEqual( np.fix([2.1, 2.9, -2.1, -2.9] * self.ureg.m), [2., 2., -2., -2.] * self.ureg.m @@ -281,15 +286,15 @@ class TestNumpyNotSupported(TestUFuncs): """shape is a property not a function """ l = np.gradient([[1,1],[3,4]] * self.ureg.J, 1 * self.ureg.m) - self.assertEqual(l[0], [[2., 3.], [2., 3.]] * self.ureg.J / self.ureg.m) - self.assertEqual(l[1], [[0., 0.], [1., 1.]] * self.ureg.J / self.ureg.m) + self.assertQuantityEqual(l[0], [[2., 3.], [2., 3.]] * self.ureg.J / self.ureg.m) + self.assertQuantityEqual(l[1], [[0., 0.], [1., 1.]] * self.ureg.J / self.ureg.m) def test_cross(self): """Units are erased by asarray, Quantity does not inherit from NDArray """ - a = [3,-3, 1] * self.ureg.kPa - b = [4, 9, 2] * self.ureg.m**2 - self.assertQuantityEqual(np.cross(a,b), [-15,-2,39]*self.ureg.kPa*self.ureg.m**2) + a = [[3,-3, 1]] * self.ureg.kPa + b = [[4, 9, 2]] * self.ureg.m**2 + self.assertQuantityEqual(np.cross(a, b), [-15, -2, 39] * self.ureg.kPa * self.ureg.m**2) def test_power(self): """This is not supported as different elements might end up with different units @@ -311,7 +316,7 @@ class TestNumpyNotSupported(TestUFuncs): 2) -@unittest.skip +@unittest.expectedFailure class TestBitTwiddlingUfuncs(TestUFuncs): """Universal functions (ufuncs) > Bittwiddling functions diff --git a/pint/testsuite/test_umath.py b/pint/testsuite/test_umath.py index 9586af5..cfbba86 100644 --- a/pint/testsuite/test_umath.py +++ b/pint/testsuite/test_umath.py @@ -52,17 +52,29 @@ class TestUFuncs(QuantityTestCase): except Exception as e: self.assertFalse(True, msg='{0} not raised but {1}\n{2}'.format(ExcType, e, msg)) - def _testn(self, func, ok_with, raise_with=(), results=None): - self._test1(func, ok_with, raise_with, output_units=None, results=results) - def _test1(self, func, ok_with, raise_with=(), output_units='same', results=None, rtol=1e-6): + """Test function that takes a single argument and returns Quantity. + + :param func: function callable. + :param ok_with: iterables of values that work fine. + :param raise_with: iterables of values that raise exceptions. + :param output_units: units to be used when building results. + 'same': ok_with[n].units (default). + is float: ok_with[n].units ** output_units. + None: no output units, the result should be an ndarray. + Other value will be parsed as unit. + :param results: iterable of results. + If None, the result will be obtained by applying + func to each ok_with value + :param rtol: relative tolerance. + """ if results is None: results = [None, ] * len(ok_with) for x1, res in zip(ok_with, results): err_msg = 'At {0} with {1}'.format(func.__name__, x1) if output_units == 'same': ou = x1.units - elif isinstance(output_units, int): + elif isinstance(output_units, (int, float)): ou = x1.units ** output_units else: ou = output_units @@ -70,20 +82,45 @@ class TestUFuncs(QuantityTestCase): qm = func(x1) if res is None: res = func(x1.magnitude) - if ou: + if ou is not None: res = self.Q_(res, ou) - if isinstance(res, self.Q_): - self.assertIsInstance(qm, self.Q_, msg=err_msg + ' {0!r} is not Quantity'.format(qm)) - qm = qm.magnitude - res = res.magnitude - np.testing.assert_allclose(qm, res, rtol=rtol, err_msg=err_msg) + + self.assertQuantityAlmostEqual(qm, res, rtol=rtol, msg=err_msg) for x1 in raise_with: self.assertRaisesMsg('At {0} with {1}'.format(func.__name__, x1), ValueError, func, x1) + def _testn(self, func, ok_with, raise_with=(), results=None): + """Test function that takes a single argument and returns and ndarray (not a Quantity) + + :param func: function callable. + :param ok_with: iterables of values that work fine. + :param raise_with: iterables of values that raise exceptions. + :param results: iterable of results. + If None, the result will be obtained by applying + func to each ok_with value + """ + self._test1(func, ok_with, raise_with, output_units=None, results=results) + def _test1_2o(self, func, ok_with, raise_with=(), output_units=('same', 'same'), results=None, rtol=1e-6): + """Test functions that takes a single argument and return two Quantities. + + :param func: function callable. + :param ok_with: iterables of values that work fine. + :param raise_with: iterables of values that raise exceptions. + :param output_units: tuple of units to be used when building the result tuple. + 'same': ok_with[n].units (default). + is float: ok_with[n].units ** output_units. + None: no output units, the result should be an ndarray. + Other value will be parsed as unit. + :param results: iterable of results. + If None, the result will be obtained by applying + func to each ok_with value + :param rtol: relative tolerance. + """ + if results is None: results = [None, ] * len(ok_with) for x1, res in zip(ok_with, results): @@ -95,26 +132,35 @@ class TestUFuncs(QuantityTestCase): for ndx, (qm, re, ou) in enumerate(zip(qms, res, output_units)): if ou == 'same': ou = x1.units - elif isinstance(ou, int): + elif isinstance(ou, (int, float)): ou = x1.units ** ou if ou is not None: re = self.Q_(re, ou) - if isinstance(re, self.Q_): - self.assertIsInstance(qm, self.Q_, msg=err_msg) - qm = qm.magnitude - re = re.magnitude - np.testing.assert_allclose(qm, re, rtol=rtol, err_msg=err_msg) + self.assertQuantityAlmostEqual(qm, re, rtol=rtol, msg=err_msg) for x1 in raise_with: self.assertRaisesMsg('At {0} with {1}'.format(func.__name__, x1), ValueError, func, x1) - def _testn2(self, func, x1, ok_with, raise_with=()): - self._test2(func, x1, ok_with, raise_with, output_units=None) - def _test2(self, func, x1, ok_with, raise_with=(), output_units='same', rtol=1e-6, convert2=True): + """Test function that takes two arguments and return a Quantity. + + :param func: function callable. + :param x1: first argument of func. + :param ok_with: iterables of values that work fine. + :param raise_with: iterables of values that raise exceptions. + :param output_units: units to be used when building results. + 'same': x1.units (default). + 'prod': x1.units * ok_with[n].units + 'div': x1.units / ok_with[n].units + 'second': x1.units * ok_with[n] + None: no output units, the result should be an ndarray. + Other value will be parsed as unit. + :param rtol: relative tolerance. + :param convert2: if the ok_with[n] should be converted to x1.units. + """ for x2 in ok_with: err_msg = 'At {0} with {1} and {2}'.format(func.__name__, x1, x2) if output_units == 'same': @@ -136,18 +182,25 @@ class TestUFuncs(QuantityTestCase): m2 = getattr(x2, 'magnitude', x2) res = func(x1.magnitude, m2) - if ou: + if ou is not None: res = self.Q_(res, ou) - if isinstance(res, self.Q_): - self.assertIsInstance(qm, self.Q_, msg=err_msg) - qm = qm.magnitude - res = res.magnitude - np.testing.assert_allclose(qm, res, rtol=rtol, err_msg=err_msg) + + self.assertQuantityAlmostEqual(qm, res, rtol=rtol, msg=err_msg) for x2 in raise_with: self.assertRaisesMsg('At {0} with {1} and {2}'.format(func.__name__, x1, x2), ValueError, func, x1, x2) + def _testn2(self, func, x1, ok_with, raise_with=()): + """Test function that takes two arguments and return a ndarray. + + :param func: function callable. + :param x1: first argument of func. + :param ok_with: iterables of values that work fine. + :param raise_with: iterables of values that raise exceptions. + """ + self._test2(func, x1, ok_with, raise_with, output_units=None) + @helpers.requires_numpy() class TestMathUfuncs(TestUFuncs): @@ -248,7 +301,7 @@ class TestMathUfuncs(TestUFuncs): self.q1, (self.q2, self.qs, self.qless), (), - 'div', convert2=False) + 'same', convert2=False) def test_mod(self): self._test2(np.mod, @@ -322,7 +375,7 @@ class TestMathUfuncs(TestUFuncs): self._test1(np.sqrt, (self.q2, self.qs, self.qless, self.qi), (), - 'same') + 0.5) def test_square(self): self._test1(np.square, @@ -334,7 +387,7 @@ class TestMathUfuncs(TestUFuncs): self._test1(np.reciprocal, (self.q2, self.qs, self.qless, self.qi), (), - 2) + -1) @helpers.requires_numpy() @@ -469,10 +522,16 @@ class TestTrigUfuncs(TestUFuncs): ), (self.ureg.m, ), 'radians') def test_rad2deg(self): - self._test1(np.rad2deg, (np.arange(0, pi/2, pi/4) * self.ureg.dimensionless, - np.arange(0, pi/2, pi/4) * self.ureg.radian, - np.arange(0, pi/2, pi/4) * self.ureg.mm / self.ureg.m - ), (self.ureg.m, ), 'degree', results=(None, None, np.rad2deg(np.arange(0, pi/2, pi/4)*0.001))) + self._test1(np.rad2deg, + (np.arange(0, pi/2, pi/4) * self.ureg.dimensionless, + np.arange(0, pi/2, pi/4) * self.ureg.radian, + np.arange(0, pi/2, pi/4) * self.ureg.mm / self.ureg.m, + ), + (self.ureg.m, ), 'degree', + results=(None, + None, + np.rad2deg(np.arange(0, pi/2, pi/4)*0.001) * self.ureg.degree, + )) |