diff options
author | Hernan <hernan.grecco@gmail.com> | 2021-01-08 20:20:14 -0300 |
---|---|---|
committer | Hernan <hernan.grecco@gmail.com> | 2021-01-10 03:58:32 -0300 |
commit | 659f6304d0054c844c3347af9df6dffa14cb7f9f (patch) | |
tree | 0822dba0fbce47a01e5357f33a763c40c2588014 | |
parent | 23ddaff124ad09445d9097408971d13f2fdb2736 (diff) | |
download | pint-659f6304d0054c844c3347af9df6dffa14cb7f9f.tar.gz |
Migration of all tests to pytest
The intento of this large commit is to move away from unittest
into pytest.
To speed-up migration we made certain choices that might
need to be revisted in the future:
- use pytest-subtests to replace unittest subtest infrastructure
A lot of this might be better using parametrize
- While we have removed certain classes and flatten them to
functions, some were kept for no particular reason
(rewriting the QuantityTestCase base class)
- We have created some fixtures but not optimized.
Feature optimization (i.e. using global registries for certain
tests might speed up testing as it will void constructing
the registry over and over)
28 files changed, 3286 insertions, 3201 deletions
diff --git a/.travis.yml b/.travis.yml index 3238d6f..d81d89f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,7 +55,7 @@ before_install: - export TEST_OPTS="-rfsxEX -s --cov=pint --cov-config=.coveragerc" install: - - conda create -n travis $PKGS pytest pytest-cov coveralls + - conda create -n travis $PKGS pytest pytest-cov coveralls pytest-subtests - source activate travis - if [[ $PKGS =~ pandas ]]; then PANDAS=1; else PANDAS=0; fi - if [[ $PKGS =~ pre-commit ]]; then LINT=1; else LINT=0; fi diff --git a/pint/testsuite/__init__.py b/pint/testsuite/__init__.py index 6877221..35b6c89 100644 --- a/pint/testsuite/__init__.py +++ b/pint/testsuite/__init__.py @@ -1,141 +1,26 @@ import doctest -import logging import math import os import unittest -from contextlib import contextmanager -from logging.handlers import BufferingHandler -from pint import Quantity, UnitRegistry, logger -from pint.compat import ndarray, np +from pint import UnitRegistry from pint.testsuite.helpers import PintOutputChecker -class TestHandler(BufferingHandler): - def __init__(self, only_warnings=False): - # BufferingHandler takes a "capacity" argument - # so as to know when to flush. As we're overriding - # shouldFlush anyway, we can set a capacity of zero. - # You can call flush() manually to clear out the - # buffer. - self.only_warnings = only_warnings - BufferingHandler.__init__(self, 0) - - def shouldFlush(self): - return False - - def emit(self, record): - if self.only_warnings and record.level != logging.WARNING: - return - self.buffer.append(record.__dict__) - - -class BaseTestCase(unittest.TestCase): - - CHECK_NO_WARNING = True - - @contextmanager - def capture_log(self, level=logging.DEBUG): - th = TestHandler() - th.setLevel(level) - logger.addHandler(th) - if self._test_handler is not None: - buflen = len(self._test_handler.buffer) - yield th.buffer - if self._test_handler is not None: - self._test_handler.buffer = self._test_handler.buffer[:buflen] - - def setUp(self): - self._test_handler = None - if self.CHECK_NO_WARNING: - self._test_handler = th = TestHandler() - th.setLevel(logging.WARNING) - logger.addHandler(th) - - def tearDown(self): - if self._test_handler is not None: - buf = self._test_handler.buffer - msg = "\n".join(record.get("msg", str(record)) for record in buf) - self.assertEqual(len(buf), 0, msg=f"{len(buf)} warnings raised.\n{msg}") - - -class QuantityTestCase(BaseTestCase): - - FORCE_NDARRAY = False +class QuantityTestCase: + kwargs = {} @classmethod - def setUpClass(cls): - cls.ureg = UnitRegistry(force_ndarray=cls.FORCE_NDARRAY) + def setup_class(cls): + cls.ureg = UnitRegistry(**cls.kwargs) cls.Q_ = cls.ureg.Quantity cls.U_ = cls.ureg.Unit - def _get_comparable_magnitudes(self, first, second, msg): - if isinstance(first, Quantity) and isinstance(second, Quantity): - second = second.to(first) - self.assertEqual( - first.units, second.units, msg=msg + " Units are not equal." - ) - m1, m2 = first.magnitude, second.magnitude - elif isinstance(first, Quantity): - self.assertTrue( - first.dimensionless, msg=msg + " The first is not dimensionless." - ) - first = first.to("") - m1, m2 = first.magnitude, second - elif isinstance(second, Quantity): - self.assertTrue( - second.dimensionless, msg=msg + " The second is not dimensionless." - ) - second = second.to("") - m1, m2 = first, second.magnitude - else: - m1, m2 = first, second - - return m1, m2 - - def assertQuantityEqual(self, first, second, msg=None): - if msg is None: - msg = "Comparing %r and %r. " % (first, second) - - m1, m2 = self._get_comparable_magnitudes(first, second, msg) - - if isinstance(m1, ndarray) or isinstance(m2, ndarray): - np.testing.assert_array_equal(m1, m2, err_msg=msg) - elif math.isnan(m1): - self.assertTrue(math.isnan(m2), msg) - elif math.isnan(m2): - self.assertTrue(math.isnan(m1), msg) - else: - self.assertEqual(m1, m2, msg) - - def assertQuantityAlmostEqual(self, first, second, rtol=1e-07, atol=0, msg=None): - if msg is None: - try: - msg = "Comparing %r and %r. " % (first, second) - except TypeError: - try: - msg = "Comparing %s and %s. " % (first, second) - except Exception: - msg = "Comparing" - - m1, m2 = self._get_comparable_magnitudes(first, second, msg) - - if isinstance(m1, ndarray) or isinstance(m2, ndarray): - np.testing.assert_allclose(m1, m2, rtol=rtol, atol=atol, err_msg=msg) - elif math.isnan(m1): - self.assertTrue(math.isnan(m2), msg) - elif math.isnan(m2): - self.assertTrue(math.isnan(m1), msg) - else: - self.assertLessEqual(abs(m1 - m2), atol + rtol * abs(m2), msg=msg) - - -class CaseInsensitveQuantityTestCase(QuantityTestCase): @classmethod - def setUpClass(cls): - cls.ureg = UnitRegistry(case_sensitive=False) - cls.Q_ = cls.ureg.Quantity - cls.U_ = cls.ureg.Unit + def teardown_class(cls): + cls.ureg = None + cls.Q_ = None + cls.U_ = None def testsuite(): diff --git a/pint/testsuite/conftest.py b/pint/testsuite/conftest.py new file mode 100644 index 0000000..529c33f --- /dev/null +++ b/pint/testsuite/conftest.py @@ -0,0 +1,77 @@ +# pytest fixtures + +import io + +import pytest + +import pint + + +@pytest.fixture +def registry_empty(): + return pint.UnitRegistry(None) + + +@pytest.fixture +def registry_tiny(): + return pint.UnitRegistry( + io.StringIO( + """ +yocto- = 1e-24 = y- +zepto- = 1e-21 = z- +atto- = 1e-18 = a- +femto- = 1e-15 = f- +pico- = 1e-12 = p- +nano- = 1e-9 = n- +micro- = 1e-6 = µ- = u- +milli- = 1e-3 = m- +centi- = 1e-2 = c- +deci- = 1e-1 = d- +deca- = 1e+1 = da- = deka- +hecto- = 1e2 = h- +kilo- = 1e3 = k- +mega- = 1e6 = M- +giga- = 1e9 = G- +tera- = 1e12 = T- +peta- = 1e15 = P- +exa- = 1e18 = E- +zetta- = 1e21 = Z- +yotta- = 1e24 = Y- + +meter = [length] = m = metre +second = [time] = s = sec + +angstrom = 1e-10 * meter = Å = ångström = Å +minute = 60 * second = min +""" + ) + ) + + +@pytest.fixture +def func_registry(): + return pint.UnitRegistry() + + +@pytest.fixture(scope="class") +def class_registry(): + """Only use for those test that do not modify the registry.""" + return pint.UnitRegistry() + + +@pytest.fixture(scope="session") +def sess_registry(): + """Only use for those test that do not modify the registry.""" + return pint.UnitRegistry() + + +@pytest.fixture(scope="class") +def class_tiny_app_registry(): + ureg_bak = pint.get_application_registry() + ureg = pint.UnitRegistry(None) + ureg.define("foo = []") + ureg.define("bar = foo / 2") + pint.set_application_registry(ureg) + assert pint.get_application_registry() is ureg + yield ureg + pint.set_application_registry(ureg_bak) diff --git a/pint/testsuite/helpers.py b/pint/testsuite/helpers.py index eae7650..0ec405a 100644 --- a/pint/testsuite/helpers.py +++ b/pint/testsuite/helpers.py @@ -1,7 +1,15 @@ import doctest +import math +import pickle import re -import unittest -from distutils.version import StrictVersion +import warnings +from distutils.version import LooseVersion +from numbers import Number + +import pytest + +from pint import Quantity +from pint.compat import ndarray, np from ..compat import ( HAS_BABEL, @@ -11,68 +19,6 @@ from ..compat import ( NUMPY_VER, ) - -def requires_array_function_protocol(): - if not HAS_NUMPY: - return unittest.skip("Requires NumPy") - return unittest.skipUnless( - HAS_NUMPY_ARRAY_FUNCTION, "Requires __array_function__ protocol to be enabled" - ) - - -def requires_not_array_function_protocol(): - if not HAS_NUMPY: - return unittest.skip("Requires NumPy") - return unittest.skipIf( - HAS_NUMPY_ARRAY_FUNCTION, - "Requires __array_function__ protocol to be unavailable or disabled", - ) - - -def requires_numpy_previous_than(version): - if not HAS_NUMPY: - return unittest.skip("Requires NumPy") - return unittest.skipUnless( - StrictVersion(NUMPY_VER) < StrictVersion(version), - "Requires NumPy < %s" % version, - ) - - -def requires_numpy_at_least(version): - if not HAS_NUMPY: - return unittest.skip("Requires NumPy") - return unittest.skipUnless( - StrictVersion(NUMPY_VER) >= StrictVersion(version), - "Requires NumPy >= %s" % version, - ) - - -def requires_numpy(): - return unittest.skipUnless(HAS_NUMPY, "Requires NumPy") - - -def requires_not_numpy(): - return unittest.skipIf(HAS_NUMPY, "Requires NumPy not to be installed.") - - -def requires_babel(): - return unittest.skipUnless(HAS_BABEL, "Requires Babel with units support") - - -def requires_not_babel(): - return unittest.skipIf(HAS_BABEL, "Requires Babel not to be installed") - - -def requires_uncertainties(): - return unittest.skipUnless(HAS_UNCERTAINTIES, "Requires Uncertainties") - - -def requires_not_uncertainties(): - return unittest.skipIf( - HAS_UNCERTAINTIES, "Requires Uncertainties not to be installed." - ) - - _number_re = r"([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)" _q_re = re.compile( r"<Quantity\(" @@ -140,3 +86,153 @@ class PintOutputChecker(doctest.OutputChecker): return self.check_output(parsed_want, parsed_got, optionflags) return False + + +def _get_comparable_magnitudes(first, second, msg): + if isinstance(first, Quantity) and isinstance(second, Quantity): + second = second.to(first) + assert first.units == second.units, msg + " Units are not equal." + m1, m2 = first.magnitude, second.magnitude + elif isinstance(first, Quantity): + assert first.dimensionless, msg + " The first is not dimensionless." + first = first.to("") + m1, m2 = first.magnitude, second + elif isinstance(second, Quantity): + assert second.dimensionless, msg + " The second is not dimensionless." + second = second.to("") + m1, m2 = first, second.magnitude + else: + m1, m2 = first, second + + return m1, m2 + + +def assert_quantity_equal(first, second, msg=None): + if msg is None: + msg = "Comparing %r and %r. " % (first, second) + + m1, m2 = _get_comparable_magnitudes(first, second, msg) + msg += " (Converted to %r and %r)" % (m1, m2) + + if isinstance(m1, ndarray) or isinstance(m2, ndarray): + np.testing.assert_array_equal(m1, m2, err_msg=msg) + elif not isinstance(m1, Number): + warnings.warn(RuntimeWarning) + return + elif not isinstance(m2, Number): + warnings.warn(RuntimeWarning) + return + elif math.isnan(m1): + assert math.isnan(m2), msg + elif math.isnan(m2): + assert math.isnan(m1), msg + else: + assert m1 == m2, msg + + +def assert_quantity_almost_equal(first, second, rtol=1e-07, atol=0, msg=None): + if msg is None: + try: + msg = "Comparing %r and %r. " % (first, second) + except TypeError: + try: + msg = "Comparing %s and %s. " % (first, second) + except Exception: + msg = "Comparing" + + m1, m2 = _get_comparable_magnitudes(first, second, msg) + msg += " (Converted to %r and %r)" % (m1, m2) + + if isinstance(m1, ndarray) or isinstance(m2, ndarray): + np.testing.assert_allclose(m1, m2, rtol=rtol, atol=atol, err_msg=msg) + elif not isinstance(m1, Number): + warnings.warn(RuntimeWarning) + return + elif not isinstance(m2, Number): + warnings.warn(RuntimeWarning) + return + elif math.isnan(m1): + assert math.isnan(m2), msg + elif math.isnan(m2): + assert math.isnan(m1), msg + elif math.isinf(m1): + assert math.isinf(m2), msg + elif math.isinf(m2): + assert math.isinf(m1), msg + else: + # Numpy version (don't like because is not symmetric) + # assert abs(m1 - m2) <= atol + rtol * abs(m2), msg + assert abs(m1 - m2) <= max(rtol * max(abs(m1), abs(m2)), atol), msg + + +# Requirements +def multi_mark(*funcs): + def _deco(f): + for func in funcs: + pytest.mark.store_mark(f, func) + + return _deco + + +requires_numpy = pytest.mark.skipif(not HAS_NUMPY, reason="Requires NumPy") +requires_not_numpy = pytest.mark.skipif( + HAS_NUMPY, reason="Requires NumPy not to be installed." +) + +requires_array_function_protocol = multi_mark( + requires_numpy, + pytest.mark.skipif( + not HAS_NUMPY_ARRAY_FUNCTION, + reason="Requires __array_function__ protocol to be enabled", + ), +) + +requires_not_array_function_protocol = multi_mark( + requires_not_numpy, + pytest.mark.skipif( + HAS_NUMPY_ARRAY_FUNCTION, + reason="Requires __array_function__ protocol to be unavailable or disabled", + ), +) + + +def requires_numpy_previous_than(version): + return multi_mark( + requires_numpy, + pytest.mark.skip( + not LooseVersion(NUMPY_VER) < LooseVersion(version), + reason="Requires NumPy < %s" % version, + ), + ) + + +def requires_numpy_at_least(version): + return multi_mark( + requires_numpy, + pytest.mark.skip( + not LooseVersion(NUMPY_VER) >= LooseVersion(version), + reason="Requires NumPy >= %s" % version, + ), + ) + + +requires_babel = pytest.mark.skipif( + not HAS_BABEL, reason="Requires Babel with units support" +) +requires_not_babel = pytest.mark.skipif( + HAS_BABEL, reason="Requires Babel not to be installed" +) +requires_uncertainties = pytest.mark.skipif( + not HAS_UNCERTAINTIES, reason="Requires Uncertainties" +) +requires_not_uncertainties = pytest.mark.skipif( + HAS_UNCERTAINTIES, reason="Requires Uncertainties not to be installed." +) + +# Parametrization + +allprotos = pytest.mark.parametrize( + ("protocol",), [(p,) for p in range(pickle.HIGHEST_PROTOCOL + 1)] +) + +check_all_bool = pytest.mark.parametrize("check_all", [False, True]) diff --git a/pint/testsuite/parameterized.py b/pint/testsuite/parameterized.py deleted file mode 100644 index 8e5df98..0000000 --- a/pint/testsuite/parameterized.py +++ /dev/null @@ -1,147 +0,0 @@ -# Adds Parameterized tests for Python's unittest module -# -# Code from: parameterizedtestcase, version: 0.1.0 -# Homepage: https://github.com/msabramo/python_unittest_parameterized_test_case -# Author: Marc Abramowitz, email: marc@marc-abramowitz.com -# License: MIT -# -# Use like this: -# -# from parameterizedtestcase import ParameterizedTestCase -# -# class MyTests(ParameterizedTestCase): -# @ParameterizedTestCase.parameterize( -# ("input", "expected_output"), -# [ -# ("2+4", 6), -# ("3+5", 8), -# ("6*9", 54), -# ] -# ) -# def test_eval(self, input, expected_output): -# self.assertEqual(eval(input), expected_output) - -import unittest -from collections.abc import Callable -from functools import wraps - - -def augment_method_docstring( - method, new_class_dict, classname, param_names, param_values, new_method -): - param_assignments_str = "; ".join( - ["%s = %s" % (k, v) for (k, v) in zip(param_names, param_values)] - ) - extra_doc = "%s (%s.%s) [with %s] " % ( - method.__name__, - new_class_dict.get("__module__", "<module>"), - classname, - param_assignments_str, - ) - - try: - new_method.__doc__ = extra_doc + new_method.__doc__ - except TypeError: # Catches when new_method.__doc__ is None - new_method.__doc__ = extra_doc - - -class ParameterizedTestCaseMetaClass(type): - method_counter = {} - - def __new__(meta, classname, bases, class_dict): - new_class_dict = {} - - for attr_name, attr_value in list(class_dict.items()): - if isinstance(attr_value, Callable) and hasattr(attr_value, "param_names"): - # print("Processing attr_name = %r; attr_value = %r" % ( - # attr_name, attr_value)) - - method = attr_value - param_names = attr_value.param_names - data = attr_value.data - func_name_format = attr_value.func_name_format - - meta.process_method( - classname, - method, - param_names, - data, - new_class_dict, - func_name_format, - ) - else: - new_class_dict[attr_name] = attr_value - - return type.__new__(meta, classname, bases, new_class_dict) - - @classmethod - def process_method( - cls, classname, method, param_names, data, new_class_dict, func_name_format - ): - method_counter = cls.method_counter - - for param_values in data: - new_method = cls.new_method(method, param_values) - method_counter[method.__name__] = method_counter.get(method.__name__, 0) + 1 - case_data = dict(list(zip(param_names, param_values))) - case_data["func_name"] = method.__name__ - case_data["case_num"] = method_counter[method.__name__] - - new_method.__name__ = func_name_format.format(**case_data) - - augment_method_docstring( - method, new_class_dict, classname, param_names, param_values, new_method - ) - new_class_dict[new_method.__name__] = new_method - - @classmethod - def new_method(cls, method, param_values): - @wraps(method) - def new_method(self): - return method(self, *param_values) - - return new_method - - -class ParameterizedTestMixin(metaclass=ParameterizedTestCaseMetaClass): - @classmethod - def parameterize( - cls, param_names, data, func_name_format="{func_name}_{case_num:05d}" - ): - """Decorator for parameterizing a test method - example: - - @ParameterizedTestCase.parameterize( - ("isbn", "expected_title"), [ - ("0262033844", "Introduction to Algorithms"), - ("0321558146", "Campbell Essential Biology")]) - - Parameters - ---------- - param_names : - - data : - - func_name_format : - (Default value = "{func_name}_{case_num:05d}") - - Returns - ------- - - """ - - def decorator(func): - @wraps(func) - def newfunc(*arg, **kwargs): - return func(*arg, **kwargs) - - newfunc.param_names = param_names - newfunc.data = data - newfunc.func_name_format = func_name_format - - return newfunc - - return decorator - - -class ParameterizedTestCase(unittest.TestCase, ParameterizedTestMixin): - pass diff --git a/pint/testsuite/test_application_registry.py b/pint/testsuite/test_application_registry.py index a068445..59c3521 100644 --- a/pint/testsuite/test_application_registry.py +++ b/pint/testsuite/test_application_registry.py @@ -2,6 +2,8 @@ """ import pickle +import pytest + from pint import ( Measurement, Quantity, @@ -11,156 +13,152 @@ from pint import ( get_application_registry, set_application_registry, ) -from pint.testsuite import BaseTestCase -from pint.testsuite.helpers import requires_uncertainties - -from .parameterized import ParameterizedTestMixin - -allprotos = ParameterizedTestMixin.parameterize( - ("protocol",), [(p,) for p in range(pickle.HIGHEST_PROTOCOL + 1)] -) +from pint.testsuite import helpers -class TestDefaultApplicationRegistry(BaseTestCase, ParameterizedTestMixin): - @allprotos +class TestDefaultApplicationRegistry: + @helpers.allprotos def test_unit(self, protocol): u = Unit("kg") - self.assertEqual(str(u), "kilogram") + assert str(u) == "kilogram" u = pickle.loads(pickle.dumps(u, protocol)) - self.assertEqual(str(u), "kilogram") + assert str(u) == "kilogram" - @allprotos + @helpers.allprotos def test_quantity_1arg(self, protocol): q = Quantity("123 kg") - self.assertEqual(str(q.units), "kilogram") - self.assertEqual(q.to("t").magnitude, 0.123) + assert str(q.units) == "kilogram" + assert q.to("t").magnitude == 0.123 q = pickle.loads(pickle.dumps(q, protocol)) - self.assertEqual(str(q.units), "kilogram") - self.assertEqual(q.to("t").magnitude, 0.123) + assert str(q.units) == "kilogram" + assert q.to("t").magnitude == 0.123 - @allprotos + @helpers.allprotos def test_quantity_2args(self, protocol): q = Quantity(123, "kg") - self.assertEqual(str(q.units), "kilogram") - self.assertEqual(q.to("t").magnitude, 0.123) + assert str(q.units) == "kilogram" + assert q.to("t").magnitude == 0.123 q = pickle.loads(pickle.dumps(q, protocol)) - self.assertEqual(str(q.units), "kilogram") - self.assertEqual(q.to("t").magnitude, 0.123) + assert str(q.units) == "kilogram" + assert q.to("t").magnitude == 0.123 - @requires_uncertainties() - @allprotos + @helpers.requires_uncertainties() + @helpers.allprotos def test_measurement_2args(self, protocol): m = Measurement(Quantity(123, "kg"), Quantity(15, "kg")) - self.assertEqual(m.value.magnitude, 123) - self.assertEqual(m.error.magnitude, 15) - self.assertEqual(str(m.units), "kilogram") + assert m.value.magnitude == 123 + assert m.error.magnitude == 15 + assert str(m.units) == "kilogram" m = pickle.loads(pickle.dumps(m, protocol)) - self.assertEqual(m.value.magnitude, 123) - self.assertEqual(m.error.magnitude, 15) - self.assertEqual(str(m.units), "kilogram") + assert m.value.magnitude == 123 + assert m.error.magnitude == 15 + assert str(m.units) == "kilogram" - @requires_uncertainties() - @allprotos + @helpers.requires_uncertainties() + @helpers.allprotos def test_measurement_3args(self, protocol): m = Measurement(123, 15, "kg") - self.assertEqual(m.value.magnitude, 123) - self.assertEqual(m.error.magnitude, 15) - self.assertEqual(str(m.units), "kilogram") + assert m.value.magnitude == 123 + assert m.error.magnitude == 15 + assert str(m.units) == "kilogram" m = pickle.loads(pickle.dumps(m, protocol)) - self.assertEqual(m.value.magnitude, 123) - self.assertEqual(m.error.magnitude, 15) - self.assertEqual(str(m.units), "kilogram") + assert m.value.magnitude == 123 + assert m.error.magnitude == 15 + assert str(m.units) == "kilogram" def test_get_application_registry(self): ureg = get_application_registry() u = ureg.Unit("kg") - self.assertEqual(str(u), "kilogram") + assert str(u) == "kilogram" - @allprotos + @helpers.allprotos def test_pickle_crash(self, protocol): ureg = UnitRegistry(None) ureg.define("foo = []") q = ureg.Quantity(123, "foo") b = pickle.dumps(q, protocol) - self.assertRaises(UndefinedUnitError, pickle.loads, b) + with pytest.raises(UndefinedUnitError): + pickle.loads(b) b = pickle.dumps(q.units, protocol) - self.assertRaises(UndefinedUnitError, pickle.loads, b) + with pytest.raises(UndefinedUnitError): + pickle.loads(b) - @requires_uncertainties() - @allprotos + @helpers.requires_uncertainties() + @helpers.allprotos def test_pickle_crash_measurement(self, protocol): ureg = UnitRegistry(None) ureg.define("foo = []") m = ureg.Quantity(123, "foo").plus_minus(10) b = pickle.dumps(m, protocol) - self.assertRaises(UndefinedUnitError, pickle.loads, b) + with pytest.raises(UndefinedUnitError): + pickle.loads(b) -class TestCustomApplicationRegistry(BaseTestCase, ParameterizedTestMixin): - def setUp(self): - super().setUp() - self.ureg_bak = get_application_registry() - self.ureg = UnitRegistry(None) - self.ureg.define("foo = []") - self.ureg.define("bar = foo / 2") - set_application_registry(self.ureg) - assert get_application_registry() is self.ureg +class TestCustomApplicationRegistry: + @classmethod + def setup_class(cls): + cls.ureg_bak = get_application_registry() + cls.ureg = UnitRegistry(None) + cls.ureg.define("foo = []") + cls.ureg.define("bar = foo / 2") + set_application_registry(cls.ureg) + assert get_application_registry() is cls.ureg - def tearDown(self): - super().tearDown() - set_application_registry(self.ureg_bak) + @classmethod + def teardown_class(cls): + set_application_registry(cls.ureg_bak) - @allprotos + @helpers.allprotos def test_unit(self, protocol): u = Unit("foo") - self.assertEqual(str(u), "foo") + assert str(u) == "foo" u = pickle.loads(pickle.dumps(u, protocol)) - self.assertEqual(str(u), "foo") + assert str(u) == "foo" - @allprotos + @helpers.allprotos def test_quantity_1arg(self, protocol): q = Quantity("123 foo") - self.assertEqual(str(q.units), "foo") - self.assertEqual(q.to("bar").magnitude, 246) + assert str(q.units) == "foo" + assert q.to("bar").magnitude == 246 q = pickle.loads(pickle.dumps(q, protocol)) - self.assertEqual(str(q.units), "foo") - self.assertEqual(q.to("bar").magnitude, 246) + assert str(q.units) == "foo" + assert q.to("bar").magnitude == 246 - @allprotos + @helpers.allprotos def test_quantity_2args(self, protocol): q = Quantity(123, "foo") - self.assertEqual(str(q.units), "foo") - self.assertEqual(q.to("bar").magnitude, 246) + assert str(q.units) == "foo" + assert q.to("bar").magnitude == 246 q = pickle.loads(pickle.dumps(q, protocol)) - self.assertEqual(str(q.units), "foo") - self.assertEqual(q.to("bar").magnitude, 246) + assert str(q.units) == "foo" + assert q.to("bar").magnitude == 246 - @requires_uncertainties() - @allprotos + @helpers.requires_uncertainties() + @helpers.allprotos def test_measurement_2args(self, protocol): m = Measurement(Quantity(123, "foo"), Quantity(10, "bar")) - self.assertEqual(m.value.magnitude, 123) - self.assertEqual(m.error.magnitude, 5) - self.assertEqual(str(m.units), "foo") + assert m.value.magnitude == 123 + assert m.error.magnitude == 5 + assert str(m.units) == "foo" m = pickle.loads(pickle.dumps(m, protocol)) - self.assertEqual(m.value.magnitude, 123) - self.assertEqual(m.error.magnitude, 5) - self.assertEqual(str(m.units), "foo") + assert m.value.magnitude == 123 + assert m.error.magnitude == 5 + assert str(m.units) == "foo" - @requires_uncertainties() - @allprotos + @helpers.requires_uncertainties() + @helpers.allprotos def test_measurement_3args(self, protocol): m = Measurement(123, 5, "foo") - self.assertEqual(m.value.magnitude, 123) - self.assertEqual(m.error.magnitude, 5) - self.assertEqual(str(m.units), "foo") + assert m.value.magnitude == 123 + assert m.error.magnitude == 5 + assert str(m.units) == "foo" m = pickle.loads(pickle.dumps(m, protocol)) - self.assertEqual(m.value.magnitude, 123) - self.assertEqual(m.error.magnitude, 5) - self.assertEqual(str(m.units), "foo") + assert m.value.magnitude == 123 + assert m.error.magnitude == 5 + assert str(m.units) == "foo" -class TestSwapApplicationRegistry(BaseTestCase, ParameterizedTestMixin): +class TestSwapApplicationRegistry: """Test that the constructors of Quantity, Unit, and Measurement capture the registry that is set as the application registry at creation time @@ -172,20 +170,21 @@ class TestSwapApplicationRegistry(BaseTestCase, ParameterizedTestMixin): """ - def setUp(self): - super().setUp() - self.ureg_bak = get_application_registry() - self.ureg1 = UnitRegistry(None) - self.ureg1.define("foo = [dim1]") - self.ureg1.define("bar = foo / 2") - self.ureg2 = UnitRegistry(None) - self.ureg2.define("foo = [dim2]") - self.ureg2.define("bar = foo / 3") - - def tearDown(self): - set_application_registry(self.ureg_bak) - - @allprotos + @classmethod + def setup_class(cls): + cls.ureg_bak = get_application_registry() + cls.ureg1 = UnitRegistry(None) + cls.ureg1.define("foo = [dim1]") + cls.ureg1.define("bar = foo / 2") + cls.ureg2 = UnitRegistry(None) + cls.ureg2.define("foo = [dim2]") + cls.ureg2.define("bar = foo / 3") + + @classmethod + def teardown_class(cls): + set_application_registry(cls.ureg_bak) + + @helpers.allprotos def test_quantity_1arg(self, protocol): set_application_registry(self.ureg1) q1 = Quantity("1 foo") @@ -199,7 +198,7 @@ class TestSwapApplicationRegistry(BaseTestCase, ParameterizedTestMixin): assert q2.to("bar").magnitude == 3 assert q3.to("bar").magnitude == 3 - @allprotos + @helpers.allprotos def test_quantity_2args(self, protocol): set_application_registry(self.ureg1) q1 = Quantity(1, "foo") @@ -213,7 +212,7 @@ class TestSwapApplicationRegistry(BaseTestCase, ParameterizedTestMixin): assert q2.to("bar").magnitude == 3 assert q3.to("bar").magnitude == 3 - @allprotos + @helpers.allprotos def test_unit(self, protocol): set_application_registry(self.ureg1) u1 = Unit("bar") @@ -224,8 +223,8 @@ class TestSwapApplicationRegistry(BaseTestCase, ParameterizedTestMixin): assert u2.dimensionality == {"[dim2]": 1} assert u3.dimensionality == {"[dim2]": 1} - @requires_uncertainties() - @allprotos + @helpers.requires_uncertainties() + @helpers.allprotos def test_measurement_2args(self, protocol): set_application_registry(self.ureg1) m1 = Measurement(Quantity(10, "foo"), Quantity(1, "foo")) @@ -236,15 +235,15 @@ class TestSwapApplicationRegistry(BaseTestCase, ParameterizedTestMixin): assert m1.dimensionality == {"[dim1]": 1} assert m2.dimensionality == {"[dim2]": 1} assert m3.dimensionality == {"[dim2]": 1} - self.assertEqual(m1.to("bar").value.magnitude, 20) - self.assertEqual(m2.to("bar").value.magnitude, 30) - self.assertEqual(m3.to("bar").value.magnitude, 30) - self.assertEqual(m1.to("bar").error.magnitude, 2) - self.assertEqual(m2.to("bar").error.magnitude, 3) - self.assertEqual(m3.to("bar").error.magnitude, 3) - - @requires_uncertainties() - @allprotos + assert m1.to("bar").value.magnitude == 20 + assert m2.to("bar").value.magnitude == 30 + assert m3.to("bar").value.magnitude == 30 + assert m1.to("bar").error.magnitude == 2 + assert m2.to("bar").error.magnitude == 3 + assert m3.to("bar").error.magnitude == 3 + + @helpers.requires_uncertainties() + @helpers.allprotos def test_measurement_3args(self, protocol): set_application_registry(self.ureg1) m1 = Measurement(10, 1, "foo") @@ -254,9 +253,9 @@ class TestSwapApplicationRegistry(BaseTestCase, ParameterizedTestMixin): assert m1.dimensionality == {"[dim1]": 1} assert m2.dimensionality == {"[dim2]": 1} - self.assertEqual(m1.to("bar").value.magnitude, 20) - self.assertEqual(m2.to("bar").value.magnitude, 30) - self.assertEqual(m3.to("bar").value.magnitude, 30) - self.assertEqual(m1.to("bar").error.magnitude, 2) - self.assertEqual(m2.to("bar").error.magnitude, 3) - self.assertEqual(m3.to("bar").error.magnitude, 3) + assert m1.to("bar").value.magnitude == 20 + assert m2.to("bar").value.magnitude == 30 + assert m3.to("bar").value.magnitude == 30 + assert m1.to("bar").error.magnitude == 2 + assert m2.to("bar").error.magnitude == 3 + assert m3.to("bar").error.magnitude == 3 diff --git a/pint/testsuite/test_babel.py b/pint/testsuite/test_babel.py index b3d5303..d889907 100644 --- a/pint/testsuite/test_babel.py +++ b/pint/testsuite/test_babel.py @@ -1,83 +1,82 @@ import os +import pytest + from pint import UnitRegistry -from pint.testsuite import BaseTestCase, helpers - - -class TestBabel(BaseTestCase): - @helpers.requires_not_babel() - def test_no_babel(self): - ureg = UnitRegistry() - distance = 24.0 * ureg.meter - self.assertRaises( - Exception, distance.format_babel, locale="fr_FR", length="long" - ) - - @helpers.requires_babel() - def test_format(self): - ureg = UnitRegistry() - dirname = os.path.dirname(__file__) - ureg.load_definitions(os.path.join(dirname, "../xtranslated.txt")) - - distance = 24.0 * ureg.meter - self.assertEqual( - distance.format_babel(locale="fr_FR", length="long"), "24.0 mètres" - ) - time = 8.0 * ureg.second - self.assertEqual( - time.format_babel(locale="fr_FR", length="long"), "8.0 secondes" - ) - self.assertEqual(time.format_babel(locale="ro", length="short"), "8.0 s") - acceleration = distance / time ** 2 - self.assertEqual( - acceleration.format_babel(locale="fr_FR", length="long"), - "0.375 mètre par seconde²", - ) - mks = ureg.get_system("mks") - self.assertEqual(mks.format_babel(locale="fr_FR"), "métrique") - - @helpers.requires_babel() - def test_registry_locale(self): - ureg = UnitRegistry(fmt_locale="fr_FR") - dirname = os.path.dirname(__file__) - ureg.load_definitions(os.path.join(dirname, "../xtranslated.txt")) - - distance = 24.0 * ureg.meter - self.assertEqual(distance.format_babel(length="long"), "24.0 mètres") - time = 8.0 * ureg.second - self.assertEqual(time.format_babel(length="long"), "8.0 secondes") - self.assertEqual(time.format_babel(locale="ro", length="short"), "8.0 s") - acceleration = distance / time ** 2 - self.assertEqual( - acceleration.format_babel(length="long"), "0.375 mètre par seconde²" - ) - mks = ureg.get_system("mks") - self.assertEqual(mks.format_babel(locale="fr_FR"), "métrique") - - @helpers.requires_babel() - def test_no_registry_locale(self): - ureg = UnitRegistry() - distance = 24.0 * ureg.meter - self.assertRaises(Exception, distance.format_babel) - - @helpers.requires_babel() - def test_str(self): - ureg = UnitRegistry() - d = 24.0 * ureg.meter - - s = "24.0 meter" - self.assertEqual(str(d), s) - self.assertEqual("%s" % d, s) - self.assertEqual("{}".format(d), s) - - ureg.set_fmt_locale("fr_FR") - s = "24.0 mètres" - self.assertEqual(str(d), s) - self.assertEqual("%s" % d, s) - self.assertEqual("{}".format(d), s) - - ureg.set_fmt_locale(None) - s = "24.0 meter" - self.assertEqual(str(d), s) - self.assertEqual("%s" % d, s) - self.assertEqual("{}".format(d), s) +from pint.testsuite import helpers + + +@helpers.requires_not_babel() +def test_no_babel(sess_registry): + ureg = sess_registry + distance = 24.0 * ureg.meter + with pytest.raises(Exception): + distance.format_babel(locale="fr_FR", length="long") + + +@helpers.requires_babel() +def test_format(sess_registry): + ureg = sess_registry + dirname = os.path.dirname(__file__) + ureg.load_definitions(os.path.join(dirname, "../xtranslated.txt")) + + distance = 24.0 * ureg.meter + assert distance.format_babel(locale="fr_FR", length="long") == "24.0 mètres" + time = 8.0 * ureg.second + assert time.format_babel(locale="fr_FR", length="long") == "8.0 secondes" + assert time.format_babel(locale="ro", length="short") == "8.0 s" + acceleration = distance / time ** 2 + assert ( + acceleration.format_babel(locale="fr_FR", length="long") + == "0.375 mètre par seconde²" + ) + mks = ureg.get_system("mks") + assert mks.format_babel(locale="fr_FR") == "métrique" + + +@helpers.requires_babel() +def test_registry_locale(): + ureg = UnitRegistry(fmt_locale="fr_FR") + dirname = os.path.dirname(__file__) + ureg.load_definitions(os.path.join(dirname, "../xtranslated.txt")) + + distance = 24.0 * ureg.meter + assert distance.format_babel(length="long") == "24.0 mètres" + time = 8.0 * ureg.second + assert time.format_babel(length="long") == "8.0 secondes" + assert time.format_babel(locale="ro", length="short") == "8.0 s" + acceleration = distance / time ** 2 + assert acceleration.format_babel(length="long") == "0.375 mètre par seconde²" + mks = ureg.get_system("mks") + assert mks.format_babel(locale="fr_FR") == "métrique" + + +@helpers.requires_babel() +def test_no_registry_locale(sess_registry): + ureg = sess_registry + distance = 24.0 * ureg.meter + with pytest.raises(Exception): + distance.format_babel() + + +@helpers.requires_babel() +def test_str(func_registry): + ureg = func_registry + d = 24.0 * ureg.meter + + s = "24.0 meter" + assert str(d) == s + assert "%s" % d == s + assert "{}".format(d) == s + + ureg.set_fmt_locale("fr_FR") + s = "24.0 mètres" + assert str(d) == s + assert "%s" % d == s + assert "{}".format(d) == s + + ureg.set_fmt_locale(None) + s = "24.0 meter" + assert str(d) == s + assert "%s" % d == s + assert "{}".format(d) == s diff --git a/pint/testsuite/test_compat.py b/pint/testsuite/test_compat.py index 926a392..5f3ba5d 100644 --- a/pint/testsuite/test_compat.py +++ b/pint/testsuite/test_compat.py @@ -1,23 +1,18 @@ import math from datetime import datetime, timedelta -import pytest +from pint.compat import eq, isnan, np, zero_or_nan +from pint.testsuite import helpers -from pint.compat import eq, isnan, zero_or_nan -from .helpers import requires_numpy - - -@pytest.mark.parametrize("check_all", [False, True]) +@helpers.check_all_bool def test_eq(check_all): assert eq(0, 0, check_all) assert not eq(0, 1, check_all) -@requires_numpy() +@helpers.requires_numpy def test_eq_numpy(): - import numpy as np - assert eq(np.array([1, 2]), np.array([1, 2]), True) assert not eq(np.array([1, 2]), np.array([1, 3]), True) np.testing.assert_equal( @@ -34,7 +29,7 @@ def test_eq_numpy(): assert not eq(np.array([1, 2]), 1, True) -@pytest.mark.parametrize("check_all", [False, True]) +@helpers.check_all_bool def test_isnan(check_all): assert not isnan(0, check_all) assert not isnan(0.0, check_all) @@ -44,10 +39,8 @@ def test_isnan(check_all): assert not isnan("foo", check_all) -@requires_numpy() +@helpers.requires_numpy def test_isnan_numpy(): - import numpy as np - assert isnan(np.nan, True) assert isnan(np.nan, False) assert not isnan(np.array([0, 0]), True) @@ -61,10 +54,8 @@ def test_isnan_numpy(): ) -@requires_numpy() +@helpers.requires_numpy def test_isnan_nat(): - import numpy as np - a = np.array(["2000-01-01", "NaT"], dtype="M8") b = np.array(["2000-01-01", "2000-01-02"], dtype="M8") assert isnan(a, True) @@ -79,7 +70,7 @@ def test_isnan_nat(): assert isnan(a[1], False) -@pytest.mark.parametrize("check_all", [False, True]) +@helpers.check_all_bool def test_zero_or_nan(check_all): assert zero_or_nan(0, check_all) assert zero_or_nan(math.nan, check_all) @@ -89,10 +80,8 @@ def test_zero_or_nan(check_all): assert not zero_or_nan("foo", check_all) -@requires_numpy() +@helpers.requires_numpy def test_zero_or_nan_numpy(): - import numpy as np - assert zero_or_nan(np.nan, True) assert zero_or_nan(np.nan, False) assert zero_or_nan(np.array([0, np.nan]), True) diff --git a/pint/testsuite/test_contexts.py b/pint/testsuite/test_contexts.py index b57a4df..7bdf0ff 100644 --- a/pint/testsuite/test_contexts.py +++ b/pint/testsuite/test_contexts.py @@ -1,7 +1,11 @@ import itertools +import logging import math +import re from collections import defaultdict +import pytest + from pint import ( DefinitionSyntaxError, DimensionalityError, @@ -9,7 +13,7 @@ from pint import ( UnitRegistry, ) from pint.context import Context -from pint.testsuite import QuantityTestCase +from pint.testsuite import helpers from pint.util import UnitsContainer @@ -81,44 +85,44 @@ def add_sharedargdef_ctxs(ureg): ureg.add_context(d) -class TestContexts(QuantityTestCase): - def test_known_context(self): +class TestContexts: + def test_known_context(self, func_registry): ureg = UnitRegistry() add_ctxs(ureg) with ureg.context("lc"): - self.assertTrue(ureg._active_ctx) - self.assertTrue(ureg._active_ctx.graph) + assert ureg._active_ctx + assert ureg._active_ctx.graph - self.assertFalse(ureg._active_ctx) - self.assertFalse(ureg._active_ctx.graph) + assert not ureg._active_ctx + assert not ureg._active_ctx.graph with ureg.context("lc", n=1): - self.assertTrue(ureg._active_ctx) - self.assertTrue(ureg._active_ctx.graph) + assert ureg._active_ctx + assert ureg._active_ctx.graph - self.assertFalse(ureg._active_ctx) - self.assertFalse(ureg._active_ctx.graph) + assert not ureg._active_ctx + assert not ureg._active_ctx.graph - def test_known_context_enable(self): + def test_known_context_enable(self, func_registry): ureg = UnitRegistry() add_ctxs(ureg) ureg.enable_contexts("lc") - self.assertTrue(ureg._active_ctx) - self.assertTrue(ureg._active_ctx.graph) + assert ureg._active_ctx + assert ureg._active_ctx.graph ureg.disable_contexts(1) - self.assertFalse(ureg._active_ctx) - self.assertFalse(ureg._active_ctx.graph) + assert not ureg._active_ctx + assert not ureg._active_ctx.graph ureg.enable_contexts("lc", n=1) - self.assertTrue(ureg._active_ctx) - self.assertTrue(ureg._active_ctx.graph) + assert ureg._active_ctx + assert ureg._active_ctx.graph ureg.disable_contexts(1) - self.assertFalse(ureg._active_ctx) - self.assertFalse(ureg._active_ctx.graph) + assert not ureg._active_ctx + assert not ureg._active_ctx.graph - def test_graph(self): + def test_graph(self, func_registry): ureg = UnitRegistry() add_ctxs(ureg) l = UnitsContainer({"[length]": 1.0}) # noqa: E741 @@ -135,29 +139,29 @@ class TestContexts(QuantityTestCase): g.update({l: {t, c}, t: {l}, c: {l}}) with ureg.context("lc"): - self.assertEqual(ureg._active_ctx.graph, g_sp) + assert ureg._active_ctx.graph == g_sp with ureg.context("lc", n=1): - self.assertEqual(ureg._active_ctx.graph, g_sp) + assert ureg._active_ctx.graph == g_sp with ureg.context("ab"): - self.assertEqual(ureg._active_ctx.graph, g_ab) + assert ureg._active_ctx.graph == g_ab with ureg.context("lc"): with ureg.context("ab"): - self.assertEqual(ureg._active_ctx.graph, g) + assert ureg._active_ctx.graph == g with ureg.context("ab"): with ureg.context("lc"): - self.assertEqual(ureg._active_ctx.graph, g) + assert ureg._active_ctx.graph == g with ureg.context("lc", "ab"): - self.assertEqual(ureg._active_ctx.graph, g) + assert ureg._active_ctx.graph == g with ureg.context("ab", "lc"): - self.assertEqual(ureg._active_ctx.graph, g) + assert ureg._active_ctx.graph == g - def test_graph_enable(self): + def test_graph_enable(self, func_registry): ureg = UnitRegistry() add_ctxs(ureg) l = UnitsContainer({"[length]": 1.0}) # noqa: E741 @@ -174,84 +178,84 @@ class TestContexts(QuantityTestCase): g.update({l: {t, c}, t: {l}, c: {l}}) ureg.enable_contexts("lc") - self.assertEqual(ureg._active_ctx.graph, g_sp) + assert ureg._active_ctx.graph == g_sp ureg.disable_contexts(1) ureg.enable_contexts("lc", n=1) - self.assertEqual(ureg._active_ctx.graph, g_sp) + assert ureg._active_ctx.graph == g_sp ureg.disable_contexts(1) ureg.enable_contexts("ab") - self.assertEqual(ureg._active_ctx.graph, g_ab) + assert ureg._active_ctx.graph == g_ab ureg.disable_contexts(1) ureg.enable_contexts("lc") ureg.enable_contexts("ab") - self.assertEqual(ureg._active_ctx.graph, g) + assert ureg._active_ctx.graph == g ureg.disable_contexts(2) ureg.enable_contexts("ab") ureg.enable_contexts("lc") - self.assertEqual(ureg._active_ctx.graph, g) + assert ureg._active_ctx.graph == g ureg.disable_contexts(2) ureg.enable_contexts("lc", "ab") - self.assertEqual(ureg._active_ctx.graph, g) + assert ureg._active_ctx.graph == g ureg.disable_contexts(2) ureg.enable_contexts("ab", "lc") - self.assertEqual(ureg._active_ctx.graph, g) + assert ureg._active_ctx.graph == g ureg.disable_contexts(2) - def test_known_nested_context(self): + def test_known_nested_context(self, func_registry): ureg = UnitRegistry() add_ctxs(ureg) with ureg.context("lc"): x = dict(ureg._active_ctx) y = dict(ureg._active_ctx.graph) - self.assertTrue(ureg._active_ctx) - self.assertTrue(ureg._active_ctx.graph) + assert ureg._active_ctx + assert ureg._active_ctx.graph with ureg.context("ab"): - self.assertTrue(ureg._active_ctx) - self.assertTrue(ureg._active_ctx.graph) - self.assertNotEqual(x, ureg._active_ctx) - self.assertNotEqual(y, ureg._active_ctx.graph) + assert ureg._active_ctx + assert ureg._active_ctx.graph + assert x != ureg._active_ctx + assert y != ureg._active_ctx.graph - self.assertEqual(x, ureg._active_ctx) - self.assertEqual(y, ureg._active_ctx.graph) + assert x == ureg._active_ctx + assert y == ureg._active_ctx.graph - self.assertFalse(ureg._active_ctx) - self.assertFalse(ureg._active_ctx.graph) + assert not ureg._active_ctx + assert not ureg._active_ctx.graph - def test_unknown_context(self): - ureg = UnitRegistry() + def test_unknown_context(self, func_registry): + ureg = func_registry add_ctxs(ureg) - with self.assertRaises(KeyError): + with pytest.raises(KeyError): with ureg.context("la"): pass - self.assertFalse(ureg._active_ctx) - self.assertFalse(ureg._active_ctx.graph) + assert not ureg._active_ctx + assert not ureg._active_ctx.graph - def test_unknown_nested_context(self): + def test_unknown_nested_context(self, func_registry): ureg = UnitRegistry() add_ctxs(ureg) with ureg.context("lc"): x = dict(ureg._active_ctx) y = dict(ureg._active_ctx.graph) - with self.assertRaises(KeyError): + with pytest.raises(KeyError): with ureg.context("la"): pass - self.assertEqual(x, ureg._active_ctx) - self.assertEqual(y, ureg._active_ctx.graph) + assert x == ureg._active_ctx + assert y == ureg._active_ctx.graph - self.assertFalse(ureg._active_ctx) - self.assertFalse(ureg._active_ctx.graph) + assert not ureg._active_ctx + assert not ureg._active_ctx.graph - def test_one_context(self): + def test_one_context(self, func_registry): ureg = UnitRegistry() add_ctxs(ureg) @@ -262,14 +266,16 @@ class TestContexts(QuantityTestCase): meter_units = ureg.get_compatible_units(ureg.meter) hertz_units = ureg.get_compatible_units(ureg.hertz) - self.assertRaises(DimensionalityError, q.to, "Hz") + with pytest.raises(DimensionalityError): + q.to("Hz") with ureg.context("lc"): - self.assertEqual(q.to("Hz"), s) - self.assertEqual(ureg.get_compatible_units(q), meter_units | hertz_units) - self.assertRaises(DimensionalityError, q.to, "Hz") - self.assertEqual(ureg.get_compatible_units(q), meter_units) + assert q.to("Hz") == s + assert ureg.get_compatible_units(q) == meter_units | hertz_units + with pytest.raises(DimensionalityError): + q.to("Hz") + assert ureg.get_compatible_units(q) == meter_units - def test_multiple_context(self): + def test_multiple_context(self, func_registry): ureg = UnitRegistry() add_ctxs(ureg) @@ -281,16 +287,18 @@ class TestContexts(QuantityTestCase): hertz_units = ureg.get_compatible_units(ureg.hertz) ampere_units = ureg.get_compatible_units(ureg.ampere) - self.assertRaises(DimensionalityError, q.to, "Hz") + with pytest.raises(DimensionalityError): + q.to("Hz") with ureg.context("lc", "ab"): - self.assertEqual(q.to("Hz"), s) - self.assertEqual( - ureg.get_compatible_units(q), meter_units | hertz_units | ampere_units + assert q.to("Hz") == s + assert ( + ureg.get_compatible_units(q) == meter_units | hertz_units | ampere_units ) - self.assertRaises(DimensionalityError, q.to, "Hz") - self.assertEqual(ureg.get_compatible_units(q), meter_units) + with pytest.raises(DimensionalityError): + q.to("Hz") + assert ureg.get_compatible_units(q) == meter_units - def test_nested_context(self): + def test_nested_context(self, func_registry): ureg = UnitRegistry() add_ctxs(ureg) @@ -298,20 +306,23 @@ class TestContexts(QuantityTestCase): q = 500 * ureg.meter s = (ureg.speed_of_light / q).to("Hz") - self.assertRaises(DimensionalityError, q.to, "Hz") + with pytest.raises(DimensionalityError): + q.to("Hz") with ureg.context("lc"): - self.assertEqual(q.to("Hz"), s) + assert q.to("Hz") == s with ureg.context("ab"): - self.assertEqual(q.to("Hz"), s) - self.assertEqual(q.to("Hz"), s) + assert q.to("Hz") == s + assert q.to("Hz") == s with ureg.context("ab"): - self.assertRaises(DimensionalityError, q.to, "Hz") + with pytest.raises(DimensionalityError): + q.to("Hz") with ureg.context("lc"): - self.assertEqual(q.to("Hz"), s) - self.assertRaises(DimensionalityError, q.to, "Hz") + assert q.to("Hz") == s + with pytest.raises(DimensionalityError): + q.to("Hz") - def test_context_with_arg(self): + def test_context_with_arg(self, func_registry): ureg = UnitRegistry() @@ -320,23 +331,27 @@ class TestContexts(QuantityTestCase): q = 500 * ureg.meter s = (ureg.speed_of_light / q).to("Hz") - self.assertRaises(DimensionalityError, q.to, "Hz") + with pytest.raises(DimensionalityError): + q.to("Hz") with ureg.context("lc", n=1): - self.assertEqual(q.to("Hz"), s) + assert q.to("Hz") == s with ureg.context("ab"): - self.assertEqual(q.to("Hz"), s) - self.assertEqual(q.to("Hz"), s) + assert q.to("Hz") == s + assert q.to("Hz") == s with ureg.context("ab"): - self.assertRaises(DimensionalityError, q.to, "Hz") + with pytest.raises(DimensionalityError): + q.to("Hz") with ureg.context("lc", n=1): - self.assertEqual(q.to("Hz"), s) - self.assertRaises(DimensionalityError, q.to, "Hz") + assert q.to("Hz") == s + with pytest.raises(DimensionalityError): + q.to("Hz") with ureg.context("lc"): - self.assertRaises(TypeError, q.to, "Hz") + with pytest.raises(TypeError): + q.to("Hz") - def test_enable_context_with_arg(self): + def test_enable_context_with_arg(self, func_registry): ureg = UnitRegistry() @@ -345,28 +360,32 @@ class TestContexts(QuantityTestCase): q = 500 * ureg.meter s = (ureg.speed_of_light / q).to("Hz") - self.assertRaises(DimensionalityError, q.to, "Hz") + with pytest.raises(DimensionalityError): + q.to("Hz") ureg.enable_contexts("lc", n=1) - self.assertEqual(q.to("Hz"), s) + assert q.to("Hz") == s ureg.enable_contexts("ab") - self.assertEqual(q.to("Hz"), s) - self.assertEqual(q.to("Hz"), s) + assert q.to("Hz") == s + assert q.to("Hz") == s ureg.disable_contexts(1) ureg.disable_contexts(1) ureg.enable_contexts("ab") - self.assertRaises(DimensionalityError, q.to, "Hz") + with pytest.raises(DimensionalityError): + q.to("Hz") ureg.enable_contexts("lc", n=1) - self.assertEqual(q.to("Hz"), s) + assert q.to("Hz") == s ureg.disable_contexts(1) - self.assertRaises(DimensionalityError, q.to, "Hz") + with pytest.raises(DimensionalityError): + q.to("Hz") ureg.disable_contexts(1) ureg.enable_contexts("lc") - self.assertRaises(TypeError, q.to, "Hz") + with pytest.raises(TypeError): + q.to("Hz") ureg.disable_contexts(1) - def test_context_with_arg_def(self): + def test_context_with_arg_def(self, func_registry): ureg = UnitRegistry() @@ -375,33 +394,39 @@ class TestContexts(QuantityTestCase): q = 500 * ureg.meter s = (ureg.speed_of_light / q).to("Hz") - self.assertRaises(DimensionalityError, q.to, "Hz") + with pytest.raises(DimensionalityError): + q.to("Hz") with ureg.context("lc"): - self.assertEqual(q.to("Hz"), s) + assert q.to("Hz") == s with ureg.context("ab"): - self.assertEqual(q.to("Hz"), s) - self.assertEqual(q.to("Hz"), s) + assert q.to("Hz") == s + assert q.to("Hz") == s with ureg.context("ab"): - self.assertRaises(DimensionalityError, q.to, "Hz") + with pytest.raises(DimensionalityError): + q.to("Hz") with ureg.context("lc"): - self.assertEqual(q.to("Hz"), s) - self.assertRaises(DimensionalityError, q.to, "Hz") + assert q.to("Hz") == s + with pytest.raises(DimensionalityError): + q.to("Hz") - self.assertRaises(DimensionalityError, q.to, "Hz") + with pytest.raises(DimensionalityError): + q.to("Hz") with ureg.context("lc", n=2): - self.assertEqual(q.to("Hz"), s / 2) + assert q.to("Hz") == s / 2 with ureg.context("ab"): - self.assertEqual(q.to("Hz"), s / 2) - self.assertEqual(q.to("Hz"), s / 2) + assert q.to("Hz") == s / 2 + assert q.to("Hz") == s / 2 with ureg.context("ab"): - self.assertRaises(DimensionalityError, q.to, "Hz") + with pytest.raises(DimensionalityError): + q.to("Hz") with ureg.context("lc", n=2): - self.assertEqual(q.to("Hz"), s / 2) - self.assertRaises(DimensionalityError, q.to, "Hz") + assert q.to("Hz") == s / 2 + with pytest.raises(DimensionalityError): + q.to("Hz") - def test_context_with_sharedarg_def(self): + def test_context_with_sharedarg_def(self, func_registry): ureg = UnitRegistry() @@ -412,63 +437,66 @@ class TestContexts(QuantityTestCase): u = (1 / 500) * ureg.ampere with ureg.context("lc"): - self.assertEqual(q.to("Hz"), s) + assert q.to("Hz") == s with ureg.context("ab"): - self.assertEqual(q.to("ampere"), u) + assert q.to("ampere") == u with ureg.context("ab"): - self.assertEqual(q.to("ampere"), 0 * u) + assert q.to("ampere") == 0 * u with ureg.context("lc"): - self.assertRaises(ZeroDivisionError, ureg.Quantity.to, q, "Hz") + with pytest.raises(ZeroDivisionError): + ureg.Quantity.to(q, "Hz") with ureg.context("lc", n=2): - self.assertEqual(q.to("Hz"), s / 2) + assert q.to("Hz") == s / 2 with ureg.context("ab"): - self.assertEqual(q.to("ampere"), 2 * u) + assert q.to("ampere") == 2 * u with ureg.context("ab", n=3): - self.assertEqual(q.to("ampere"), 3 * u) + assert q.to("ampere") == 3 * u with ureg.context("lc"): - self.assertEqual(q.to("Hz"), s / 3) + assert q.to("Hz") == s / 3 with ureg.context("lc", n=2): - self.assertEqual(q.to("Hz"), s / 2) + assert q.to("Hz") == s / 2 with ureg.context("ab", n=4): - self.assertEqual(q.to("ampere"), 4 * u) + assert q.to("ampere") == 4 * u with ureg.context("ab", n=3): - self.assertEqual(q.to("ampere"), 3 * u) + assert q.to("ampere") == 3 * u with ureg.context("lc", n=6): - self.assertEqual(q.to("Hz"), s / 6) + assert q.to("Hz") == s / 6 - def test_anonymous_context(self): + def test_anonymous_context(self, func_registry): ureg = UnitRegistry() c = Context() c.add_transformation("[length]", "[time]", lambda ureg, x: x / ureg("5 cm/s")) - self.assertRaises(ValueError, ureg.add_context, c) + with pytest.raises(ValueError): + ureg.add_context(c) x = ureg("10 cm") expect = ureg("2 s") - self.assertQuantityEqual(x.to("s", c), expect) + helpers.assert_quantity_equal(x.to("s", c), expect) with ureg.context(c): - self.assertQuantityEqual(x.to("s"), expect) + helpers.assert_quantity_equal(x.to("s"), expect) ureg.enable_contexts(c) - self.assertQuantityEqual(x.to("s"), expect) + helpers.assert_quantity_equal(x.to("s"), expect) ureg.disable_contexts(1) - self.assertRaises(DimensionalityError, x.to, "s") + with pytest.raises(DimensionalityError): + x.to("s") # Multiple anonymous contexts c2 = Context() c2.add_transformation("[length]", "[time]", lambda ureg, x: x / ureg("10 cm/s")) c2.add_transformation("[mass]", "[time]", lambda ureg, x: x / ureg("10 kg/s")) with ureg.context(c2, c): - self.assertQuantityEqual(x.to("s"), expect) + helpers.assert_quantity_equal(x.to("s"), expect) # Transformations only in c2 are still working even if c takes priority - self.assertQuantityEqual(ureg("100 kg").to("s"), ureg("10 s")) + helpers.assert_quantity_equal(ureg("100 kg").to("s"), ureg("10 s")) with ureg.context(c, c2): - self.assertQuantityEqual(x.to("s"), ureg("1 s")) + helpers.assert_quantity_equal(x.to("s"), ureg("1 s")) def _test_ctx(self, ctx): ureg = UnitRegistry() @@ -477,30 +505,32 @@ class TestContexts(QuantityTestCase): nctx = len(ureg._contexts) - self.assertNotIn(ctx.name, ureg._contexts) + assert ctx.name not in ureg._contexts ureg.add_context(ctx) - self.assertIn(ctx.name, ureg._contexts) - self.assertEqual(len(ureg._contexts), nctx + 1 + len(ctx.aliases)) + assert ctx.name in ureg._contexts + assert len(ureg._contexts) == nctx + 1 + len(ctx.aliases) with ureg.context(ctx.name): - self.assertEqual(q.to("Hz"), s) - self.assertEqual(s.to("meter"), q) + assert q.to("Hz") == s + assert s.to("meter") == q ureg.remove_context(ctx.name) - self.assertNotIn(ctx.name, ureg._contexts) - self.assertEqual(len(ureg._contexts), nctx) + assert ctx.name not in ureg._contexts + assert len(ureg._contexts) == nctx - def test_parse_invalid(self): - for badrow in ( + @pytest.mark.parametrize( + "badrow", + ( "[length] = 1 / [time]: c / value", "1 / [time] = [length]: c / value", "[length] <- [time] = c / value", "[length] - [time] = c / value", - ): - with self.subTest(badrow): - with self.assertRaises(DefinitionSyntaxError): - Context.from_lines(["@context c", badrow]) + ), + ) + def test_parse_invalid(self, badrow): + with pytest.raises(DefinitionSyntaxError): + Context.from_lines(["@context c", badrow]) def test_parse_simple(self): @@ -518,19 +548,19 @@ class TestContexts(QuantityTestCase): ] c = Context.from_lines(s) - self.assertEqual(c.name, "longcontextname") - self.assertEqual(c.aliases, ()) - self.assertEqual(c.defaults, {}) - self.assertEqual(c.funcs.keys(), {a, b}) + assert c.name == "longcontextname" + assert c.aliases == () + assert c.defaults == {} + assert c.funcs.keys() == {a, b} self._test_ctx(c) s = ["@context longcontextname = lc", "[length] <-> 1 / [time]: c / value"] c = Context.from_lines(s) - self.assertEqual(c.name, "longcontextname") - self.assertEqual(c.aliases, ("lc",)) - self.assertEqual(c.defaults, {}) - self.assertEqual(c.funcs.keys(), {a, b}) + assert c.name == "longcontextname" + assert c.aliases == ("lc",) + assert c.defaults == {} + assert c.funcs.keys() == {a, b} self._test_ctx(c) s = [ @@ -539,10 +569,10 @@ class TestContexts(QuantityTestCase): ] c = Context.from_lines(s) - self.assertEqual(c.name, "longcontextname") - self.assertEqual(c.aliases, ("lc", "lcn")) - self.assertEqual(c.defaults, {}) - self.assertEqual(c.funcs.keys(), {a, b}) + assert c.name == "longcontextname" + assert c.aliases == ("lc", "lcn") + assert c.defaults == {} + assert c.funcs.keys() == {a, b} self._test_ctx(c) def test_parse_auto_inverse(self): @@ -557,8 +587,8 @@ class TestContexts(QuantityTestCase): s = ["@context longcontextname", "[length] <-> 1 / [time]: c / value"] c = Context.from_lines(s) - self.assertEqual(c.defaults, {}) - self.assertEqual(c.funcs.keys(), {a, b}) + assert c.defaults == {} + assert c.funcs.keys() == {a, b} self._test_ctx(c) def test_parse_define(self): @@ -571,8 +601,8 @@ class TestContexts(QuantityTestCase): s = ["@context longcontextname", "[length] <-> 1 / [time]: c / value"] c = Context.from_lines(s) - self.assertEqual(c.defaults, {}) - self.assertEqual(c.funcs.keys(), {a, b}) + assert c.defaults == {} + assert c.funcs.keys() == {a, b} self._test_ctx(c) def test_parse_parameterized(self): @@ -586,8 +616,8 @@ class TestContexts(QuantityTestCase): s = ["@context(n=1) longcontextname", "[length] <-> 1 / [time]: n * c / value"] c = Context.from_lines(s) - self.assertEqual(c.defaults, {"n": 1}) - self.assertEqual(c.funcs.keys(), {a, b}) + assert c.defaults == {"n": 1} + assert c.funcs.keys() == {a, b} self._test_ctx(c) s = [ @@ -596,36 +626,42 @@ class TestContexts(QuantityTestCase): ] c = Context.from_lines(s) - self.assertEqual(c.defaults, {"n": 1, "bla": 2}) - self.assertEqual(c.funcs.keys(), {a, b}) + assert c.defaults == {"n": 1, "bla": 2} + assert c.funcs.keys() == {a, b} # If the variable is not present in the definition, then raise an error s = ["@context(n=1) longcontextname", "[length] <-> 1 / [time]: c / value"] - self.assertRaises(DefinitionSyntaxError, Context.from_lines, s) + with pytest.raises(DefinitionSyntaxError): + Context.from_lines(s) - def test_warnings(self): + def test_warnings(self, caplog): ureg = UnitRegistry() - with self.capture_log() as buffer: + with caplog.at_level(logging.DEBUG, "pint"): add_ctxs(ureg) d = Context("ab") ureg.add_context(d) - self.assertEqual(len(buffer), 1) - self.assertIn("ab", str(buffer[-1])) + assert len(caplog.records) == 1 + assert "ab" in str(caplog.records[-1].args) d = Context("ab1", aliases=("ab",)) ureg.add_context(d) - self.assertEqual(len(buffer), 2) - self.assertIn("ab", str(buffer[-1])) + assert len(caplog.records) == 2 + assert "ab" in str(caplog.records[-1].args) -class TestDefinedContexts(QuantityTestCase): +class TestDefinedContexts: + @classmethod + def setup_class(cls): + cls.ureg = UnitRegistry() - FORCE_NDARRAY = False + @classmethod + def teardown_class(cls): + cls.ureg = None def test_defined(self): ureg = self.ureg @@ -638,11 +674,11 @@ class TestDefinedContexts(QuantityTestCase): b = Context.__keytransform__( UnitsContainer({"[length]": 1.0}), UnitsContainer({"[time]": -1.0}) ) - self.assertIn(a, ureg._contexts["sp"].funcs) - self.assertIn(b, ureg._contexts["sp"].funcs) + assert a in ureg._contexts["sp"].funcs + assert b in ureg._contexts["sp"].funcs with ureg.context("sp"): - self.assertIn(a, ureg._active_ctx) - self.assertIn(b, ureg._active_ctx) + assert a in ureg._active_ctx + assert b in ureg._active_ctx def test_spectroscopy(self): ureg = self.ureg @@ -659,18 +695,18 @@ class TestDefinedContexts(QuantityTestCase): a.dimensionality, b.dimensionality ) p = find_shortest_path(ureg._active_ctx.graph, da, db) - self.assertTrue(p) + assert p msg = "{} <-> {}".format(a, b) # assertAlmostEqualRelError converts second to first - self.assertQuantityAlmostEqual(b, a, rtol=0.01, msg=msg) + helpers.assert_quantity_almost_equal(b, a, rtol=0.01, msg=msg) for a, b in itertools.product(eq, eq): - self.assertQuantityAlmostEqual(a.to(b.units, "sp"), b, rtol=0.01) + helpers.assert_quantity_almost_equal(a.to(b.units, "sp"), b, rtol=0.01) def test_textile(self): ureg = self.ureg qty_direct = 1.331 * ureg.tex - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): qty_indirect = qty_direct.to("Nm") with ureg.context("textile"): @@ -681,18 +717,23 @@ class TestDefinedContexts(QuantityTestCase): b = qty_indirect.to_base_units() da, db = Context.__keytransform__(a.dimensionality, b.dimensionality) p = find_shortest_path(ureg._active_ctx.graph, da, db) - self.assertTrue(p) + assert p msg = "{} <-> {}".format(a, b) - self.assertQuantityAlmostEqual(b, a, rtol=0.01, msg=msg) + helpers.assert_quantity_almost_equal(b, a, rtol=0.01, msg=msg) # Check RKM <-> cN/tex conversion - self.assertQuantityAlmostEqual(1 * ureg.RKM, 0.980665 * ureg.cN / ureg.tex) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( + 1 * ureg.RKM, 0.980665 * ureg.cN / ureg.tex + ) + helpers.assert_quantity_almost_equal( (1 / 0.980665) * ureg.RKM, 1 * ureg.cN / ureg.tex ) - self.assertAlmostEqual((1 * ureg.RKM).to(ureg.cN / ureg.tex).m, 0.980665) - self.assertAlmostEqual( - (1 * ureg.cN / ureg.tex).to(ureg.RKM).m, 1 / 0.980665 + assert ( + round(abs((1 * ureg.RKM).to(ureg.cN / ureg.tex).m - 0.980665), 7) == 0 + ) + assert ( + round(abs((1 * ureg.cN / ureg.tex).to(ureg.RKM).m - 1 / 0.980665), 7) + == 0 ) def test_decorator(self): @@ -705,13 +746,14 @@ class TestDefinedContexts(QuantityTestCase): def f(wl): return wl.to("terahertz") - self.assertRaises(DimensionalityError, f, a) + with pytest.raises(DimensionalityError): + f(a) @ureg.with_context("sp") def g(wl): return wl.to("terahertz") - self.assertEqual(b, g(a)) + assert b == g(a) def test_decorator_composition(self): ureg = self.ureg @@ -730,256 +772,257 @@ class TestDefinedContexts(QuantityTestCase): def g(wl): return wl.to("terahertz") - self.assertEqual(b, f(a)) - self.assertEqual(b, g(a)) - - -class TestContextRedefinitions(QuantityTestCase): - def test_redefine(self): - ureg = UnitRegistry( - """ - foo = [d] = f = foo_alias - bar = 2 foo = b = bar_alias - baz = 3 bar = _ = baz_alias - asd = 4 baz - - @context c - # Note how we're redefining a symbol, not the base name, as a - # function of another name - b = 5 f - """.splitlines() - ) - # Units that are somehow directly or indirectly defined as a function of the - # overridden unit are also affected - foo = ureg.Quantity(1, "foo") - bar = ureg.Quantity(1, "bar") - asd = ureg.Quantity(1, "asd") - - # Test without context before and after, to verify that the cache and units have - # not been polluted - for enable_ctx in (False, True, False): - with self.subTest(enable_ctx): - if enable_ctx: - ureg.enable_contexts("c") - k = 5 - else: - k = 2 - - self.assertEqual(foo.to("b").magnitude, 1 / k) - self.assertEqual(foo.to("bar").magnitude, 1 / k) - self.assertEqual(foo.to("bar_alias").magnitude, 1 / k) - self.assertEqual(foo.to("baz").magnitude, 1 / k / 3) - self.assertEqual(bar.to("foo").magnitude, k) - self.assertEqual(bar.to("baz").magnitude, 1 / 3) - self.assertEqual(asd.to("foo").magnitude, 4 * 3 * k) - self.assertEqual(asd.to("bar").magnitude, 4 * 3) - self.assertEqual(asd.to("baz").magnitude, 4) - - ureg.disable_contexts() - - def test_define_nan(self): - ureg = UnitRegistry( - """ - USD = [currency] - EUR = nan USD - GBP = nan USD - - @context c - EUR = 1.11 USD - # Note that we're changing which unit GBP is defined against - GBP = 1.18 EUR - @end - """.splitlines() - ) + assert b == f(a) + assert b == g(a) + + +def test_redefine(subtests): + ureg = UnitRegistry( + """ + foo = [d] = f = foo_alias + bar = 2 foo = b = bar_alias + baz = 3 bar = _ = baz_alias + asd = 4 baz + + @context c + # Note how we're redefining a symbol, not the base name, as a + # function of another name + b = 5 f + """.splitlines() + ) + # Units that are somehow directly or indirectly defined as a function of the + # overridden unit are also affected + foo = ureg.Quantity(1, "foo") + bar = ureg.Quantity(1, "bar") + asd = ureg.Quantity(1, "asd") + + # Test without context before and after, to verify that the cache and units have + # not been polluted + for enable_ctx in (False, True, False): + with subtests.test(enable_ctx): + if enable_ctx: + ureg.enable_contexts("c") + k = 5 + else: + k = 2 + + assert foo.to("b").magnitude == 1 / k + assert foo.to("bar").magnitude == 1 / k + assert foo.to("bar_alias").magnitude == 1 / k + assert foo.to("baz").magnitude == 1 / k / 3 + assert bar.to("foo").magnitude == k + assert bar.to("baz").magnitude == 1 / 3 + assert asd.to("foo").magnitude == 4 * 3 * k + assert asd.to("bar").magnitude == 4 * 3 + assert asd.to("baz").magnitude == 4 + + ureg.disable_contexts() + + +def test_define_nan(): + ureg = UnitRegistry( + """ + USD = [currency] + EUR = nan USD + GBP = nan USD + + @context c + EUR = 1.11 USD + # Note that we're changing which unit GBP is defined against + GBP = 1.18 EUR + @end + """.splitlines() + ) + + q = ureg.Quantity("10 GBP") + assert q.magnitude == 10 + assert q.units.dimensionality == {"[currency]": 1} + assert q.to("GBP").magnitude == 10 + assert math.isnan(q.to("USD").magnitude) + assert round(abs(q.to("USD", "c").magnitude - 10 * 1.18 * 1.11), 7) == 0 + + +def test_non_multiplicative(subtests): + ureg = UnitRegistry( + """ + kelvin = [temperature] + fahrenheit = 5 / 9 * kelvin; offset: 255 + bogodegrees = 9 * kelvin + + @context nonmult_to_nonmult + fahrenheit = 7 * kelvin; offset: 123 + @end + @context nonmult_to_mult + fahrenheit = 123 * kelvin + @end + @context mult_to_nonmult + bogodegrees = 5 * kelvin; offset: 123 + @end + """.splitlines() + ) + k = ureg.Quantity(100, "kelvin") + + with subtests.test("baseline"): + assert round(abs(k.to("fahrenheit").magnitude - (100 - 255) * 9 / 5), 7) == 0 + assert round(abs(k.to("bogodegrees").magnitude - 100 / 9), 7) == 0 + + with subtests.test("nonmult_to_nonmult"): + with ureg.context("nonmult_to_nonmult"): + assert round(abs(k.to("fahrenheit").magnitude - (100 - 123) / 7), 7) == 0 + + with subtests.test("nonmult_to_mult"): + with ureg.context("nonmult_to_mult"): + assert round(abs(k.to("fahrenheit").magnitude - 100 / 123), 7) == 0 + + with subtests.test("mult_to_nonmult"): + with ureg.context("mult_to_nonmult"): + assert round(abs(k.to("bogodegrees").magnitude - (100 - 123) / 5), 7) == 0 + + +def test_stack_contexts(): + ureg = UnitRegistry( + """ + a = [dim1] + b = 1/2 a + c = 1/3 a + d = [dim2] + + @context c1 + b = 1/4 a + c = 1/6 a + [dim1]->[dim2]: value * 2 d/a + @end + @context c2 + b = 1/5 a + [dim1]->[dim2]: value * 3 d/a + @end + """.splitlines() + ) + q = ureg.Quantity(1, "a") + assert q.to("b").magnitude == 2 + assert q.to("c").magnitude == 3 + assert q.to("b", "c1").magnitude == 4 + assert q.to("c", "c1").magnitude == 6 + assert q.to("d", "c1").magnitude == 2 + assert q.to("b", "c2").magnitude == 5 + assert q.to("c", "c2").magnitude == 3 + assert q.to("d", "c2").magnitude == 3 + assert q.to("b", "c1", "c2").magnitude == 5 # c2 takes precedence + assert q.to("c", "c1", "c2").magnitude == 6 # c2 doesn't change it, so use c1 + assert q.to("d", "c1", "c2").magnitude == 3 # c2 takes precedence + + +def test_err_to_base_unit(): + expected = "Can't define base units within a context" + with pytest.raises(DefinitionSyntaxError, match=expected): + Context.from_lines(["@context c", "x = [d]"]) + + +def test_err_change_base_unit(): + ureg = UnitRegistry( + """ + foo = [d1] + bar = [d2] + + @context c + bar = foo + @end + """.splitlines() + ) - q = ureg.Quantity("10 GBP") - self.assertEquals(q.magnitude, 10) - self.assertEquals(q.units.dimensionality, {"[currency]": 1}) - self.assertEquals(q.to("GBP").magnitude, 10) - self.assertTrue(math.isnan(q.to("USD").magnitude)) - self.assertAlmostEqual(q.to("USD", "c").magnitude, 10 * 1.18 * 1.11) - - def test_non_multiplicative(self): - ureg = UnitRegistry( - """ - kelvin = [temperature] - fahrenheit = 5 / 9 * kelvin; offset: 255 - bogodegrees = 9 * kelvin - - @context nonmult_to_nonmult - fahrenheit = 7 * kelvin; offset: 123 - @end - @context nonmult_to_mult - fahrenheit = 123 * kelvin - @end - @context mult_to_nonmult - bogodegrees = 5 * kelvin; offset: 123 - @end - """.splitlines() - ) - k = ureg.Quantity(100, "kelvin") - - with self.subTest("baseline"): - self.assertAlmostEqual(k.to("fahrenheit").magnitude, (100 - 255) * 9 / 5) - self.assertAlmostEqual(k.to("bogodegrees").magnitude, 100 / 9) - - with self.subTest("nonmult_to_nonmult"): - with ureg.context("nonmult_to_nonmult"): - self.assertAlmostEqual(k.to("fahrenheit").magnitude, (100 - 123) / 7) - - with self.subTest("nonmult_to_mult"): - with ureg.context("nonmult_to_mult"): - self.assertAlmostEqual(k.to("fahrenheit").magnitude, 100 / 123) - - with self.subTest("mult_to_nonmult"): - with ureg.context("mult_to_nonmult"): - self.assertAlmostEqual(k.to("bogodegrees").magnitude, (100 - 123) / 5) - - def test_stack_contexts(self): - ureg = UnitRegistry( - """ - a = [dim1] - b = 1/2 a - c = 1/3 a - d = [dim2] - - @context c1 - b = 1/4 a - c = 1/6 a - [dim1]->[dim2]: value * 2 d/a - @end - @context c2 - b = 1/5 a - [dim1]->[dim2]: value * 3 d/a - @end - """.splitlines() - ) - q = ureg.Quantity(1, "a") - assert q.to("b").magnitude == 2 - assert q.to("c").magnitude == 3 - assert q.to("b", "c1").magnitude == 4 - assert q.to("c", "c1").magnitude == 6 - assert q.to("d", "c1").magnitude == 2 - assert q.to("b", "c2").magnitude == 5 - assert q.to("c", "c2").magnitude == 3 - assert q.to("d", "c2").magnitude == 3 - assert q.to("b", "c1", "c2").magnitude == 5 # c2 takes precedence - assert q.to("c", "c1", "c2").magnitude == 6 # c2 doesn't change it, so use c1 - assert q.to("d", "c1", "c2").magnitude == 3 # c2 takes precedence - - def test_err_to_base_unit(self): - with self.assertRaises(DefinitionSyntaxError) as e: - Context.from_lines(["@context c", "x = [d]"]) - self.assertEquals(str(e.exception), "Can't define base units within a context") - - def test_err_change_base_unit(self): - ureg = UnitRegistry( - """ - foo = [d1] - bar = [d2] - - @context c - bar = foo - @end - """.splitlines() - ) + expected = "Can't redefine a base unit to a derived one" + with pytest.raises(ValueError, match=expected): + ureg.enable_contexts("c") - with self.assertRaises(ValueError) as e: - ureg.enable_contexts("c") - self.assertEquals( - str(e.exception), "Can't redefine a base unit to a derived one" - ) - def test_err_change_dimensionality(self): - ureg = UnitRegistry( - """ - foo = [d1] - bar = [d2] - baz = foo - - @context c - baz = bar - @end - """.splitlines() - ) - with self.assertRaises(ValueError) as e: - ureg.enable_contexts("c") - self.assertEquals( - str(e.exception), - "Can't change dimensionality of baz from [d1] to [d2] in a context", - ) +def test_err_change_dimensionality(): + ureg = UnitRegistry( + """ + foo = [d1] + bar = [d2] + baz = foo - def test_err_cyclic_dependency(self): - ureg = UnitRegistry( - """ - foo = [d] - bar = foo + @context c baz = bar + @end + """.splitlines() + ) + expected = re.escape( + "Can't change dimensionality of baz from [d1] to [d2] in a context" + ) + with pytest.raises(ValueError, match=expected): + ureg.enable_contexts("c") - @context c - bar = baz - @end - """.splitlines() - ) - # TODO align this exception and the one you get when you implement a cyclic - # dependency within the base registry. Ideally this exception should be - # raised by enable_contexts. + +def test_err_cyclic_dependency(): + ureg = UnitRegistry( + """ + foo = [d] + bar = foo + baz = bar + + @context c + bar = baz + @end + """.splitlines() + ) + # TODO align this exception and the one you get when you implement a cyclic + # dependency within the base registry. Ideally this exception should be + # raised by enable_contexts. + ureg.enable_contexts("c") + q = ureg.Quantity("bar") + with pytest.raises(RecursionError): + q.to("foo") + + +def test_err_dimension_redefinition(): + expected = re.escape("Expected <unit> = <converter>; got [d1] = [d2] * [d3]") + with pytest.raises(DefinitionSyntaxError, match=expected): + Context.from_lines(["@context c", "[d1] = [d2] * [d3]"]) + + +def test_err_prefix_redefinition(): + expected = re.escape("Expected <unit> = <converter>; got [d1] = [d2] * [d3]") + with pytest.raises(DefinitionSyntaxError, match=expected): + Context.from_lines(["@context c", "[d1] = [d2] * [d3]"]) + + +def test_err_redefine_alias(subtests): + expected = "Can't change a unit's symbol or aliases within a context" + for s in ("foo = bar = f", "foo = bar = _ = baz"): + with subtests.test(s): + with pytest.raises(DefinitionSyntaxError, match=expected): + Context.from_lines(["@context c", s]) + + +def test_err_redefine_with_prefix(): + ureg = UnitRegistry( + """ + kilo- = 1000 + gram = [mass] + pound = 454 gram + + @context c + kilopound = 500000 gram + @end + """.splitlines() + ) + + expected = "Can't redefine a unit with a prefix: kilopound" + with pytest.raises(ValueError, match=expected): ureg.enable_contexts("c") - q = ureg.Quantity("bar") - with self.assertRaises(RecursionError): - q.to("foo") - - def test_err_dimension_redefinition(self): - with self.assertRaises(DefinitionSyntaxError) as e: - Context.from_lines(["@context c", "[d1] = [d2] * [d3]"]) - self.assertEquals( - str(e.exception), "Expected <unit> = <converter>; got [d1] = [d2] * [d3]" - ) - def test_err_prefix_redefinition(self): - with self.assertRaises(DefinitionSyntaxError) as e: - Context.from_lines(["@context c", "[d1] = [d2] * [d3]"]) - self.assertEquals( - str(e.exception), "Expected <unit> = <converter>; got [d1] = [d2] * [d3]" - ) - def test_err_redefine_alias(self): - for s in ("foo = bar = f", "foo = bar = _ = baz"): - with self.subTest(s): - with self.assertRaises(DefinitionSyntaxError) as e: - Context.from_lines(["@context c", s]) - self.assertEquals( - str(e.exception), - "Can't change a unit's symbol or aliases within a context", - ) - - def test_err_redefine_with_prefix(self): - ureg = UnitRegistry( - """ - kilo- = 1000 - gram = [mass] - pound = 454 gram - - @context c - kilopound = 500000 gram - @end - """.splitlines() - ) - with self.assertRaises(ValueError) as e: - ureg.enable_contexts("c") - self.assertEquals( - str(e.exception), "Can't redefine a unit with a prefix: kilopound" - ) +def test_err_new_unit(): + ureg = UnitRegistry( + """ + foo = [d] + @context c + bar = foo + @end + """.splitlines() + ) - def test_err_new_unit(self): - ureg = UnitRegistry( - """ - foo = [d] - @context c - bar = foo - @end - """.splitlines() - ) - with self.assertRaises(UndefinedUnitError) as e: - ureg.enable_contexts("c") - self.assertEquals(str(e.exception), "'bar' is not defined in the unit registry") + expected = "'bar' is not defined in the unit registry" + with pytest.raises(UndefinedUnitError, match=expected): + ureg.enable_contexts("c") diff --git a/pint/testsuite/test_converters.py b/pint/testsuite/test_converters.py index 460b3e5..6e8d59a 100644 --- a/pint/testsuite/test_converters.py +++ b/pint/testsuite/test_converters.py @@ -7,60 +7,67 @@ from pint.converters import ( OffsetConverter, ScaleConverter, ) -from pint.testsuite import BaseTestCase, helpers +from pint.testsuite import helpers -class TestConverter(BaseTestCase): +class TestConverter: def test_converter(self): c = Converter() - self.assertTrue(c.is_multiplicative) - self.assertFalse(c.is_logarithmic) - self.assertTrue(c.to_reference(8)) - self.assertTrue(c.from_reference(8)) + assert c.is_multiplicative + assert not c.is_logarithmic + assert c.to_reference(8) + assert c.from_reference(8) def test_multiplicative_converter(self): c = ScaleConverter(20.0) - self.assertTrue(c.is_multiplicative) - self.assertFalse(c.is_logarithmic) - self.assertEqual(c.from_reference(c.to_reference(100)), 100) - self.assertEqual(c.to_reference(c.from_reference(100)), 100) + assert c.is_multiplicative + assert not c.is_logarithmic + assert c.from_reference(c.to_reference(100)) == 100 + assert c.to_reference(c.from_reference(100)) == 100 def test_offset_converter(self): c = OffsetConverter(20.0, 2) - self.assertFalse(c.is_multiplicative) - self.assertFalse(c.is_logarithmic) - self.assertEqual(c.from_reference(c.to_reference(100)), 100) - self.assertEqual(c.to_reference(c.from_reference(100)), 100) + assert not c.is_multiplicative + assert not c.is_logarithmic + assert c.from_reference(c.to_reference(100)) == 100 + assert c.to_reference(c.from_reference(100)) == 100 def test_log_converter(self): c = LogarithmicConverter(scale=1, logbase=10, logfactor=1) - self.assertFalse(c.is_multiplicative) - self.assertTrue(c.is_logarithmic) - self.assertAlmostEqual(c.to_reference(0), 1) - self.assertAlmostEqual(c.to_reference(1), 10) - self.assertAlmostEqual(c.to_reference(2), 100) - self.assertAlmostEqual(c.from_reference(1), 0) - self.assertAlmostEqual(c.from_reference(10), 1) - self.assertAlmostEqual(c.from_reference(100), 2) + assert not c.is_multiplicative + assert c.is_logarithmic + assert round(abs(c.to_reference(0) - 1), 7) == 0 + assert round(abs(c.to_reference(1) - 10), 7) == 0 + assert round(abs(c.to_reference(2) - 100), 7) == 0 + assert round(abs(c.from_reference(1) - 0), 7) == 0 + assert round(abs(c.from_reference(10) - 1), 7) == 0 + assert round(abs(c.from_reference(100) - 2), 7) == 0 arb_value = 20.0 - self.assertAlmostEqual(c.from_reference(c.to_reference(arb_value)), arb_value) - self.assertAlmostEqual(c.to_reference(c.from_reference(arb_value)), arb_value) + assert ( + round(abs(c.from_reference(c.to_reference(arb_value)) - arb_value), 7) == 0 + ) + assert ( + round(abs(c.to_reference(c.from_reference(arb_value)) - arb_value), 7) == 0 + ) - @helpers.requires_numpy() + @helpers.requires_numpy def test_converter_inplace(self): for c in (ScaleConverter(20.0), OffsetConverter(20.0, 2)): fun1 = lambda x, y: c.from_reference(c.to_reference(x, y), y) fun2 = lambda x, y: c.to_reference(c.from_reference(x, y), y) for fun, (inplace, comp) in itertools.product( - (fun1, fun2), ((True, self.assertIs), (False, self.assertIsNot)) + (fun1, fun2), ((True, True), (False, False)) ): a = np.ones((1, 10)) ac = np.ones((1, 10)) r = fun(a, inplace) np.testing.assert_allclose(r, ac) - comp(a, r) + if comp: + assert a is r + else: + assert a is not r - @helpers.requires_numpy() + @helpers.requires_numpy def test_log_converter_inplace(self): arb_value = 3.14 c = LogarithmicConverter(scale=1, logbase=10, logfactor=1) @@ -74,9 +81,12 @@ class TestConverter(BaseTestCase): ) for fun, (inplace, comp) in itertools.product( - (from_to, to_from), ((True, self.assertIs), (False, self.assertIsNot)) + (from_to, to_from), ((True, True), (False, False)) ): arb_array = arb_value * np.ones((1, 10)) result = fun(arb_array, inplace) np.testing.assert_allclose(result, arb_array) - comp(arb_array, result) + if comp: + assert arb_array is result + else: + assert arb_array is not result diff --git a/pint/testsuite/test_definitions.py b/pint/testsuite/test_definitions.py index 21ba401..43cd03c 100644 --- a/pint/testsuite/test_definitions.py +++ b/pint/testsuite/test_definitions.py @@ -1,3 +1,5 @@ +import pytest + from pint.converters import LogarithmicConverter, OffsetConverter, ScaleConverter from pint.definitions import ( AliasDefinition, @@ -7,165 +9,164 @@ from pint.definitions import ( UnitDefinition, ) from pint.errors import DefinitionSyntaxError -from pint.testsuite import BaseTestCase from pint.util import UnitsContainer -class TestDefinition(BaseTestCase): +class TestDefinition: def test_invalid(self): - with self.assertRaises(DefinitionSyntaxError): + with pytest.raises(DefinitionSyntaxError): Definition.from_string("x = [time] * meter") - with self.assertRaises(DefinitionSyntaxError): + with pytest.raises(DefinitionSyntaxError): Definition.from_string("[x] = [time] * meter") def test_prefix_definition(self): - self.assertRaises(ValueError, Definition.from_string, "m- = 1e-3 k") + with pytest.raises(ValueError): + Definition.from_string("m- = 1e-3 k") for definition in ("m- = 1e-3", "m- = 10**-3", "m- = 0.001"): x = Definition.from_string(definition) - self.assertIsInstance(x, PrefixDefinition) - self.assertEqual(x.name, "m") - self.assertEqual(x.aliases, ()) - self.assertEqual(x.converter.to_reference(1000), 1) - self.assertEqual(x.converter.from_reference(0.001), 1) - self.assertEqual(str(x), "m") + assert isinstance(x, PrefixDefinition) + assert x.name == "m" + assert x.aliases == () + assert x.converter.to_reference(1000) == 1 + assert x.converter.from_reference(0.001) == 1 + assert str(x) == "m" x = Definition.from_string("kilo- = 1e-3 = k-") - self.assertIsInstance(x, PrefixDefinition) - self.assertEqual(x.name, "kilo") - self.assertEqual(x.aliases, ()) - self.assertEqual(x.symbol, "k") - self.assertEqual(x.converter.to_reference(1000), 1) - self.assertEqual(x.converter.from_reference(0.001), 1) + assert isinstance(x, PrefixDefinition) + assert x.name == "kilo" + assert x.aliases == () + assert x.symbol == "k" + assert x.converter.to_reference(1000) == 1 + assert x.converter.from_reference(0.001) == 1 x = Definition.from_string("kilo- = 1e-3 = k- = anotherk-") - self.assertIsInstance(x, PrefixDefinition) - self.assertEqual(x.name, "kilo") - self.assertEqual(x.aliases, ("anotherk",)) - self.assertEqual(x.symbol, "k") - self.assertEqual(x.converter.to_reference(1000), 1) - self.assertEqual(x.converter.from_reference(0.001), 1) + assert isinstance(x, PrefixDefinition) + assert x.name == "kilo" + assert x.aliases == ("anotherk",) + assert x.symbol == "k" + assert x.converter.to_reference(1000) == 1 + assert x.converter.from_reference(0.001) == 1 def test_baseunit_definition(self): x = Definition.from_string("meter = [length]") - self.assertIsInstance(x, UnitDefinition) - self.assertTrue(x.is_base) - self.assertEqual(x.reference, UnitsContainer({"[length]": 1})) + assert isinstance(x, UnitDefinition) + assert x.is_base + assert x.reference == UnitsContainer({"[length]": 1}) def test_unit_definition(self): x = Definition.from_string("coulomb = ampere * second") - self.assertIsInstance(x, UnitDefinition) - self.assertFalse(x.is_base) - self.assertIsInstance(x.converter, ScaleConverter) - self.assertEqual(x.converter.scale, 1) - self.assertEqual(x.reference, UnitsContainer(ampere=1, second=1)) + assert isinstance(x, UnitDefinition) + assert not x.is_base + assert isinstance(x.converter, ScaleConverter) + assert x.converter.scale == 1 + assert x.reference == UnitsContainer(ampere=1, second=1) x = Definition.from_string("faraday = 96485.3399 * coulomb") - self.assertIsInstance(x, UnitDefinition) - self.assertFalse(x.is_base) - self.assertIsInstance(x.converter, ScaleConverter) - self.assertEqual(x.converter.scale, 96485.3399) - self.assertEqual(x.reference, UnitsContainer(coulomb=1)) + assert isinstance(x, UnitDefinition) + assert not x.is_base + assert isinstance(x.converter, ScaleConverter) + assert x.converter.scale == 96485.3399 + assert x.reference == UnitsContainer(coulomb=1) x = Definition.from_string("degF = 9 / 5 * kelvin; offset: 255.372222") - self.assertIsInstance(x, UnitDefinition) - self.assertFalse(x.is_base) - self.assertIsInstance(x.converter, OffsetConverter) - self.assertEqual(x.converter.scale, 9 / 5) - self.assertEqual(x.converter.offset, 255.372222) - self.assertEqual(x.reference, UnitsContainer(kelvin=1)) + assert isinstance(x, UnitDefinition) + assert not x.is_base + assert isinstance(x.converter, OffsetConverter) + assert x.converter.scale == 9 / 5 + assert x.converter.offset == 255.372222 + assert x.reference == UnitsContainer(kelvin=1) x = Definition.from_string( "turn = 6.28 * radian = _ = revolution = = cycle = _" ) - self.assertIsInstance(x, UnitDefinition) - self.assertEqual(x.name, "turn") - self.assertEqual(x.aliases, ("revolution", "cycle")) - self.assertEqual(x.symbol, "turn") - self.assertFalse(x.is_base) - self.assertIsInstance(x.converter, ScaleConverter) - self.assertEqual(x.converter.scale, 6.28) - self.assertEqual(x.reference, UnitsContainer(radian=1)) - - self.assertRaises( - ValueError, - Definition.from_string, - "degF = 9 / 5 * kelvin; offset: 255.372222 bla", - ) + assert isinstance(x, UnitDefinition) + assert x.name == "turn" + assert x.aliases == ("revolution", "cycle") + assert x.symbol == "turn" + assert not x.is_base + assert isinstance(x.converter, ScaleConverter) + assert x.converter.scale == 6.28 + assert x.reference == UnitsContainer(radian=1) + + with pytest.raises(ValueError): + Definition.from_string( + "degF = 9 / 5 * kelvin; offset: 255.372222 bla", + ) def test_log_unit_definition(self): x = Definition.from_string( "decibelmilliwatt = 1e-3 watt; logbase: 10; logfactor: 10 = dBm" ) - self.assertIsInstance(x, UnitDefinition) - self.assertFalse(x.is_base) - self.assertIsInstance(x.converter, LogarithmicConverter) - self.assertEqual(x.converter.scale, 1e-3) - self.assertEqual(x.converter.logbase, 10) - self.assertEqual(x.converter.logfactor, 10) - self.assertEqual(x.reference, UnitsContainer(watt=1)) + assert isinstance(x, UnitDefinition) + assert not x.is_base + assert isinstance(x.converter, LogarithmicConverter) + assert x.converter.scale == 1e-3 + assert x.converter.logbase == 10 + assert x.converter.logfactor == 10 + assert x.reference == UnitsContainer(watt=1) x = Definition.from_string("decibel = 1 ; logbase: 10; logfactor: 10 = dB") - self.assertIsInstance(x, UnitDefinition) - self.assertFalse(x.is_base) - self.assertIsInstance(x.converter, LogarithmicConverter) - self.assertEqual(x.converter.scale, 1) - self.assertEqual(x.converter.logbase, 10) - self.assertEqual(x.converter.logfactor, 10) - self.assertEqual(x.reference, UnitsContainer()) + assert isinstance(x, UnitDefinition) + assert not x.is_base + assert isinstance(x.converter, LogarithmicConverter) + assert x.converter.scale == 1 + assert x.converter.logbase == 10 + assert x.converter.logfactor == 10 + assert x.reference == UnitsContainer() x = Definition.from_string("bell = 1 ; logbase: 10; logfactor: 1 = B") - self.assertIsInstance(x, UnitDefinition) - self.assertFalse(x.is_base) - self.assertIsInstance(x.converter, LogarithmicConverter) - self.assertEqual(x.converter.scale, 1) - self.assertEqual(x.converter.logbase, 10) - self.assertEqual(x.converter.logfactor, 1) - self.assertEqual(x.reference, UnitsContainer()) + assert isinstance(x, UnitDefinition) + assert not x.is_base + assert isinstance(x.converter, LogarithmicConverter) + assert x.converter.scale == 1 + assert x.converter.logbase == 10 + assert x.converter.logfactor == 1 + assert x.reference == UnitsContainer() x = Definition.from_string("decade = 1 ; logbase: 10; logfactor: 1") - self.assertIsInstance(x, UnitDefinition) - self.assertFalse(x.is_base) - self.assertIsInstance(x.converter, LogarithmicConverter) - self.assertEqual(x.converter.scale, 1) - self.assertEqual(x.converter.logbase, 10) - self.assertEqual(x.converter.logfactor, 1) - self.assertEqual(x.reference, UnitsContainer()) + assert isinstance(x, UnitDefinition) + assert not x.is_base + assert isinstance(x.converter, LogarithmicConverter) + assert x.converter.scale == 1 + assert x.converter.logbase == 10 + assert x.converter.logfactor == 1 + assert x.reference == UnitsContainer() eulersnumber = 2.71828182845904523536028747135266249775724709369995 x = Definition.from_string( "neper = 1 ; logbase: %1.50f; logfactor: 0.5 = Np" % eulersnumber ) - self.assertIsInstance(x, UnitDefinition) - self.assertFalse(x.is_base) - self.assertIsInstance(x.converter, LogarithmicConverter) - self.assertEqual(x.converter.scale, 1) - self.assertEqual(x.converter.logbase, eulersnumber) - self.assertEqual(x.converter.logfactor, 0.5) - self.assertEqual(x.reference, UnitsContainer()) + assert isinstance(x, UnitDefinition) + assert not x.is_base + assert isinstance(x.converter, LogarithmicConverter) + assert x.converter.scale == 1 + assert x.converter.logbase == eulersnumber + assert x.converter.logfactor == 0.5 + assert x.reference == UnitsContainer() x = Definition.from_string("octave = 1 ; logbase: 2; logfactor: 1 = oct") - self.assertIsInstance(x, UnitDefinition) - self.assertFalse(x.is_base) - self.assertIsInstance(x.converter, LogarithmicConverter) - self.assertEqual(x.converter.scale, 1) - self.assertEqual(x.converter.logbase, 2) - self.assertEqual(x.converter.logfactor, 1) - self.assertEqual(x.reference, UnitsContainer()) + assert isinstance(x, UnitDefinition) + assert not x.is_base + assert isinstance(x.converter, LogarithmicConverter) + assert x.converter.scale == 1 + assert x.converter.logbase == 2 + assert x.converter.logfactor == 1 + assert x.reference == UnitsContainer() def test_dimension_definition(self): x = DimensionDefinition("[time]", "", (), None, is_base=True) - self.assertTrue(x.is_base) - self.assertEqual(x.name, "[time]") + assert x.is_base + assert x.name == "[time]" x = Definition.from_string("[speed] = [length]/[time]") - self.assertIsInstance(x, DimensionDefinition) - self.assertEqual(x.reference, UnitsContainer({"[length]": 1, "[time]": -1})) + assert isinstance(x, DimensionDefinition) + assert x.reference == UnitsContainer({"[length]": 1, "[time]": -1}) def test_alias_definition(self): x = Definition.from_string("@alias meter = metro = metr") - self.assertIsInstance(x, AliasDefinition) - self.assertEqual(x.name, "meter") - self.assertEqual(x.aliases, ("metro", "metr")) + assert isinstance(x, AliasDefinition) + assert x.name == "meter" + assert x.aliases == ("metro", "metr") diff --git a/pint/testsuite/test_errors.py b/pint/testsuite/test_errors.py index 3e65c61..c6f14fb 100644 --- a/pint/testsuite/test_errors.py +++ b/pint/testsuite/test_errors.py @@ -1,5 +1,7 @@ import pickle +import pytest + from pint import ( DefinitionSyntaxError, DimensionalityError, @@ -11,107 +13,106 @@ from pint import ( UnitRegistry, ) from pint.errors import LOG_ERROR_DOCS_HTML, OFFSET_ERROR_DOCS_HTML -from pint.testsuite import BaseTestCase -class TestErrors(BaseTestCase): +class TestErrors: def test_definition_syntax_error(self): ex = DefinitionSyntaxError("foo") - self.assertEqual(str(ex), "foo") + assert str(ex) == "foo" # filename and lineno can be attached after init ex.filename = "a.txt" ex.lineno = 123 - self.assertEqual(str(ex), "While opening a.txt, in line 123: foo") + assert str(ex) == "While opening a.txt, in line 123: foo" ex = DefinitionSyntaxError("foo", lineno=123) - self.assertEqual(str(ex), "In line 123: foo") + assert str(ex) == "In line 123: foo" ex = DefinitionSyntaxError("foo", filename="a.txt") - self.assertEqual(str(ex), "While opening a.txt: foo") + assert str(ex) == "While opening a.txt: foo" ex = DefinitionSyntaxError("foo", filename="a.txt", lineno=123) - self.assertEqual(str(ex), "While opening a.txt, in line 123: foo") + assert str(ex) == "While opening a.txt, in line 123: foo" def test_redefinition_error(self): ex = RedefinitionError("foo", "bar") - self.assertEqual(str(ex), "Cannot redefine 'foo' (bar)") + assert str(ex) == "Cannot redefine 'foo' (bar)" # filename and lineno can be attached after init ex.filename = "a.txt" ex.lineno = 123 - self.assertEqual( - str(ex), "While opening a.txt, in line 123: Cannot redefine 'foo' (bar)" + assert ( + str(ex) == "While opening a.txt, in line 123: Cannot redefine 'foo' (bar)" ) ex = RedefinitionError("foo", "bar", lineno=123) - self.assertEqual(str(ex), "In line 123: Cannot redefine 'foo' (bar)") + assert str(ex) == "In line 123: Cannot redefine 'foo' (bar)" ex = RedefinitionError("foo", "bar", filename="a.txt") - self.assertEqual(str(ex), "While opening a.txt: Cannot redefine 'foo' (bar)") + assert str(ex) == "While opening a.txt: Cannot redefine 'foo' (bar)" ex = RedefinitionError("foo", "bar", filename="a.txt", lineno=123) - self.assertEqual( - str(ex), "While opening a.txt, in line 123: Cannot redefine 'foo' (bar)" + assert ( + str(ex) == "While opening a.txt, in line 123: Cannot redefine 'foo' (bar)" ) def test_undefined_unit_error(self): x = ("meter",) msg = "'meter' is not defined in the unit registry" - self.assertEqual(str(UndefinedUnitError(x)), msg) - self.assertEqual(str(UndefinedUnitError(list(x))), msg) - self.assertEqual(str(UndefinedUnitError(set(x))), msg) + assert str(UndefinedUnitError(x)) == msg + assert str(UndefinedUnitError(list(x))) == msg + assert str(UndefinedUnitError(set(x))) == msg def test_undefined_unit_error_multi(self): x = ("meter", "kg") msg = "('meter', 'kg') are not defined in the unit registry" - self.assertEqual(str(UndefinedUnitError(x)), msg) - self.assertEqual(str(UndefinedUnitError(list(x))), msg) + assert str(UndefinedUnitError(x)) == msg + assert str(UndefinedUnitError(list(x))) == msg def test_dimensionality_error(self): ex = DimensionalityError("a", "b") - self.assertEqual(str(ex), "Cannot convert from 'a' to 'b'") + assert str(ex) == "Cannot convert from 'a' to 'b'" ex = DimensionalityError("a", "b", "c") - self.assertEqual(str(ex), "Cannot convert from 'a' (c) to 'b' ()") + assert str(ex) == "Cannot convert from 'a' (c) to 'b' ()" ex = DimensionalityError("a", "b", "c", "d", extra_msg=": msg") - self.assertEqual(str(ex), "Cannot convert from 'a' (c) to 'b' (d): msg") + assert str(ex) == "Cannot convert from 'a' (c) to 'b' (d): msg" def test_offset_unit_calculus_error(self): ex = OffsetUnitCalculusError(Quantity("1 kg")._units) - self.assertEqual( - str(ex), - "Ambiguous operation with offset unit (kilogram). See " + assert ( + str(ex) + == "Ambiguous operation with offset unit (kilogram). See " + OFFSET_ERROR_DOCS_HTML - + " for guidance.", + + " for guidance." ) ex = OffsetUnitCalculusError(Quantity("1 kg")._units, Quantity("1 s")._units) - self.assertEqual( - str(ex), - "Ambiguous operation with offset unit (kilogram, second). See " + assert ( + str(ex) + == "Ambiguous operation with offset unit (kilogram, second). See " + OFFSET_ERROR_DOCS_HTML - + " for guidance.", + + " for guidance." ) def test_logarithmic_unit_calculus_error(self): Quantity = UnitRegistry(autoconvert_offset_to_baseunit=True).Quantity ex = LogarithmicUnitCalculusError(Quantity("1 dB")._units) - self.assertEqual( - str(ex), - "Ambiguous operation with logarithmic unit (decibel). See " + assert ( + str(ex) + == "Ambiguous operation with logarithmic unit (decibel). See " + LOG_ERROR_DOCS_HTML - + " for guidance.", + + " for guidance." ) ex = LogarithmicUnitCalculusError( Quantity("1 dB")._units, Quantity("1 octave")._units ) - self.assertEqual( - str(ex), - "Ambiguous operation with logarithmic unit (decibel, octave). See " + assert ( + str(ex) + == "Ambiguous operation with logarithmic unit (decibel, octave). See " + LOG_ERROR_DOCS_HTML - + " for guidance.", + + " for guidance." ) - def test_pickle_definition_syntax_error(self): + def test_pickle_definition_syntax_error(self, subtests): # OffsetUnitCalculusError raised from a custom ureg must be pickleable even if # the ureg is not registered as the application ureg ureg = UnitRegistry(filename=None) @@ -131,14 +132,14 @@ class TestErrors(BaseTestCase): ), OffsetUnitCalculusError(q1._units, q2._units), ]: - with self.subTest(protocol=protocol, etype=type(ex)): + with subtests.test(protocol=protocol, etype=type(ex)): pik = pickle.dumps(ureg.Quantity("1 foo"), protocol) - with self.assertRaises(UndefinedUnitError): + with pytest.raises(UndefinedUnitError): pickle.loads(pik) # assert False, ex.__reduce__() ex2 = pickle.loads(pickle.dumps(ex, protocol)) assert type(ex) is type(ex2) - self.assertEqual(ex.args, ex2.args) - self.assertEqual(ex.__dict__, ex2.__dict__) - self.assertEqual(str(ex), str(ex2)) + assert ex.args == ex2.args + assert ex.__dict__ == ex2.__dict__ + assert str(ex) == str(ex2) diff --git a/pint/testsuite/test_formatter.py b/pint/testsuite/test_formatter.py index c4a4d57..9e362fc 100644 --- a/pint/testsuite/test_formatter.py +++ b/pint/testsuite/test_formatter.py @@ -1,47 +1,48 @@ +import pytest + from pint import formatting as fmt -from pint.testsuite import QuantityTestCase -class TestFormatter(QuantityTestCase): +class TestFormatter: def test_join(self): for empty in (tuple(), []): - self.assertEqual(fmt._join("s", empty), "") - self.assertEqual(fmt._join("*", "1 2 3".split()), "1*2*3") - self.assertEqual(fmt._join("{0}*{1}", "1 2 3".split()), "1*2*3") + assert fmt._join("s", empty) == "" + assert fmt._join("*", "1 2 3".split()) == "1*2*3" + assert fmt._join("{0}*{1}", "1 2 3".split()) == "1*2*3" def test_formatter(self): - self.assertEqual(fmt.formatter(dict().items()), "") - self.assertEqual(fmt.formatter(dict(meter=1).items()), "meter") - self.assertEqual(fmt.formatter(dict(meter=-1).items()), "1 / meter") - self.assertEqual( - fmt.formatter(dict(meter=-1).items(), as_ratio=False), "meter ** -1" - ) + assert fmt.formatter(dict().items()) == "" + assert fmt.formatter(dict(meter=1).items()) == "meter" + assert fmt.formatter(dict(meter=-1).items()) == "1 / meter" + assert fmt.formatter(dict(meter=-1).items(), as_ratio=False) == "meter ** -1" - self.assertEqual( - fmt.formatter(dict(meter=-1, second=-1).items(), as_ratio=False), - "meter ** -1 * second ** -1", - ) - self.assertEqual( - fmt.formatter(dict(meter=-1, second=-1).items()), "1 / meter / second" + assert ( + fmt.formatter(dict(meter=-1, second=-1).items(), as_ratio=False) + == "meter ** -1 * second ** -1" ) - self.assertEqual( - fmt.formatter(dict(meter=-1, second=-1).items(), single_denominator=True), - "1 / (meter * second)", + assert fmt.formatter(dict(meter=-1, second=-1).items()) == "1 / meter / second" + assert ( + fmt.formatter(dict(meter=-1, second=-1).items(), single_denominator=True) + == "1 / (meter * second)" ) - self.assertEqual( - fmt.formatter(dict(meter=-1, second=-2).items()), "1 / meter / second ** 2" + assert ( + fmt.formatter(dict(meter=-1, second=-2).items()) + == "1 / meter / second ** 2" ) - self.assertEqual( - fmt.formatter(dict(meter=-1, second=-2).items(), single_denominator=True), - "1 / (meter * second ** 2)", + assert ( + fmt.formatter(dict(meter=-1, second=-2).items(), single_denominator=True) + == "1 / (meter * second ** 2)" ) def test_parse_spec(self): - self.assertEqual(fmt._parse_spec(""), "") - self.assertEqual(fmt._parse_spec(""), "") - self.assertRaises(ValueError, fmt._parse_spec, "W") - self.assertRaises(ValueError, fmt._parse_spec, "PL") + assert fmt._parse_spec("") == "" + assert fmt._parse_spec("") == "" + with pytest.raises(ValueError): + fmt._parse_spec("W") + with pytest.raises(ValueError): + fmt._parse_spec("PL") def test_format_unit(self): - self.assertEqual(fmt.format_unit("", "C"), "dimensionless") - self.assertRaises(ValueError, fmt.format_unit, "m", "W") + assert fmt.format_unit("", "C") == "dimensionless" + with pytest.raises(ValueError): + fmt.format_unit("m", "W") diff --git a/pint/testsuite/test_infer_base_unit.py b/pint/testsuite/test_infer_base_unit.py index dc3bd82..54a4720 100644 --- a/pint/testsuite/test_infer_base_unit.py +++ b/pint/testsuite/test_infer_base_unit.py @@ -1,32 +1,30 @@ from pint import Quantity as Q -from pint.testsuite import QuantityTestCase +from pint.testsuite import helpers from pint.util import infer_base_unit -class TestInferBaseUnit(QuantityTestCase): +class TestInferBaseUnit: def test_infer_base_unit(self): from pint.util import infer_base_unit - self.assertEqual( - infer_base_unit(Q(1, "millimeter * nanometer")), Q(1, "meter**2").units - ) + assert infer_base_unit(Q(1, "millimeter * nanometer")) == Q(1, "meter**2").units def test_units_adding_to_zero(self): - self.assertEqual(infer_base_unit(Q(1, "m * mm / m / um * s")), Q(1, "s").units) + assert infer_base_unit(Q(1, "m * mm / m / um * s")) == Q(1, "s").units def test_to_compact(self): r = Q(1000000000, "m") * Q(1, "mm") / Q(1, "s") / Q(1, "ms") compact_r = r.to_compact() expected = Q(1000.0, "kilometer**2 / second**2") - self.assertQuantityAlmostEqual(compact_r, expected) + helpers.assert_quantity_almost_equal(compact_r, expected) r = (Q(1, "m") * Q(1, "mm") / Q(1, "m") / Q(2, "um") * Q(2, "s")).to_compact() - self.assertQuantityAlmostEqual(r, Q(1000, "s")) + helpers.assert_quantity_almost_equal(r, Q(1000, "s")) def test_volts(self): from pint.util import infer_base_unit r = Q(1, "V") * Q(1, "mV") / Q(1, "kV") b = infer_base_unit(r) - self.assertEqual(b, Q(1, "V").units) - self.assertQuantityAlmostEqual(r, Q(1, "uV")) + assert b == Q(1, "V").units + helpers.assert_quantity_almost_equal(r, Q(1, "uV")) diff --git a/pint/testsuite/test_issues.py b/pint/testsuite/test_issues.py index 6be33db..4d36326 100644 --- a/pint/testsuite/test_issues.py +++ b/pint/testsuite/test_issues.py @@ -1,7 +1,6 @@ import copy import math import pprint -import unittest import pytest @@ -16,109 +15,108 @@ ureg = UnitRegistry() class TestIssues(QuantityTestCase): - FORCE_NDARRAY = False + kwargs = dict(autoconvert_offset_to_baseunit=False) - def setup(self): - self.ureg.autoconvert_offset_to_baseunit = False - - @unittest.expectedFailure + @pytest.mark.xfail def test_issue25(self): x = ParserHelper.from_string("10 %") - self.assertEqual(x, ParserHelper(10, {"%": 1})) + assert x == ParserHelper(10, {"%": 1}) x = ParserHelper.from_string("10 ‰") - self.assertEqual(x, ParserHelper(10, {"‰": 1})) + assert x == ParserHelper(10, {"‰": 1}) ureg.define("percent = [fraction]; offset: 0 = %") ureg.define("permille = percent / 10 = ‰") x = ureg.parse_expression("10 %") - self.assertEqual(x, ureg.Quantity(10, {"%": 1})) + assert x == ureg.Quantity(10, {"%": 1}) y = ureg.parse_expression("10 ‰") - self.assertEqual(y, ureg.Quantity(10, {"‰": 1})) - self.assertEqual(x.to("‰"), ureg.Quantity(1, {"‰": 1})) + assert y == ureg.Quantity(10, {"‰": 1}) + assert x.to("‰") == ureg.Quantity(1, {"‰": 1}) def test_issue29(self): t = 4 * ureg("mW") - self.assertEqual(t.magnitude, 4) - self.assertEqual(t._units, UnitsContainer(milliwatt=1)) - self.assertEqual(t.to("joule / second"), 4e-3 * ureg("W")) + assert t.magnitude == 4 + assert t._units == UnitsContainer(milliwatt=1) + assert t.to("joule / second") == 4e-3 * ureg("W") - @unittest.expectedFailure - @helpers.requires_numpy() + @pytest.mark.xfail + @helpers.requires_numpy def test_issue37(self): x = np.ma.masked_array([1, 2, 3], mask=[True, True, False]) q = ureg.meter * x - self.assertIsInstance(q, ureg.Quantity) + assert isinstance(q, ureg.Quantity) np.testing.assert_array_equal(q.magnitude, x) - self.assertEqual(q.units, ureg.meter.units) + assert q.units == ureg.meter.units q = x * ureg.meter - self.assertIsInstance(q, ureg.Quantity) + assert isinstance(q, ureg.Quantity) np.testing.assert_array_equal(q.magnitude, x) - self.assertEqual(q.units, ureg.meter.units) + assert q.units == ureg.meter.units m = np.ma.masked_array(2 * np.ones(3, 3)) qq = q * m - self.assertIsInstance(qq, ureg.Quantity) + assert isinstance(qq, ureg.Quantity) np.testing.assert_array_equal(qq.magnitude, x * m) - self.assertEqual(qq.units, ureg.meter.units) + assert qq.units == ureg.meter.units qq = m * q - self.assertIsInstance(qq, ureg.Quantity) + assert isinstance(qq, ureg.Quantity) np.testing.assert_array_equal(qq.magnitude, x * m) - self.assertEqual(qq.units, ureg.meter.units) + assert qq.units == ureg.meter.units - @unittest.expectedFailure - @helpers.requires_numpy() + @pytest.mark.xfail + @helpers.requires_numpy def test_issue39(self): x = np.matrix([[1, 2, 3], [1, 2, 3], [1, 2, 3]]) q = ureg.meter * x - self.assertIsInstance(q, ureg.Quantity) + assert isinstance(q, ureg.Quantity) np.testing.assert_array_equal(q.magnitude, x) - self.assertEqual(q.units, ureg.meter.units) + assert q.units == ureg.meter.units q = x * ureg.meter - self.assertIsInstance(q, ureg.Quantity) + assert isinstance(q, ureg.Quantity) np.testing.assert_array_equal(q.magnitude, x) - self.assertEqual(q.units, ureg.meter.units) + assert q.units == ureg.meter.units m = np.matrix(2 * np.ones(3, 3)) qq = q * m - self.assertIsInstance(qq, ureg.Quantity) + assert isinstance(qq, ureg.Quantity) np.testing.assert_array_equal(qq.magnitude, x * m) - self.assertEqual(qq.units, ureg.meter.units) + assert qq.units == ureg.meter.units qq = m * q - self.assertIsInstance(qq, ureg.Quantity) + assert isinstance(qq, ureg.Quantity) np.testing.assert_array_equal(qq.magnitude, x * m) - self.assertEqual(qq.units, ureg.meter.units) + assert qq.units == ureg.meter.units - @helpers.requires_numpy() + @helpers.requires_numpy def test_issue44(self): x = 4.0 * ureg.dimensionless np.sqrt(x) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( np.sqrt([4.0] * ureg.dimensionless), [2.0] * ureg.dimensionless ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( np.sqrt(4.0 * ureg.dimensionless), 2.0 * ureg.dimensionless ) def test_issue45(self): import math - self.assertAlmostEqual(math.sqrt(4 * ureg.m / ureg.cm), math.sqrt(4 * 100)) - self.assertAlmostEqual(float(ureg.V / ureg.mV), 1000.0) + helpers.assert_quantity_almost_equal( + math.sqrt(4 * ureg.m / ureg.cm), math.sqrt(4 * 100) + ) + helpers.assert_quantity_almost_equal(float(ureg.V / ureg.mV), 1000.0) - @helpers.requires_numpy() + @helpers.requires_numpy def test_issue45b(self): - self.assertAlmostEqual( + helpers.assert_quantity_almost_equal( np.sin([np.pi / 2] * ureg.m / ureg.m), np.sin([np.pi / 2] * ureg.dimensionless), ) - self.assertAlmostEqual( + helpers.assert_quantity_almost_equal( np.sin([np.pi / 2] * ureg.cm / ureg.m), np.sin([np.pi / 2] * ureg.dimensionless * 0.01), ) def test_issue50(self): Q_ = ureg.Quantity - self.assertEqual(Q_(100), 100 * ureg.dimensionless) - self.assertEqual(Q_("100"), 100 * ureg.dimensionless) + assert Q_(100) == 100 * ureg.dimensionless + assert Q_("100") == 100 * ureg.dimensionless def test_issue52(self): u1 = UnitRegistry() @@ -139,63 +137,69 @@ class TestIssues(QuantityTestCase): op.truediv, op.itruediv, ): - self.assertRaises(ValueError, fun, q1, q2) + with pytest.raises(ValueError): + fun(q1, q2) def test_issue54(self): - self.assertEqual((1 * ureg.km / ureg.m + 1).magnitude, 1001) + assert (1 * ureg.km / ureg.m + 1).magnitude == 1001 def test_issue54_related(self): - self.assertEqual(ureg.km / ureg.m, 1000) - self.assertEqual(1000, ureg.km / ureg.m) - self.assertLess(900, ureg.km / ureg.m) - self.assertGreater(1100, ureg.km / ureg.m) + assert ureg.km / ureg.m == 1000 + assert 1000 == ureg.km / ureg.m + assert 900 < ureg.km / ureg.m + assert 1100 > ureg.km / ureg.m def test_issue61(self): Q_ = ureg.Quantity for value in ({}, {"a": 3}, None): - self.assertRaises(TypeError, Q_, value) - self.assertRaises(TypeError, Q_, value, "meter") - self.assertRaises(ValueError, Q_, "", "meter") - self.assertRaises(ValueError, Q_, "") + with pytest.raises(TypeError): + Q_(value) + with pytest.raises(TypeError): + Q_(value, "meter") + with pytest.raises(ValueError): + Q_("", "meter") + with pytest.raises(ValueError): + Q_("") @helpers.requires_not_numpy() def test_issue61_notNP(self): Q_ = ureg.Quantity for value in ([1, 2, 3], (1, 2, 3)): - self.assertRaises(TypeError, Q_, value) - self.assertRaises(TypeError, Q_, value, "meter") + with pytest.raises(TypeError): + Q_(value) + with pytest.raises(TypeError): + Q_(value, "meter") def test_issue62(self): m = ureg("m**0.5") - self.assertEqual(str(m.units), "meter ** 0.5") + assert str(m.units) == "meter ** 0.5" def test_issue66(self): - self.assertEqual( - ureg.get_dimensionality(UnitsContainer({"[temperature]": 1})), - UnitsContainer({"[temperature]": 1}), + assert ureg.get_dimensionality( + UnitsContainer({"[temperature]": 1}) + ) == UnitsContainer({"[temperature]": 1}) + assert ureg.get_dimensionality(ureg.kelvin) == UnitsContainer( + {"[temperature]": 1} ) - self.assertEqual( - ureg.get_dimensionality(ureg.kelvin), UnitsContainer({"[temperature]": 1}) - ) - self.assertEqual( - ureg.get_dimensionality(ureg.degC), UnitsContainer({"[temperature]": 1}) + assert ureg.get_dimensionality(ureg.degC) == UnitsContainer( + {"[temperature]": 1} ) def test_issue66b(self): - self.assertEqual( - ureg.get_base_units(ureg.kelvin), - (1.0, ureg.Unit(UnitsContainer({"kelvin": 1}))), + assert ureg.get_base_units(ureg.kelvin) == ( + 1.0, + ureg.Unit(UnitsContainer({"kelvin": 1})), ) - self.assertEqual( - ureg.get_base_units(ureg.degC), - (1.0, ureg.Unit(UnitsContainer({"kelvin": 1}))), + assert ureg.get_base_units(ureg.degC) == ( + 1.0, + ureg.Unit(UnitsContainer({"kelvin": 1})), ) def test_issue69(self): q = ureg("m").to(ureg("in")) - self.assertEqual(q, ureg("m").to("in")) + assert q == ureg("m").to("in") - @helpers.requires_numpy() + @helpers.requires_numpy def test_issue74(self): v1 = np.asarray([1.0, 2.0, 3.0]) v2 = np.asarray([3.0, 2.0, 1.0]) @@ -217,7 +221,7 @@ class TestIssues(QuantityTestCase): np.testing.assert_array_equal(q1 <= q2s, v1 <= v2s) np.testing.assert_array_equal(q1 >= q2s, v1 >= v2s) - @helpers.requires_numpy() + @helpers.requires_numpy def test_issue75(self): v1 = np.asarray([1.0, 2.0, 3.0]) v2 = np.asarray([3.0, 2.0, 1.0]) @@ -238,7 +242,7 @@ class TestIssues(QuantityTestCase): acc = (5.0 * ureg("m/s/s")).plus_minus(0.25) tim = (37.0 * ureg("s")).plus_minus(0.16) dis = acc * tim ** 2 / 2 - self.assertEqual(dis.value, acc.value * tim.value ** 2 / 2) + assert dis.value == acc.value * tim.value ** 2 / 2 def test_issue85(self): @@ -251,7 +255,7 @@ class TestIssues(QuantityTestCase): boltmk = 1.380649e-23 * ureg.J / ureg.K vb = 2.0 * boltmk * T / m - self.assertQuantityAlmostEqual(va.to_base_units(), vb.to_base_units()) + helpers.assert_quantity_almost_equal(va.to_base_units(), vb.to_base_units()) def test_issue86(self): ureg = self.ureg @@ -273,22 +277,22 @@ class TestIssues(QuantityTestCase): k1m, k1u = parts(k1) - self.assertEqual(parts(q2 * q3), (q2m * q3m, q2u * q3u)) - self.assertEqual(parts(q2 / q3), (q2m / q3m, q2u / q3u)) - self.assertEqual(parts(q3 * q2), (q3m * q2m, q3u * q2u)) - self.assertEqual(parts(q3 / q2), (q3m / q2m, q3u / q2u)) - self.assertEqual(parts(q2 ** 1), (q2m ** 1, q2u ** 1)) - self.assertEqual(parts(q2 ** -1), (q2m ** -1, q2u ** -1)) - self.assertEqual(parts(q2 ** 2), (q2m ** 2, q2u ** 2)) - self.assertEqual(parts(q2 ** -2), (q2m ** -2, q2u ** -2)) - - self.assertEqual(parts(q1 * q3), (k1m * q3m, k1u * q3u)) - self.assertEqual(parts(q1 / q3), (k1m / q3m, k1u / q3u)) - self.assertEqual(parts(q3 * q1), (q3m * k1m, q3u * k1u)) - self.assertEqual(parts(q3 / q1), (q3m / k1m, q3u / k1u)) - self.assertEqual(parts(q1 ** -1), (k1m ** -1, k1u ** -1)) - self.assertEqual(parts(q1 ** 2), (k1m ** 2, k1u ** 2)) - self.assertEqual(parts(q1 ** -2), (k1m ** -2, k1u ** -2)) + assert parts(q2 * q3) == (q2m * q3m, q2u * q3u) + assert parts(q2 / q3) == (q2m / q3m, q2u / q3u) + assert parts(q3 * q2) == (q3m * q2m, q3u * q2u) + assert parts(q3 / q2) == (q3m / q2m, q3u / q2u) + assert parts(q2 ** 1) == (q2m ** 1, q2u ** 1) + assert parts(q2 ** -1) == (q2m ** -1, q2u ** -1) + assert parts(q2 ** 2) == (q2m ** 2, q2u ** 2) + assert parts(q2 ** -2) == (q2m ** -2, q2u ** -2) + + assert parts(q1 * q3) == (k1m * q3m, k1u * q3u) + assert parts(q1 / q3) == (k1m / q3m, k1u / q3u) + assert parts(q3 * q1) == (q3m * k1m, q3u * k1u) + assert parts(q3 / q1) == (q3m / k1m, q3u / k1u) + assert parts(q1 ** -1) == (k1m ** -1, k1u ** -1) + assert parts(q1 ** 2) == (k1m ** 2, k1u ** 2) + assert parts(q1 ** -2) == (k1m ** -2, k1u ** -2) def test_issues86b(self): ureg = self.ureg @@ -299,31 +303,31 @@ class TestIssues(QuantityTestCase): v1 = 2 * ureg.k * T1 / m v2 = 2 * ureg.k * T2 / m - self.assertQuantityAlmostEqual(v1, v2) - self.assertQuantityAlmostEqual(v1, v2.to_base_units()) - self.assertQuantityAlmostEqual(v1.to_base_units(), v2) - self.assertQuantityAlmostEqual(v1.to_base_units(), v2.to_base_units()) + helpers.assert_quantity_almost_equal(v1, v2) + helpers.assert_quantity_almost_equal(v1, v2.to_base_units()) + helpers.assert_quantity_almost_equal(v1.to_base_units(), v2) + helpers.assert_quantity_almost_equal(v1.to_base_units(), v2.to_base_units()) - @unittest.expectedFailure + @pytest.mark.xfail def test_issue86c(self): ureg = self.ureg ureg.autoconvert_offset_to_baseunit = True T = ureg.degC T = 100.0 * T - self.assertQuantityAlmostEqual(ureg.k * 2 * T, ureg.k * (2 * T)) + helpers.assert_quantity_almost_equal(ureg.k * 2 * T, ureg.k * (2 * T)) def test_issue93(self): x = 5 * ureg.meter - self.assertIsInstance(x.magnitude, int) + assert isinstance(x.magnitude, int) y = 0.1 * ureg.meter - self.assertIsInstance(y.magnitude, float) + assert isinstance(y.magnitude, float) z = 5 * ureg.meter - self.assertIsInstance(z.magnitude, int) + assert isinstance(z.magnitude, int) z += y - self.assertIsInstance(z.magnitude, float) + assert isinstance(z.magnitude, float) - self.assertQuantityAlmostEqual(x + y, 5.1 * ureg.meter) - self.assertQuantityAlmostEqual(z, 5.1 * ureg.meter) + helpers.assert_quantity_almost_equal(x + y, 5.1 * ureg.meter) + helpers.assert_quantity_almost_equal(z, 5.1 * ureg.meter) def test_issue104(self): @@ -339,40 +343,40 @@ class TestIssues(QuantityTestCase): return total - self.assertQuantityAlmostEqual(summer(x), ureg.Quantity(3, "meter")) - self.assertQuantityAlmostEqual(x[0], ureg.Quantity(1, "meter")) - self.assertQuantityAlmostEqual(summer(y), ureg.Quantity(3, "meter")) - self.assertQuantityAlmostEqual(y[0], ureg.Quantity(1, "meter")) + helpers.assert_quantity_almost_equal(summer(x), ureg.Quantity(3, "meter")) + helpers.assert_quantity_almost_equal(x[0], ureg.Quantity(1, "meter")) + helpers.assert_quantity_almost_equal(summer(y), ureg.Quantity(3, "meter")) + helpers.assert_quantity_almost_equal(y[0], ureg.Quantity(1, "meter")) def test_issue105(self): func = ureg.parse_unit_name val = list(func("meter")) - self.assertEqual(list(func("METER")), []) - self.assertEqual(val, list(func("METER", False))) + assert list(func("METER")) == [] + assert val == list(func("METER", False)) for func in (ureg.get_name, ureg.parse_expression): val = func("meter") - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): func("METER") - self.assertEqual(val, func("METER", False)) + assert val == func("METER", False) - @helpers.requires_numpy() + @helpers.requires_numpy def test_issue127(self): q = [1.0, 2.0, 3.0, 4.0] * self.ureg.meter q[0] = np.nan - self.assertNotEqual(q[0], 1.0) - self.assertTrue(math.isnan(q[0].magnitude)) + assert q[0] != 1.0 + assert math.isnan(q[0].magnitude) q[1] = float("NaN") - self.assertNotEqual(q[1], 2.0) - self.assertTrue(math.isnan(q[1].magnitude)) + assert q[1] != 2.0 + assert math.isnan(q[1].magnitude) def test_issue170(self): Q_ = UnitRegistry().Quantity q = Q_("1 kHz") / Q_("100 Hz") iq = int(q) - self.assertEqual(iq, 10) - self.assertIsInstance(iq, int) + assert iq == 10 + assert isinstance(iq, int) def test_angstrom_creation(self): ureg.Quantity(2, "Å") @@ -383,57 +387,57 @@ class TestIssues(QuantityTestCase): def test_micro_creation(self): ureg.Quantity(2, "µm") - @helpers.requires_numpy() + @helpers.requires_numpy def test_issue171_real_imag(self): qr = [1.0, 2.0, 3.0, 4.0] * self.ureg.meter qi = [4.0, 3.0, 2.0, 1.0] * self.ureg.meter q = qr + 1j * qi - self.assertQuantityEqual(q.real, qr) - self.assertQuantityEqual(q.imag, qi) + helpers.assert_quantity_equal(q.real, qr) + helpers.assert_quantity_equal(q.imag, qi) - @helpers.requires_numpy() + @helpers.requires_numpy def test_issue171_T(self): a = np.asarray([[1.0, 2.0, 3.0, 4.0], [4.0, 3.0, 2.0, 1.0]]) q1 = a * self.ureg.meter q2 = a.T * self.ureg.meter - self.assertQuantityEqual(q1.T, q2) + helpers.assert_quantity_equal(q1.T, q2) - @helpers.requires_numpy() + @helpers.requires_numpy def test_issue250(self): a = self.ureg.V b = self.ureg.mV - self.assertEqual(np.float16(a / b), 1000.0) - self.assertEqual(np.float32(a / b), 1000.0) - self.assertEqual(np.float64(a / b), 1000.0) + assert np.float16(a / b) == 1000.0 + assert np.float32(a / b) == 1000.0 + assert np.float64(a / b) == 1000.0 if "float128" in dir(np): - self.assertEqual(np.float128(a / b), 1000.0) + assert np.float128(a / b) == 1000.0 def test_issue252(self): ur = UnitRegistry() q = ur("3 F") t = copy.deepcopy(q) u = t.to(ur.mF) - self.assertQuantityEqual(q.to(ur.mF), u) + helpers.assert_quantity_equal(q.to(ur.mF), u) def test_issue323(self): from fractions import Fraction as F - self.assertEqual((self.Q_(F(2, 3), "s")).to("ms"), self.Q_(F(2000, 3), "ms")) - self.assertEqual((self.Q_(F(2, 3), "m")).to("km"), self.Q_(F(1, 1500), "km")) + assert (self.Q_(F(2, 3), "s")).to("ms") == self.Q_(F(2000, 3), "ms") + assert (self.Q_(F(2, 3), "m")).to("km") == self.Q_(F(1, 1500), "km") def test_issue339(self): q1 = self.ureg("") - self.assertEqual(q1.magnitude, 1) - self.assertEqual(q1.units, self.ureg.dimensionless) + assert q1.magnitude == 1 + assert q1.units == self.ureg.dimensionless q2 = self.ureg("1 dimensionless") - self.assertEqual(q1, q2) + assert q1 == q2 def test_issue354_356_370(self): - self.assertEqual( - "{:~}".format(1 * self.ureg.second / self.ureg.millisecond), "1.0 s / ms" + assert ( + "{:~}".format(1 * self.ureg.second / self.ureg.millisecond) == "1.0 s / ms" ) - self.assertEqual("{:~}".format(1 * self.ureg.count), "1 count") - self.assertEqual("{:~}".format(1 * self.ureg("MiB")), "1 MiB") + assert "{:~}".format(1 * self.ureg.count) == "1 count" + assert "{:~}".format(1 * self.ureg("MiB")) == "1 MiB" def test_issue468(self): @ureg.wraps(("kg"), "meter") @@ -443,15 +447,15 @@ class TestIssues(QuantityTestCase): x = ureg.Quantity(1.0, "meter") y = f(x) z = x * y - self.assertEqual(z, ureg.Quantity(1.0, "meter * kilogram")) + assert z == ureg.Quantity(1.0, "meter * kilogram") - @helpers.requires_numpy() + @helpers.requires_numpy def test_issue482(self): q = self.ureg.Quantity(1, self.ureg.dimensionless) qe = np.exp(q) - self.assertIsInstance(qe, self.ureg.Quantity) + assert isinstance(qe, self.ureg.Quantity) - @helpers.requires_numpy() + @helpers.requires_numpy def test_issue483(self): ureg = self.ureg a = np.asarray([1, 2, 3]) @@ -465,19 +469,21 @@ class TestIssues(QuantityTestCase): battery_ec = 16 * ureg.kWh / ureg._100km # noqa: F841 # ... but not with text ureg.define("_home = 4700 * kWh / year") - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): home_elec_power = 1 * ureg._home # noqa: F841 # ... or with *only* underscores ureg.define("_ = 45 * km") - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): one_blank = 1 * ureg._ # noqa: F841 def test_issue523(self): src, dst = UnitsContainer({"meter": 1}), UnitsContainer({"degF": 1}) value = 10.0 convert = self.ureg.convert - self.assertRaises(DimensionalityError, convert, value, src, dst) - self.assertRaises(DimensionalityError, convert, value, dst, src) + with pytest.raises(DimensionalityError): + convert(value, src, dst) + with pytest.raises(DimensionalityError): + convert(value, dst, src) def test_issue532(self): ureg = self.ureg @@ -486,8 +492,9 @@ class TestIssues(QuantityTestCase): def f(x): return 2 * x - self.assertEqual(f(ureg.Quantity(1, "")), 2) - self.assertRaises(DimensionalityError, f, ureg.Quantity(1, "m")) + assert f(ureg.Quantity(1, "")) == 2 + with pytest.raises(DimensionalityError): + f(ureg.Quantity(1, "m")) def test_issue625a(self): Q_ = ureg.Quantity @@ -521,11 +528,11 @@ class TestIssues(QuantityTestCase): lunar_module_height = Q_(10, "m") t1 = calculate_time_to_fall(lunar_module_height) # print(t1) - self.assertAlmostEqual(t1, Q_(1.4285714285714286, "s")) + assert round(abs(t1 - Q_(1.4285714285714286, "s")), 7) == 0 moon_gravity = Q_(1.625, "m/s^2") t2 = calculate_time_to_fall(lunar_module_height, moon_gravity) - self.assertAlmostEqual(t2, Q_(3.508232077228117, "s")) + assert round(abs(t2 - Q_(3.508232077228117, "s")), 7) == 0 def test_issue625b(self): Q_ = ureg.Quantity @@ -550,10 +557,10 @@ class TestIssues(QuantityTestCase): return time * rate d1 = get_displacement(Q_(2, "s")) - self.assertAlmostEqual(d1, Q_(2, "m")) + assert round(abs(d1 - Q_(2, "m")), 7) == 0 d2 = get_displacement(Q_(2, "s"), Q_(1, "deg/s")) - self.assertAlmostEqual(d2, Q_(2, " deg")) + assert round(abs(d2 - Q_(2, " deg")), 7) == 0 def test_issue625c(self): u = UnitRegistry() @@ -562,18 +569,18 @@ class TestIssues(QuantityTestCase): def get_product(a=2 * u.m, b=3 * u.m, c=5 * u.m): return a * b * c - self.assertEqual(get_product(a=3 * u.m), 45 * u.m ** 3) - self.assertEqual(get_product(b=2 * u.m), 20 * u.m ** 3) - self.assertEqual(get_product(c=1 * u.dimensionless), 6 * u.m ** 2) + assert get_product(a=3 * u.m) == 45 * u.m ** 3 + assert get_product(b=2 * u.m) == 20 * u.m ** 3 + assert get_product(c=1 * u.dimensionless) == 6 * u.m ** 2 def test_issue655a(self): distance = 1 * ureg.m time = 1 * ureg.s velocity = distance / time - self.assertEqual(distance.check("[length]"), True) - self.assertEqual(distance.check("[time]"), False) - self.assertEqual(velocity.check("[length] / [time]"), True) - self.assertEqual(velocity.check("1 / [time] * [length]"), True) + assert distance.check("[length]") + assert not distance.check("[time]") + assert velocity.check("[length] / [time]") + assert velocity.check("1 / [time] * [length]") def test_issue655b(self): Q_ = ureg.Quantity @@ -586,11 +593,11 @@ class TestIssues(QuantityTestCase): length = Q_(1, ureg.m) # Assume earth gravity t = pendulum_period(length) - self.assertAlmostEqual(t, Q_("2.0064092925890407 second")) + assert round(abs(t - Q_("2.0064092925890407 second")), 7) == 0 # Use moon gravity moon_gravity = Q_(1.625, "m/s^2") t = pendulum_period(length, moon_gravity) - self.assertAlmostEqual(t, Q_("4.928936075204336 second")) + assert round(abs(t - Q_("4.928936075204336 second")), 7) == 0 def test_issue783(self): assert not ureg("g") == [] @@ -658,12 +665,12 @@ class TestIssues(QuantityTestCase): def test_issue932(self): q = ureg.Quantity("1 kg") - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): q.to("joule") ureg.enable_contexts("energy", *(Context() for _ in range(20))) q.to("joule") ureg.disable_contexts() - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): q.to("joule") def test_issue960(self): @@ -681,10 +688,10 @@ class TestIssues(QuantityTestCase): q = 3 * ureg.s d = MultiplicativeDictionary({4: 5, 6: 7}) assert q * d == MultiplicativeDictionary({4: 15 * ureg.s, 6: 21 * ureg.s}) - with self.assertRaises(TypeError): + with pytest.raises(TypeError): d * q - @helpers.requires_numpy() + @helpers.requires_numpy def test_issue973(self): """Verify that an empty array Quantity can be created through multiplication.""" q0 = np.array([]) * ureg.m # by Unit @@ -698,10 +705,11 @@ class TestIssues(QuantityTestCase): of same base type succeeds""" q = 1 * ureg.mg / ureg.g / ureg.kg q.ito_reduced_units() - self.assertIsInstance(q, ureg.Quantity) + assert isinstance(q, ureg.Quantity) def test_issue1062_issue1097(self): # Must not be used by any other tests + ureg = UnitRegistry() assert "nanometer" not in ureg._units for i in range(5): ctx = Context.from_lines(["@context _", "cal = 4 J"]) @@ -745,7 +753,7 @@ class TestIssues(QuantityTestCase): ureg.enable_contexts("c2") ureg.enable_contexts("c3") - @helpers.requires_numpy() + @helpers.requires_numpy def test_issue1144_1102(self): # Performing operations shouldn't modify the original objects # Issue 1144 @@ -768,7 +776,7 @@ class TestIssues(QuantityTestCase): q1 - q2 assert all(q1 == ureg.Quantity([-287.78, -32.24, -1.94], ddc)) - @helpers.requires_numpy() + @helpers.requires_numpy def test_issue_1136(self): assert (2 ** ureg.Quantity([2, 3], "") == 2 ** np.array([2, 3])).all() @@ -780,14 +788,14 @@ class TestIssues(QuantityTestCase): foo1 = get_application_registry().Quantity(1, "s") foo2 = pickle.loads(pickle.dumps(foo1)) - self.assertIsInstance(foo1, foo2.__class__) - self.assertIsInstance(foo2, foo1.__class__) + assert isinstance(foo1, foo2.__class__) + assert isinstance(foo2, foo1.__class__) - @helpers.requires_numpy() + @helpers.requires_numpy def test_issue1174(self): q = [1.0, -2.0, 3.0, -4.0] * self.ureg.meter - self.assertTrue(np.sign(q[0].magnitude)) - self.assertTrue(np.sign(q[1].magnitude)) + assert np.sign(q[0].magnitude) + assert np.sign(q[1].magnitude) if np is not None: diff --git a/pint/testsuite/test_log_units.py b/pint/testsuite/test_log_units.py index 0860dd7..77eba02 100644 --- a/pint/testsuite/test_log_units.py +++ b/pint/testsuite/test_log_units.py @@ -1,9 +1,10 @@ +import logging import math import pytest from pint import OffsetUnitCalculusError, UnitRegistry -from pint.testsuite import QuantityTestCase +from pint.testsuite import QuantityTestCase, helpers from pint.unit import Unit, UnitsContainer @@ -18,10 +19,7 @@ def ureg(): class TestLogarithmicQuantity(QuantityTestCase): - - FORCE_NDARRAY = False - - def test_log_quantity_creation(self): + def test_log_quantity_creation(self, caplog): # Following Quantity Creation Pattern for args in ( @@ -30,42 +28,46 @@ class TestLogarithmicQuantity(QuantityTestCase): (4.2, self.ureg.dBm), ): x = self.Q_(*args) - self.assertEqual(x.magnitude, 4.2) - self.assertEqual(x.units, UnitsContainer(decibelmilliwatt=1)) + assert x.magnitude == 4.2 + assert x.units == UnitsContainer(decibelmilliwatt=1) x = self.Q_(self.Q_(4.2, "dBm")) - self.assertEqual(x.magnitude, 4.2) - self.assertEqual(x.units, UnitsContainer(decibelmilliwatt=1)) + assert x.magnitude == 4.2 + assert x.units == UnitsContainer(decibelmilliwatt=1) x = self.Q_(4.2, UnitsContainer(decibelmilliwatt=1)) y = self.Q_(x) - self.assertEqual(x.magnitude, y.magnitude) - self.assertEqual(x.units, y.units) - self.assertIsNot(x, y) + assert x.magnitude == y.magnitude + assert x.units == y.units + assert x is not y # Using multiplications for dB units requires autoconversion to baseunits new_reg = UnitRegistry(autoconvert_offset_to_baseunit=True) x = new_reg.Quantity("4.2 * dBm") - self.assertEqual(x.magnitude, 4.2) - self.assertEqual(x.units, UnitsContainer(decibelmilliwatt=1)) + assert x.magnitude == 4.2 + assert x.units == UnitsContainer(decibelmilliwatt=1) + + with caplog.at_level(logging.DEBUG): + assert "wally" not in caplog.text + assert 4.2 * new_reg.dBm == new_reg.Quantity(4.2, 2 * new_reg.dBm) - with self.capture_log() as buffer: - self.assertEqual(4.2 * new_reg.dBm, new_reg.Quantity(4.2, 2 * new_reg.dBm)) - self.assertEqual(len(buffer), 1) + assert len(caplog.records) == 1 def test_log_convert(self): # # 1 dB = 1/10 * bel - # self.assertQuantityAlmostEqual(self.Q_(1.0, "dB").to("dimensionless"), self.Q_(1, "bell") / 10) + # helpers.assert_quantity_almost_equal(self.Q_(1.0, "dB").to("dimensionless"), self.Q_(1, "bell") / 10) # # Uncomment Bell unit in default_en.txt # ## Test dB to dB units octave - decade # 1 decade = log2(10) octave - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(1.0, "decade"), self.Q_(math.log(10, 2), "octave") ) # ## Test dB to dB units dBm - dBu # 0 dBm = 1mW = 1e3 uW = 30 dBu - self.assertAlmostEqual(self.Q_(0.0, "dBm"), self.Q_(29.999999999999996, "dBu")) + helpers.assert_quantity_almost_equal( + self.Q_(0.0, "dBm"), self.Q_(29.999999999999996, "dBu"), atol=1e-7 + ) def test_mix_regular_log_units(self): # Test regular-logarithmic mixed definition, such as dB/km or dB/cm @@ -73,13 +75,15 @@ class TestLogarithmicQuantity(QuantityTestCase): # Multiplications and divisions with a mix of Logarithmic Units and regular Units is normally not possible. # The reason is that dB are considered by pint like offset units. # Multiplications and divisions that involve offset units are badly defined, so pint raises an error - with self.assertRaises(OffsetUnitCalculusError): + with pytest.raises(OffsetUnitCalculusError): (-10.0 * self.ureg.dB) / (1 * self.ureg.cm) # However, if the flag autoconvert_offset_to_baseunit=True is given to UnitRegistry, then pint converts the unit to base. # With this flag on multiplications and divisions are now possible: new_reg = UnitRegistry(autoconvert_offset_to_baseunit=True) - self.assertQuantityAlmostEqual(-10 * new_reg.dB / new_reg.cm, 0.1 / new_reg.cm) + helpers.assert_quantity_almost_equal( + -10 * new_reg.dB / new_reg.cm, 0.1 / new_reg.cm + ) log_unit_names = [ diff --git a/pint/testsuite/test_measurement.py b/pint/testsuite/test_measurement.py index 789e47c..323140f 100644 --- a/pint/testsuite/test_measurement.py +++ b/pint/testsuite/test_measurement.py @@ -1,22 +1,19 @@ +import pytest + from pint import DimensionalityError from pint.testsuite import QuantityTestCase, helpers @helpers.requires_not_uncertainties() class TestNotMeasurement(QuantityTestCase): - - FORCE_NDARRAY = False - def test_instantiate(self): M_ = self.ureg.Measurement - self.assertRaises(RuntimeError, M_, 4.0, 0.1, "s") + with pytest.raises(RuntimeError): + M_(4.0, 0.1, "s") @helpers.requires_uncertainties() class TestMeasurement(QuantityTestCase): - - FORCE_NDARRAY = False - def test_simple(self): M_ = self.ureg.Measurement M_(4.0, 0.1, "s") @@ -35,11 +32,11 @@ class TestMeasurement(QuantityTestCase): ) for m in ms: - self.assertEqual(m.value, v) - self.assertEqual(m.error, u) - self.assertEqual(m.rel, m.error / abs(m.value)) + assert m.value == v + assert m.error == u + assert m.rel == m.error / abs(m.value) - def test_format(self): + def test_format(self, subtests): v, u = self.Q_(4.0, "s ** 2"), self.Q_(0.1, "s ** 2") m = self.ureg.Measurement(v, u) @@ -58,10 +55,10 @@ class TestMeasurement(QuantityTestCase): ("{:.1fC}", "(4.0+/-0.1) second**2"), ("{:.1fLx}", r"\SI{4.0 +- 0.1}{\second\squared}"), ): - with self.subTest(spec): - self.assertEqual(spec.format(m), result) + with subtests.test(spec): + assert spec.format(m) == result - def test_format_paru(self): + def test_format_paru(self, subtests): v, u = self.Q_(0.20, "s ** 2"), self.Q_(0.01, "s ** 2") m = self.ureg.Measurement(v, u) @@ -73,10 +70,10 @@ class TestMeasurement(QuantityTestCase): ("{:.3uSH}", "0.2000(100) second<sup>2</sup>"), ("{:.3uSC}", "0.2000(100) second**2"), ): - with self.subTest(spec): - self.assertEqual(spec.format(m), result) + with subtests.test(spec): + assert spec.format(m) == result - def test_format_u(self): + def test_format_u(self, subtests): v, u = self.Q_(0.20, "s ** 2"), self.Q_(0.01, "s ** 2") m = self.ureg.Measurement(v, u) @@ -92,11 +89,11 @@ class TestMeasurement(QuantityTestCase): ), ("{:.1uLx}", r"\SI{0.20 +- 0.01}{\second\squared}"), ): - with self.subTest(spec): - self.assertEqual(spec.format(m), result) + with subtests.test(spec): + assert spec.format(m) == result - def test_format_percu(self): - self.test_format_perce() + def test_format_percu(self, subtests): + self.test_format_perce(subtests) v, u = self.Q_(0.20, "s ** 2"), self.Q_(0.01, "s ** 2") m = self.ureg.Measurement(v, u) @@ -107,10 +104,10 @@ class TestMeasurement(QuantityTestCase): ("{:.1u%H}", "(20 ± 1)% second<sup>2</sup>"), ("{:.1u%C}", "(20+/-1)% second**2"), ): - with self.subTest(spec): - self.assertEqual(spec.format(m), result) + with subtests.test(spec): + assert spec.format(m) == result - def test_format_perce(self): + def test_format_perce(self, subtests): v, u = self.Q_(0.20, "s ** 2"), self.Q_(0.01, "s ** 2") m = self.ureg.Measurement(v, u) for spec, result in ( @@ -123,10 +120,10 @@ class TestMeasurement(QuantityTestCase): ("{:.1ueH}", "(2.0 ± 0.1)×10<sup>-1</sup> second<sup>2</sup>"), ("{:.1ueC}", "(2.0+/-0.1)e-01 second**2"), ): - with self.subTest(spec): - self.assertEqual(spec.format(m), result) + with subtests.test(spec): + assert spec.format(m) == result - def test_format_exponential_pos(self): + def test_format_exponential_pos(self, subtests): # Quantities in exponential format come with their own parenthesis, don't wrap # them twice m = self.ureg.Quantity(4e20, "s^2").plus_minus(1e19) @@ -139,10 +136,10 @@ class TestMeasurement(QuantityTestCase): ("{:C}", "(4.00+/-0.10)e+20 second**2"), ("{:Lx}", r"\SI{4.00 +- 0.10 e+20}{\second\squared}"), ): - with self.subTest(spec): - self.assertEqual(spec.format(m), result) + with subtests.test(spec): + assert spec.format(m) == result - def test_format_exponential_neg(self): + def test_format_exponential_neg(self, subtests): m = self.ureg.Quantity(4e-20, "s^2").plus_minus(1e-21) for spec, result in ( ("{}", "(4.00 +/- 0.10)e-20 second ** 2"), @@ -156,19 +153,19 @@ class TestMeasurement(QuantityTestCase): ("{:C}", "(4.00+/-0.10)e-20 second**2"), ("{:Lx}", r"\SI{4.00 +- 0.10 e-20}{\second\squared}"), ): - with self.subTest(spec): - self.assertEqual(spec.format(m), result) + with subtests.test(spec): + assert spec.format(m) == result def test_raise_build(self): v, u = self.Q_(1.0, "s"), self.Q_(0.1, "s") o = self.Q_(0.1, "m") M_ = self.ureg.Measurement - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): M_(v, o) - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): v.plus_minus(o) - with self.assertRaises(ValueError): + with pytest.raises(ValueError): v.plus_minus(u, relative=True) def test_propagate_linear(self): @@ -183,35 +180,41 @@ class TestMeasurement(QuantityTestCase): for factor, m in zip((3, -3, 3, -3), (m1, m3, m1, m3)): r = factor * m - self.assertAlmostEqual(r.value.magnitude, factor * m.value.magnitude) - self.assertAlmostEqual(r.error.magnitude, abs(factor * m.error.magnitude)) - self.assertEqual(r.value.units, m.value.units) + helpers.assert_quantity_almost_equal( + r.value.magnitude, factor * m.value.magnitude + ) + helpers.assert_quantity_almost_equal( + r.error.magnitude, abs(factor * m.error.magnitude) + ) + assert r.value.units == m.value.units for ml, mr in zip((m1, m1, m1, m3), (m1, m2, m3, m3)): r = ml + mr - self.assertAlmostEqual( + helpers.assert_quantity_almost_equal( r.value.magnitude, ml.value.magnitude + mr.value.magnitude ) - self.assertAlmostEqual( + helpers.assert_quantity_almost_equal( r.error.magnitude, - ml.error.magnitude + mr.error.magnitude - if ml is mr - else (ml.error.magnitude ** 2 + mr.error.magnitude ** 2) ** 0.5, + ( + ml.error.magnitude + mr.error.magnitude + if ml is mr + else (ml.error.magnitude ** 2 + mr.error.magnitude ** 2) ** 0.5 + ), ) - self.assertEqual(r.value.units, ml.value.units) + assert r.value.units == ml.value.units for ml, mr in zip((m1, m1, m1, m3), (m1, m2, m3, m3)): r = ml - mr - self.assertAlmostEqual( + helpers.assert_quantity_almost_equal( r.value.magnitude, ml.value.magnitude - mr.value.magnitude ) - self.assertAlmostEqual( + helpers.assert_quantity_almost_equal( r.error.magnitude, 0 if ml is mr else (ml.error.magnitude ** 2 + mr.error.magnitude ** 2) ** 0.5, ) - self.assertEqual(r.value.units, ml.value.units) + assert r.value.units == ml.value.units def test_propagate_product(self): @@ -228,20 +231,20 @@ class TestMeasurement(QuantityTestCase): for ml, mr in zip((m1, m1, m1, m3, m4), (m1, m2, m3, m3, m5)): r = ml * mr - self.assertAlmostEqual( + helpers.assert_quantity_almost_equal( r.value.magnitude, ml.value.magnitude * mr.value.magnitude ) - self.assertEqual(r.value.units, ml.value.units * mr.value.units) + assert r.value.units == ml.value.units * mr.value.units for ml, mr in zip((m1, m1, m1, m3, m4), (m1, m2, m3, m3, m5)): r = ml / mr - self.assertAlmostEqual( + helpers.assert_quantity_almost_equal( r.value.magnitude, ml.value.magnitude / mr.value.magnitude ) - self.assertEqual(r.value.units, ml.value.units / mr.value.units) + assert r.value.units == ml.value.units / mr.value.units def test_measurement_comparison(self): x = self.Q_(4.2, "meter") y = self.Q_(5.0, "meter").plus_minus(0.1) - self.assertTrue(x <= y) - self.assertFalse(x >= y) + assert x <= y + assert not (x >= y) diff --git a/pint/testsuite/test_non_int.py b/pint/testsuite/test_non_int.py index 4a377d2..63f8091 100644 --- a/pint/testsuite/test_non_int.py +++ b/pint/testsuite/test_non_int.py @@ -5,9 +5,10 @@ import pickle from decimal import Decimal from fractions import Fraction +import pytest + from pint import DimensionalityError, OffsetUnitCalculusError, UnitRegistry -from pint.testsuite import QuantityTestCase -from pint.testsuite.parameterized import ParameterizedTestMixin as ParameterizedTestCase +from pint.testsuite import QuantityTestCase, helpers from pint.unit import UnitsContainer @@ -18,36 +19,25 @@ class FakeWrapper: class NonIntTypeQuantityTestCase(QuantityTestCase): - - NON_INT_TYPE = None - - @classmethod - def setUpClass(cls): - cls.ureg = UnitRegistry( - force_ndarray=cls.FORCE_NDARRAY, non_int_type=cls.NON_INT_TYPE - ) - cls.Q_ = cls.ureg.Quantity - cls.U_ = cls.ureg.Unit - - def assertQuantityAlmostEqual( + def assert_quantity_almost_equal( self, first, second, rtol="1e-07", atol="0", msg=None ): if isinstance(first, self.Q_): - self.assertIsInstance(first.m, (self.NON_INT_TYPE, int)) + assert isinstance(first.m, (self.NON_INT_TYPE, int)) else: - self.assertIsInstance(first, (self.NON_INT_TYPE, int)) + assert isinstance(first, (self.NON_INT_TYPE, int)) if isinstance(second, self.Q_): - self.assertIsInstance(second.m, (self.NON_INT_TYPE, int)) + assert isinstance(second.m, (self.NON_INT_TYPE, int)) else: - self.assertIsInstance(second, (self.NON_INT_TYPE, int)) - super().assertQuantityAlmostEqual( + assert isinstance(second, (self.NON_INT_TYPE, int)) + super().assert_quantity_almost_equal( first, second, self.NON_INT_TYPE(rtol), self.NON_INT_TYPE(atol), msg ) def QP_(self, value, units): - self.assertIsInstance(value, str) + assert isinstance(value, str) return self.Q_(self.NON_INT_TYPE(value), units) @@ -65,25 +55,24 @@ class _TestBasic: (self.Q_(value, "meter"),), ): x = self.Q_(*args) - self.assertEqual(x.magnitude, value) - self.assertEqual(x.units, self.ureg.UnitsContainer(meter=1)) + assert x.magnitude == value + assert x.units == self.ureg.UnitsContainer(meter=1) x = self.Q_(value, UnitsContainer(length=1)) y = self.Q_(x) - self.assertEqual(x.magnitude, y.magnitude) - self.assertEqual(x.units, y.units) - self.assertIsNot(x, y) + assert x.magnitude == y.magnitude + assert x.units == y.units + assert x is not y x = self.Q_(value, None) - self.assertEqual(x.magnitude, value) - self.assertEqual(x.units, UnitsContainer()) + assert x.magnitude == value + assert x.units == UnitsContainer() with self.capture_log() as buffer: - self.assertEqual( - value * self.ureg.meter, - self.Q_(value, self.NON_INT_TYPE("2") * self.ureg.meter), + assert value * self.ureg.meter == self.Q_( + value, self.NON_INT_TYPE("2") * self.ureg.meter ) - self.assertEqual(len(buffer), 1) + assert len(buffer) == 1 def test_quantity_comparison(self): x = self.QP_("4.2", "meter") @@ -92,37 +81,34 @@ class _TestBasic: j = self.QP_("5", "meter*meter") # identity for single object - self.assertTrue(x == x) - self.assertFalse(x != x) + assert x == x + assert not (x != x) # identity for multiple objects with same value - self.assertTrue(x == y) - self.assertFalse(x != y) + assert x == y + assert not (x != y) - self.assertTrue(x <= y) - self.assertTrue(x >= y) - self.assertFalse(x < y) - self.assertFalse(x > y) + assert x <= y + assert x >= y + assert not (x < y) + assert not (x > y) - self.assertFalse(x == z) - self.assertTrue(x != z) - self.assertTrue(x < z) + assert not (x == z) + assert x != z + assert x < z - self.assertTrue(z != j) + assert z != j - self.assertNotEqual(z, j) - self.assertEqual(self.QP_("0", "meter"), self.QP_("0", "centimeter")) - self.assertNotEqual(self.QP_("0", "meter"), self.QP_("0", "second")) + assert z != j + assert self.QP_("0", "meter") == self.QP_("0", "centimeter") + assert self.QP_("0", "meter") != self.QP_("0", "second") - self.assertLess(self.QP_("10", "meter"), self.QP_("5", "kilometer")) + assert self.QP_("10", "meter") < self.QP_("5", "kilometer") def test_quantity_comparison_convert(self): - self.assertEqual(self.QP_("1000", "millimeter"), self.QP_("1", "meter")) - self.assertEqual( - self.QP_("1000", "millimeter/min"), - self.Q_( - self.NON_INT_TYPE("1000") / self.NON_INT_TYPE("60"), "millimeter/s" - ), + assert self.QP_("1000", "millimeter") == self.QP_("1", "meter") + assert self.QP_("1000", "millimeter/min") == self.Q_( + self.NON_INT_TYPE("1000") / self.NON_INT_TYPE("60"), "millimeter/s" ) def test_quantity_hash(self): @@ -130,29 +116,31 @@ class _TestBasic: x2 = self.QP_("4200", "millimeter") y = self.QP_("2", "second") z = self.QP_("0.5", "hertz") - self.assertEqual(hash(x), hash(x2)) + assert hash(x) == hash(x2) # Dimensionless equality - self.assertEqual(hash(y * z), hash(1.0)) + assert hash(y * z) == hash(1.0) # Dimensionless equality from a different unit registry ureg2 = UnitRegistry(force_ndarray=self.FORCE_NDARRAY) y2 = ureg2.Quantity(self.NON_INT_TYPE("2"), "second") z2 = ureg2.Quantity(self.NON_INT_TYPE("0.5"), "hertz") - self.assertEqual(hash(y * z), hash(y2 * z2)) + assert hash(y * z) == hash(y2 * z2) def test_to_base_units(self): x = self.Q_("1*inch") - self.assertQuantityAlmostEqual(x.to_base_units(), self.QP_("0.0254", "meter")) + helpers.assert_quantity_almost_equal( + x.to_base_units(), self.QP_("0.0254", "meter") + ) x = self.Q_("1*inch*inch") - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( x.to_base_units(), self.Q_( self.NON_INT_TYPE("0.0254") ** self.NON_INT_TYPE("2.0"), "meter*meter" ), ) x = self.Q_("1*inch/minute") - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( x.to_base_units(), self.Q_( self.NON_INT_TYPE("0.0254") / self.NON_INT_TYPE("60"), "meter/second" @@ -160,190 +148,196 @@ class _TestBasic: ) def test_convert(self): - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_("2 inch").to("meter"), self.Q_(self.NON_INT_TYPE("2") * self.NON_INT_TYPE("0.0254"), "meter"), ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_("2 meter").to("inch"), self.Q_(self.NON_INT_TYPE("2") / self.NON_INT_TYPE("0.0254"), "inch"), ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_("2 sidereal_year").to("second"), self.QP_("63116297.5325", "second") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_("2.54 centimeter/second").to("inch/second"), self.Q_("1 inch/second"), ) - self.assertAlmostEqual(self.Q_("2.54 centimeter").to("inch").magnitude, 1) - self.assertAlmostEqual(self.Q_("2 second").to("millisecond").magnitude, 2000) + assert round(abs(self.Q_("2.54 centimeter").to("inch").magnitude - 1), 7) == 0 + assert ( + round(abs(self.Q_("2 second").to("millisecond").magnitude - 2000), 7) == 0 + ) def test_convert_from(self): x = self.Q_("2*inch") meter = self.ureg.meter # from quantity - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( meter.from_(x), self.Q_(self.NON_INT_TYPE("2") * self.NON_INT_TYPE("0.0254"), "meter"), ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( meter.m_from(x), self.NON_INT_TYPE("2") * self.NON_INT_TYPE("0.0254") ) # from unit - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( meter.from_(self.ureg.inch), self.QP_("0.0254", "meter") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( meter.m_from(self.ureg.inch), self.NON_INT_TYPE("0.0254") ) # from number - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( meter.from_(2, strict=False), self.QP_("2", "meter") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( meter.m_from(self.NON_INT_TYPE("2"), strict=False), self.NON_INT_TYPE("2") ) # from number (strict mode) - self.assertRaises(ValueError, meter.from_, self.NON_INT_TYPE("2")) - self.assertRaises(ValueError, meter.m_from, self.NON_INT_TYPE("2")) + with pytest.raises(ValueError): + meter.from_(self.NON_INT_TYPE("2")) + with pytest.raises(ValueError): + meter.m_from(self.NON_INT_TYPE("2")) def test_context_attr(self): - self.assertEqual(self.ureg.meter, self.QP_("1", "meter")) + assert self.ureg.meter == self.QP_("1", "meter") def test_both_symbol(self): - self.assertEqual(self.QP_("2", "ms"), self.QP_("2", "millisecond")) - self.assertEqual(self.QP_("2", "cm"), self.QP_("2", "centimeter")) + assert self.QP_("2", "ms") == self.QP_("2", "millisecond") + assert self.QP_("2", "cm") == self.QP_("2", "centimeter") def test_dimensionless_units(self): twopi = self.NON_INT_TYPE("2") * self.ureg.pi - self.assertAlmostEqual(self.QP_("360", "degree").to("radian").magnitude, twopi) - self.assertAlmostEqual(self.Q_(twopi, "radian"), self.QP_("360", "degree")) - self.assertEqual(self.QP_("1", "radian").dimensionality, UnitsContainer()) - self.assertTrue(self.QP_("1", "radian").dimensionless) - self.assertFalse(self.QP_("1", "radian").unitless) + assert ( + round(abs(self.QP_("360", "degree").to("radian").magnitude - twopi), 7) == 0 + ) + assert round(abs(self.Q_(twopi, "radian") - self.QP_("360", "degree")), 7) == 0 + assert self.QP_("1", "radian").dimensionality == UnitsContainer() + assert self.QP_("1", "radian").dimensionless + assert not self.QP_("1", "radian").unitless - self.assertEqual(self.QP_("1", "meter") / self.QP_("1", "meter"), 1) - self.assertEqual((self.QP_("1", "meter") / self.QP_("1", "mm")).to(""), 1000) + assert self.QP_("1", "meter") / self.QP_("1", "meter") == 1 + assert (self.QP_("1", "meter") / self.QP_("1", "mm")).to("") == 1000 - self.assertEqual(self.Q_(10) // self.QP_("360", "degree"), 1) - self.assertEqual(self.QP_("400", "degree") // self.Q_(twopi), 1) - self.assertEqual(self.QP_("400", "degree") // twopi, 1) - self.assertEqual(7 // self.QP_("360", "degree"), 1) + assert self.Q_(10) // self.QP_("360", "degree") == 1 + assert self.QP_("400", "degree") // self.Q_(twopi) == 1 + assert self.QP_("400", "degree") // twopi == 1 + assert 7 // self.QP_("360", "degree") == 1 def test_offset(self): - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("0", "kelvin").to("kelvin"), self.QP_("0", "kelvin") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("0", "degC").to("kelvin"), self.QP_("273.15", "kelvin") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("0", "degF").to("kelvin"), self.QP_("255.372222", "kelvin"), rtol=0.01, ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("100", "kelvin").to("kelvin"), self.QP_("100", "kelvin") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("100", "degC").to("kelvin"), self.QP_("373.15", "kelvin") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("100", "degF").to("kelvin"), self.QP_("310.92777777", "kelvin"), rtol=0.01, ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("0", "kelvin").to("degC"), self.QP_("-273.15", "degC") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("100", "kelvin").to("degC"), self.QP_("-173.15", "degC") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("0", "kelvin").to("degF"), self.QP_("-459.67", "degF"), rtol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("100", "kelvin").to("degF"), self.QP_("-279.67", "degF"), rtol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("32", "degF").to("degC"), self.QP_("0", "degC"), atol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("100", "degC").to("degF"), self.QP_("212", "degF"), atol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("54", "degF").to("degC"), self.QP_("12.2222", "degC"), atol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("12", "degC").to("degF"), self.QP_("53.6", "degF"), atol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("12", "kelvin").to("degC"), self.QP_("-261.15", "degC"), atol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("12", "degC").to("kelvin"), self.QP_("285.15", "kelvin"), atol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("12", "kelvin").to("degR"), self.QP_("21.6", "degR"), atol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("12", "degR").to("kelvin"), self.QP_("6.66666667", "kelvin"), atol=0.01, ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("12", "degC").to("degR"), self.QP_("513.27", "degR"), atol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("12", "degR").to("degC"), self.QP_("-266.483333", "degC"), atol=0.01, ) def test_offset_delta(self): - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("0", "delta_degC").to("kelvin"), self.QP_("0", "kelvin") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("0", "delta_degF").to("kelvin"), self.QP_("0", "kelvin"), rtol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("100", "kelvin").to("delta_degC"), self.QP_("100", "delta_degC") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("100", "kelvin").to("delta_degF"), self.QP_("180", "delta_degF"), rtol=0.01, ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("100", "delta_degF").to("kelvin"), self.QP_("55.55555556", "kelvin"), rtol=0.01, ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("100", "delta_degC").to("delta_degF"), self.QP_("180", "delta_degF"), rtol=0.01, ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("100", "delta_degF").to("delta_degC"), self.QP_("55.55555556", "delta_degC"), rtol=0.01, ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.QP_("12.3", "delta_degC").to("delta_degF"), self.QP_("22.14", "delta_degF"), rtol=0.01, @@ -360,13 +354,13 @@ class _TestBasic: with self.subTest(protocol=protocol, magnitude=magnitude, unit=unit): q1 = self.QP_(magnitude, unit) q2 = pickle.loads(pickle.dumps(q1, protocol)) - self.assertEqual(q1, q2) + assert q1 == q2 def test_notiter(self): # Verify that iter() crashes immediately, without needing to draw any # element from it, if the magnitude isn't iterable x = self.QP_("1", "m") - with self.assertRaises(TypeError): + with pytest.raises(TypeError): iter(x) @@ -393,10 +387,10 @@ class _TestQuantityBasicMath: id2 = id(value2) value1 = operator(value1, value2) value2_cpy = copy.copy(value2) - self.assertQuantityAlmostEqual(value1, expected_result) - self.assertEqual(id1, id(value1)) - self.assertQuantityAlmostEqual(value2, value2_cpy) - self.assertEqual(id2, id(value2)) + helpers.assert_quantity_almost_equal(value1, expected_result) + assert id1 == id(value1) + helpers.assert_quantity_almost_equal(value2, value2_cpy) + assert id2 == id(value2) def _test_not_inplace(self, operator, value1, value2, expected_result, unit=None): if isinstance(value1, str): @@ -419,11 +413,11 @@ class _TestQuantityBasicMath: result = operator(value1, value2) - self.assertQuantityAlmostEqual(expected_result, result) - self.assertQuantityAlmostEqual(value1, value1_cpy) - self.assertQuantityAlmostEqual(value2, value2_cpy) - self.assertNotEqual(id(result), id1) - self.assertNotEqual(id(result), id2) + helpers.assert_quantity_almost_equal(expected_result, result) + helpers.assert_quantity_almost_equal(value1, value1_cpy) + helpers.assert_quantity_almost_equal(value2, value2_cpy) + assert id(result) != id1 + assert id(result) != id2 def _test_quantity_add_sub(self, unit, func): x = self.Q_(unit, "centimeter") @@ -442,9 +436,12 @@ class _TestQuantityBasicMath: self.Q_(unit + unit / (self.NON_INT_TYPE("2.54") * unit), "inch"), ) func(op.add, a, unit, self.Q_(unit + unit, None)) - self.assertRaises(DimensionalityError, op.add, self.NON_INT_TYPE("10"), x) - self.assertRaises(DimensionalityError, op.add, x, self.NON_INT_TYPE("10")) - self.assertRaises(DimensionalityError, op.add, x, z) + with pytest.raises(DimensionalityError): + op.add(self.NON_INT_TYPE("10"), x) + with pytest.raises(DimensionalityError): + op.add(x, self.NON_INT_TYPE("10")) + with pytest.raises(DimensionalityError): + op.add(x, z) func(op.sub, x, x, self.Q_(unit - unit, "centimeter")) func( @@ -457,9 +454,12 @@ class _TestQuantityBasicMath: self.Q_(unit - unit / (self.NON_INT_TYPE("2.54") * unit), "inch"), ) func(op.sub, a, unit, self.Q_(unit - unit, None)) - self.assertRaises(DimensionalityError, op.sub, self.NON_INT_TYPE("10"), x) - self.assertRaises(DimensionalityError, op.sub, x, self.NON_INT_TYPE("10")) - self.assertRaises(DimensionalityError, op.sub, x, z) + with pytest.raises(DimensionalityError): + op.sub(self.NON_INT_TYPE("10"), x) + with pytest.raises(DimensionalityError): + op.sub(x, self.NON_INT_TYPE("10")) + with pytest.raises(DimensionalityError): + op.sub(x, z) def _test_quantity_iadd_isub(self, unit, func): x = self.Q_(unit, "centimeter") @@ -476,17 +476,23 @@ class _TestQuantityBasicMath: ) func(op.iadd, y, x, self.Q_(unit + unit / self.NON_INT_TYPE("2.54"), "inch")) func(op.iadd, a, unit, self.Q_(unit + unit, None)) - self.assertRaises(DimensionalityError, op.iadd, self.NON_INT_TYPE("10"), x) - self.assertRaises(DimensionalityError, op.iadd, x, self.NON_INT_TYPE("10")) - self.assertRaises(DimensionalityError, op.iadd, x, z) + with pytest.raises(DimensionalityError): + op.iadd(self.NON_INT_TYPE("10"), x) + with pytest.raises(DimensionalityError): + op.iadd(x, self.NON_INT_TYPE("10")) + with pytest.raises(DimensionalityError): + op.iadd(x, z) func(op.isub, x, x, self.Q_(unit - unit, "centimeter")) func(op.isub, x, y, self.Q_(unit - self.NON_INT_TYPE("2.54"), "centimeter")) func(op.isub, y, x, self.Q_(unit - unit / self.NON_INT_TYPE("2.54"), "inch")) func(op.isub, a, unit, self.Q_(unit - unit, None)) - self.assertRaises(DimensionalityError, op.sub, self.NON_INT_TYPE("10"), x) - self.assertRaises(DimensionalityError, op.sub, x, self.NON_INT_TYPE("10")) - self.assertRaises(DimensionalityError, op.sub, x, z) + with pytest.raises(DimensionalityError): + op.sub(self.NON_INT_TYPE("10"), x) + with pytest.raises(DimensionalityError): + op.sub(x, self.NON_INT_TYPE("10")) + with pytest.raises(DimensionalityError): + op.sub(x, z) def _test_quantity_mul_div(self, unit, func): func(op.mul, unit * self.NON_INT_TYPE("10"), "4.2*meter", "42*meter", unit) @@ -511,12 +517,18 @@ class _TestQuantityBasicMath: def _test_quantity_floordiv(self, unit, func): a = self.Q_("10*meter") b = self.Q_("3*second") - self.assertRaises(DimensionalityError, op.floordiv, a, b) - self.assertRaises(DimensionalityError, op.floordiv, self.NON_INT_TYPE("3"), b) - self.assertRaises(DimensionalityError, op.floordiv, a, self.NON_INT_TYPE("3")) - self.assertRaises(DimensionalityError, op.ifloordiv, a, b) - self.assertRaises(DimensionalityError, op.ifloordiv, self.NON_INT_TYPE("3"), b) - self.assertRaises(DimensionalityError, op.ifloordiv, a, self.NON_INT_TYPE("3")) + with pytest.raises(DimensionalityError): + op.floordiv(a, b) + with pytest.raises(DimensionalityError): + op.floordiv(self.NON_INT_TYPE("3"), b) + with pytest.raises(DimensionalityError): + op.floordiv(a, self.NON_INT_TYPE("3")) + with pytest.raises(DimensionalityError): + op.ifloordiv(a, b) + with pytest.raises(DimensionalityError): + op.ifloordiv(self.NON_INT_TYPE("3"), b) + with pytest.raises(DimensionalityError): + op.ifloordiv(a, self.NON_INT_TYPE("3")) func( op.floordiv, unit * self.NON_INT_TYPE("10"), @@ -529,12 +541,18 @@ class _TestQuantityBasicMath: def _test_quantity_mod(self, unit, func): a = self.Q_("10*meter") b = self.Q_("3*second") - self.assertRaises(DimensionalityError, op.mod, a, b) - self.assertRaises(DimensionalityError, op.mod, 3, b) - self.assertRaises(DimensionalityError, op.mod, a, 3) - self.assertRaises(DimensionalityError, op.imod, a, b) - self.assertRaises(DimensionalityError, op.imod, 3, b) - self.assertRaises(DimensionalityError, op.imod, a, 3) + with pytest.raises(DimensionalityError): + op.mod(a, b) + with pytest.raises(DimensionalityError): + op.mod(3, b) + with pytest.raises(DimensionalityError): + op.mod(a, 3) + with pytest.raises(DimensionalityError): + op.imod(a, b) + with pytest.raises(DimensionalityError): + op.imod(3, b) + with pytest.raises(DimensionalityError): + op.imod(a, 3) func( op.mod, unit * self.NON_INT_TYPE("10"), @@ -560,25 +578,25 @@ class _TestQuantityBasicMath: b = self.Q_(b) q, r = divmod(a, b) - self.assertEqual(q, a // b) - self.assertEqual(r, a % b) - self.assertQuantityEqual(a, (q * b) + r) - self.assertEqual(q, math.floor(q)) + assert q == a // b + assert r == a % b + helpers.assert_quantity_equal(a, (q * b) + r) + assert q == math.floor(q) if b > (0 * b): - self.assertTrue((0 * b) <= r < b) + assert (0 * b) <= r < b else: - self.assertTrue((0 * b) >= r > b) + assert (0 * b) >= r > b if isinstance(a, self.Q_): - self.assertEqual(r.units, a.units) + assert r.units == a.units else: - self.assertTrue(r.unitless) - self.assertTrue(q.unitless) + assert r.unitless + assert q.unitless copy_a = copy.copy(a) a %= b - self.assertEqual(a, r) + assert a == r copy_a //= b - self.assertEqual(copy_a, q) + assert copy_a == q def _test_quantity_divmod(self): self._test_quantity_divmod_one("10*meter", "4.2*inch") @@ -602,9 +620,12 @@ class _TestQuantityBasicMath: a = self.Q_("10*meter") b = self.Q_("3*second") - self.assertRaises(DimensionalityError, divmod, a, b) - self.assertRaises(DimensionalityError, divmod, 3, b) - self.assertRaises(DimensionalityError, divmod, a, 3) + with pytest.raises(DimensionalityError): + divmod(a, b) + with pytest.raises(DimensionalityError): + divmod(3, b) + with pytest.raises(DimensionalityError): + divmod(a, 3) def _test_numeric(self, unit, ifunc): self._test_quantity_add_sub(unit, self._test_not_inplace) @@ -627,28 +648,30 @@ class _TestQuantityBasicMath: zy = self.Q_(fun(y.magnitude), "meter") rx = fun(x) ry = fun(y) - self.assertEqual(rx, zx, "while testing {0}".format(fun)) - self.assertEqual(ry, zy, "while testing {0}".format(fun)) - self.assertIsNot(rx, zx, "while testing {0}".format(fun)) - self.assertIsNot(ry, zy, "while testing {0}".format(fun)) + assert rx == zx, "while testing {0}".format(fun) + assert ry == zy, "while testing {0}".format(fun) + assert rx is not zx, "while testing {0}".format(fun) + assert ry is not zy, "while testing {0}".format(fun) def test_quantity_float_complex(self): x = self.QP_("-4.2", None) y = self.QP_("4.2", None) z = self.QP_("1", "meter") for fun in (float, complex): - self.assertEqual(fun(x), fun(x.magnitude)) - self.assertEqual(fun(y), fun(y.magnitude)) - self.assertRaises(DimensionalityError, fun, z) + assert fun(x) == fun(x.magnitude) + assert fun(y) == fun(y.magnitude) + with pytest.raises(DimensionalityError): + fun(z) def test_not_inplace(self): self._test_numeric(self.NON_INT_TYPE("1.0"), self._test_not_inplace) -class _TestOffsetUnitMath(ParameterizedTestCase): - def setup(self): - self.ureg.autoconvert_offset_to_baseunit = False - self.ureg.default_as_delta = True +class _TestOffsetUnitMath: + @classmethod + def setup_class(cls): + cls.ureg.autoconvert_offset_to_baseunit = False + cls.ureg.default_as_delta = True additions = [ # --- input tuple -------------------- | -- expected result -- @@ -690,7 +713,7 @@ class _TestOffsetUnitMath(ParameterizedTestCase): ((("100", "delta_degF"), ("10", "delta_degF")), ("110", "delta_degF")), ] - @ParameterizedTestCase.parameterize(("input", "expected_output"), additions) + @pytest.mark.parametrize(("input", "expected_output"), additions) def test_addition(self, input_tuple, expected): self.ureg.autoconvert_offset_to_baseunit = False qin1, qin2 = input_tuple @@ -698,11 +721,12 @@ class _TestOffsetUnitMath(ParameterizedTestCase): # update input tuple with new values to have correct values on failure input_tuple = q1, q2 if expected == "error": - self.assertRaises(OffsetUnitCalculusError, op.add, q1, q2) + with pytest.raises(OffsetUnitCalculusError): + op.add(q1, q2) else: expected = self.QP_(*expected) - self.assertEqual(op.add(q1, q2).units, expected.units) - self.assertQuantityAlmostEqual(op.add(q1, q2), expected, atol="0.01") + assert op.add(q1, q2).units == expected.units + helpers.assert_quantity_almost_equal(op.add(q1, q2), expected, atol="0.01") subtractions = [ ((("100", "kelvin"), ("10", "kelvin")), ("90", "kelvin")), @@ -743,18 +767,19 @@ class _TestOffsetUnitMath(ParameterizedTestCase): ((("100", "delta_degF"), ("10", "delta_degF")), ("90", "delta_degF")), ] - @ParameterizedTestCase.parameterize(("input", "expected_output"), subtractions) + @pytest.mark.parametrize(("input", "expected_output"), subtractions) def test_subtraction(self, input_tuple, expected): self.ureg.autoconvert_offset_to_baseunit = False qin1, qin2 = input_tuple q1, q2 = self.QP_(*qin1), self.QP_(*qin2) input_tuple = q1, q2 if expected == "error": - self.assertRaises(OffsetUnitCalculusError, op.sub, q1, q2) + with pytest.raises(OffsetUnitCalculusError): + op.sub(q1, q2) else: expected = self.QP_(*expected) - self.assertEqual(op.sub(q1, q2).units, expected.units) - self.assertQuantityAlmostEqual(op.sub(q1, q2), expected, atol=0.01) + assert op.sub(q1, q2).units == expected.units + helpers.assert_quantity_almost_equal(op.sub(q1, q2), expected, atol=0.01) multiplications = [ ((("100", "kelvin"), ("10", "kelvin")), ("1000", "kelvin**2")), @@ -801,18 +826,19 @@ class _TestOffsetUnitMath(ParameterizedTestCase): ((("100", "delta_degF"), ("10", "delta_degF")), ("1000", "delta_degF**2")), ] - @ParameterizedTestCase.parameterize(("input", "expected_output"), multiplications) + @pytest.mark.parametrize(("input", "expected_output"), multiplications) def test_multiplication(self, input_tuple, expected): self.ureg.autoconvert_offset_to_baseunit = False qin1, qin2 = input_tuple q1, q2 = self.QP_(*qin1), self.QP_(*qin2) input_tuple = q1, q2 if expected == "error": - self.assertRaises(OffsetUnitCalculusError, op.mul, q1, q2) + with pytest.raises(OffsetUnitCalculusError): + op.mul(q1, q2) else: expected = self.QP_(*expected) - self.assertEqual(op.mul(q1, q2).units, expected.units) - self.assertQuantityAlmostEqual(op.mul(q1, q2), expected, atol=0.01) + assert op.mul(q1, q2).units == expected.units + helpers.assert_quantity_almost_equal(op.mul(q1, q2), expected, atol=0.01) divisions = [ ((("100", "kelvin"), ("10", "kelvin")), ("10", "")), @@ -859,18 +885,21 @@ class _TestOffsetUnitMath(ParameterizedTestCase): ((("100", "delta_degF"), ("10", "delta_degF")), ("10", "")), ] - @ParameterizedTestCase.parameterize(("input", "expected_output"), divisions) + @pytest.mark.parametrize(("input", "expected_output"), divisions) def test_truedivision(self, input_tuple, expected): self.ureg.autoconvert_offset_to_baseunit = False qin1, qin2 = input_tuple q1, q2 = self.QP_(*qin1), self.QP_(*qin2) input_tuple = q1, q2 if expected == "error": - self.assertRaises(OffsetUnitCalculusError, op.truediv, q1, q2) + with pytest.raises(OffsetUnitCalculusError): + op.truediv(q1, q2) else: expected = self.QP_(*expected) - self.assertEqual(op.truediv(q1, q2).units, expected.units) - self.assertQuantityAlmostEqual(op.truediv(q1, q2), expected, atol=0.01) + assert op.truediv(q1, q2).units == expected.units + helpers.assert_quantity_almost_equal( + op.truediv(q1, q2), expected, atol=0.01 + ) multiplications_with_autoconvert_to_baseunit = [ ((("100", "kelvin"), ("10", "degC")), ("28315.0", "kelvin**2")), @@ -895,7 +924,7 @@ class _TestOffsetUnitMath(ParameterizedTestCase): ((("100", "delta_degF"), ("10", "degF")), ("26092.78", "delta_degF*kelvin")), ] - @ParameterizedTestCase.parameterize( + @pytest.mark.parametrize( ("input", "expected_output"), multiplications_with_autoconvert_to_baseunit ) def test_multiplication_with_autoconvert(self, input_tuple, expected): @@ -904,11 +933,12 @@ class _TestOffsetUnitMath(ParameterizedTestCase): q1, q2 = self.QP_(*qin1), self.QP_(*qin2) input_tuple = q1, q2 if expected == "error": - self.assertRaises(OffsetUnitCalculusError, op.mul, q1, q2) + with pytest.raises(OffsetUnitCalculusError): + op.mul(q1, q2) else: expected = self.QP_(*expected) - self.assertEqual(op.mul(q1, q2).units, expected.units) - self.assertQuantityAlmostEqual(op.mul(q1, q2), expected, atol=0.01) + assert op.mul(q1, q2).units == expected.units + helpers.assert_quantity_almost_equal(op.mul(q1, q2), expected, atol=0.01) multiplications_with_scalar = [ ((("10", "kelvin"), "2"), ("20.0", "kelvin")), @@ -920,9 +950,7 @@ class _TestOffsetUnitMath(ParameterizedTestCase): ((("10", "degC**-2"), "2"), "error"), ] - @ParameterizedTestCase.parameterize( - ("input", "expected_output"), multiplications_with_scalar - ) + @pytest.mark.parametrize(("input", "expected_output"), multiplications_with_scalar) def test_multiplication_with_scalar(self, input_tuple, expected): self.ureg.default_as_delta = False in1, in2 = input_tuple @@ -932,11 +960,14 @@ class _TestOffsetUnitMath(ParameterizedTestCase): in1, in2 = in1, self.QP_(*in2) input_tuple = in1, in2 # update input_tuple for better tracebacks if expected == "error": - self.assertRaises(OffsetUnitCalculusError, op.mul, in1, in2) + with pytest.raises(OffsetUnitCalculusError): + op.mul(in1, in2) else: expected = self.QP_(*expected) - self.assertEqual(op.mul(in1, in2).units, expected.units) - self.assertQuantityAlmostEqual(op.mul(in1, in2), expected, atol="0.01") + assert op.mul(in1, in2).units == expected.units + helpers.assert_quantity_almost_equal( + op.mul(in1, in2), expected, atol="0.01" + ) divisions_with_scalar = [ # without / with autoconvert to base unit ((("10", "kelvin"), "2"), [("5.0", "kelvin"), ("5.0", "kelvin")]), @@ -950,9 +981,7 @@ class _TestOffsetUnitMath(ParameterizedTestCase): (("2", ("10", "degC**-2")), ["error", "error"]), ] - @ParameterizedTestCase.parameterize( - ("input", "expected_output"), divisions_with_scalar - ) + @pytest.mark.parametrize(("input", "expected_output"), divisions_with_scalar) def test_division_with_scalar(self, input_tuple, expected): self.ureg.default_as_delta = False in1, in2 = input_tuple @@ -965,11 +994,12 @@ class _TestOffsetUnitMath(ParameterizedTestCase): for i, mode in enumerate([False, True]): self.ureg.autoconvert_offset_to_baseunit = mode if expected_copy[i] == "error": - self.assertRaises(OffsetUnitCalculusError, op.truediv, in1, in2) + with pytest.raises(OffsetUnitCalculusError): + op.truediv(in1, in2) else: expected = self.QP_(*expected_copy[i]) - self.assertEqual(op.truediv(in1, in2).units, expected.units) - self.assertQuantityAlmostEqual(op.truediv(in1, in2), expected) + assert op.truediv(in1, in2).units == expected.units + helpers.assert_quantity_almost_equal(op.truediv(in1, in2), expected) exponentiation = [ # resuls without / with autoconvert ((("10", "degC"), "1"), [("10", "degC"), ("10", "degC")]), @@ -993,7 +1023,7 @@ class _TestOffsetUnitMath(ParameterizedTestCase): # ), ] - @ParameterizedTestCase.parameterize(("input", "expected_output"), exponentiation) + @pytest.mark.parametrize(("input", "expected_output"), exponentiation) def test_exponentiation(self, input_tuple, expected): self.ureg.default_as_delta = False in1, in2 = input_tuple @@ -1008,70 +1038,69 @@ class _TestOffsetUnitMath(ParameterizedTestCase): for i, mode in enumerate([False, True]): self.ureg.autoconvert_offset_to_baseunit = mode if expected_copy[i] == "error": - self.assertRaises( - (OffsetUnitCalculusError, DimensionalityError), op.pow, in1, in2 - ) + with pytest.raises((OffsetUnitCalculusError, DimensionalityError)): + op.pow(in1, in2) else: if type(expected_copy[i]) is tuple: expected = self.QP_(*expected_copy[i]) - self.assertEqual(op.pow(in1, in2).units, expected.units) + assert op.pow(in1, in2).units == expected.units else: expected = expected_copy[i] - self.assertQuantityAlmostEqual(op.pow(in1, in2), expected) + helpers.assert_quantity_almost_equal(op.pow(in1, in2), expected) class NonIntTypeQuantityTestQuantityFloat(_TestBasic, NonIntTypeQuantityTestCase): - NON_INT_TYPE = float + kwargs = dict(non_int_type=float) class NonIntTypeQuantityTestQuantityBasicMathFloat( _TestQuantityBasicMath, NonIntTypeQuantityTestCase ): - NON_INT_TYPE = float + kwargs = dict(non_int_type=float) class NonIntTypeQuantityTestOffsetUnitMathFloat( _TestOffsetUnitMath, NonIntTypeQuantityTestCase ): - NON_INT_TYPE = float + kwargs = dict(non_int_type=float) class NonIntTypeQuantityTestQuantityDecimal(_TestBasic, NonIntTypeQuantityTestCase): - NON_INT_TYPE = Decimal + kwargs = dict(non_int_type=Decimal) class NonIntTypeQuantityTestQuantityBasicMathDecimal( _TestQuantityBasicMath, NonIntTypeQuantityTestCase ): - NON_INT_TYPE = Decimal + kwargs = dict(non_int_type=Decimal) class NonIntTypeQuantityTestOffsetUnitMathDecimal( _TestOffsetUnitMath, NonIntTypeQuantityTestCase ): - NON_INT_TYPE = Decimal + kwargs = dict(non_int_type=Decimal) class NonIntTypeQuantityTestQuantityFraction(_TestBasic, NonIntTypeQuantityTestCase): - NON_INT_TYPE = Fraction + kwargs = dict(non_int_type=Fraction) class NonIntTypeQuantityTestQuantityBasicMathFraction( _TestQuantityBasicMath, NonIntTypeQuantityTestCase ): - NON_INT_TYPE = Fraction + kwargs = dict(non_int_type=Fraction) class NonIntTypeQuantityTestOffsetUnitMathFraction( _TestOffsetUnitMath, NonIntTypeQuantityTestCase ): - NON_INT_TYPE = Fraction + kwargs = dict(non_int_type=Fraction) diff --git a/pint/testsuite/test_numpy.py b/pint/testsuite/test_numpy.py index cb4c016..de59362 100644 --- a/pint/testsuite/test_numpy.py +++ b/pint/testsuite/test_numpy.py @@ -1,27 +1,30 @@ import copy import operator as op import pickle -import unittest import warnings +import pytest + from pint import DimensionalityError, OffsetUnitCalculusError, UnitStrippedWarning from pint.compat import np -from pint.testsuite import QuantityTestCase, helpers +from pint.testsuite import helpers from pint.testsuite.test_umath import TestUFuncs -@helpers.requires_numpy() -class TestNumpyMethods(QuantityTestCase): - - FORCE_NDARRAY = True - +@helpers.requires_numpy +class TestNumpyMethods: @classmethod - def setUpClass(cls): + def setup_class(cls): from pint import _DEFAULT_REGISTRY cls.ureg = _DEFAULT_REGISTRY cls.Q_ = cls.ureg.Quantity + @classmethod + def teardown_class(cls): + cls.ureg = None + cls.Q_ = None + @property def q(self): return [[1, 2], [3, 4]] * self.ureg.m @@ -45,30 +48,30 @@ class TestNumpyMethods(QuantityTestCase): def assertNDArrayEqual(self, actual, desired): # Assert that the given arrays are equal, and are not Quantities np.testing.assert_array_equal(actual, desired) - self.assertFalse(isinstance(actual, self.Q_)) - self.assertFalse(isinstance(desired, self.Q_)) + assert not isinstance(actual, self.Q_) + assert not isinstance(desired, self.Q_) class TestNumpyArrayCreation(TestNumpyMethods): # https://docs.scipy.org/doc/numpy/reference/routines.array-creation.html - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_ones_like(self): self.assertNDArrayEqual(np.ones_like(self.q), np.array([[1, 1], [1, 1]])) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_zeros_like(self): self.assertNDArrayEqual(np.zeros_like(self.q), np.array([[0, 0], [0, 0]])) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_empty_like(self): ret = np.empty_like(self.q) - self.assertEqual(ret.shape, (2, 2)) - self.assertTrue(isinstance(ret, np.ndarray)) + assert ret.shape == (2, 2) + assert isinstance(ret, np.ndarray) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_full_like(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.full_like(self.q, self.Q_(0, self.ureg.degC)), self.Q_([[0, 0], [0, 0]], self.ureg.degC), ) @@ -85,66 +88,72 @@ class TestNumpyArrayManipulation(TestNumpyMethods): # Changing array shape def test_flatten(self): - self.assertQuantityEqual(self.q.flatten(), [1, 2, 3, 4] * self.ureg.m) + helpers.assert_quantity_equal(self.q.flatten(), [1, 2, 3, 4] * self.ureg.m) def test_flat(self): for q, v in zip(self.q.flat, [1, 2, 3, 4]): - self.assertEqual(q, v * self.ureg.m) + assert q == v * self.ureg.m def test_reshape(self): - self.assertQuantityEqual(self.q.reshape([1, 4]), [[1, 2, 3, 4]] * self.ureg.m) + helpers.assert_quantity_equal( + self.q.reshape([1, 4]), [[1, 2, 3, 4]] * self.ureg.m + ) def test_ravel(self): - self.assertQuantityEqual(self.q.ravel(), [1, 2, 3, 4] * self.ureg.m) + helpers.assert_quantity_equal(self.q.ravel(), [1, 2, 3, 4] * self.ureg.m) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_ravel_numpy_func(self): - self.assertQuantityEqual(np.ravel(self.q), [1, 2, 3, 4] * self.ureg.m) + helpers.assert_quantity_equal(np.ravel(self.q), [1, 2, 3, 4] * self.ureg.m) # Transpose-like operations - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_moveaxis(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.moveaxis(self.q, 1, 0), np.array([[1, 2], [3, 4]]).T * self.ureg.m ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_rollaxis(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.rollaxis(self.q, 1), np.array([[1, 2], [3, 4]]).T * self.ureg.m ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_swapaxes(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.swapaxes(self.q, 1, 0), np.array([[1, 2], [3, 4]]).T * self.ureg.m ) def test_transpose(self): - self.assertQuantityEqual(self.q.transpose(), [[1, 3], [2, 4]] * self.ureg.m) + helpers.assert_quantity_equal( + self.q.transpose(), [[1, 3], [2, 4]] * self.ureg.m + ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_transpose_numpy_func(self): - self.assertQuantityEqual(np.transpose(self.q), [[1, 3], [2, 4]] * self.ureg.m) + helpers.assert_quantity_equal( + np.transpose(self.q), [[1, 3], [2, 4]] * self.ureg.m + ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_flip_numpy_func(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.flip(self.q, axis=0), [[3, 4], [1, 2]] * self.ureg.m ) # Changing number of dimensions - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_atleast_1d(self): actual = np.atleast_1d(self.Q_(0, self.ureg.degC), self.q.flatten()) expected = (self.Q_(np.array([0]), self.ureg.degC), self.q.flatten()) for ind_actual, ind_expected in zip(actual, expected): - self.assertQuantityEqual(ind_actual, ind_expected) - self.assertQuantityEqual(np.atleast_1d(self.q), self.q) + helpers.assert_quantity_equal(ind_actual, ind_expected) + helpers.assert_quantity_equal(np.atleast_1d(self.q), self.q) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_atleast_2d(self): actual = np.atleast_2d(self.Q_(0, self.ureg.degC), self.q.flatten()) expected = ( @@ -152,10 +161,10 @@ class TestNumpyArrayManipulation(TestNumpyMethods): np.array([[1, 2, 3, 4]]) * self.ureg.m, ) for ind_actual, ind_expected in zip(actual, expected): - self.assertQuantityEqual(ind_actual, ind_expected) - self.assertQuantityEqual(np.atleast_2d(self.q), self.q) + helpers.assert_quantity_equal(ind_actual, ind_expected) + helpers.assert_quantity_equal(np.atleast_2d(self.q), self.q) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_atleast_3d(self): actual = np.atleast_3d(self.Q_(0, self.ureg.degC), self.q.flatten()) expected = ( @@ -163,42 +172,42 @@ class TestNumpyArrayManipulation(TestNumpyMethods): np.array([[[1], [2], [3], [4]]]) * self.ureg.m, ) for ind_actual, ind_expected in zip(actual, expected): - self.assertQuantityEqual(ind_actual, ind_expected) - self.assertQuantityEqual( + helpers.assert_quantity_equal(ind_actual, ind_expected) + helpers.assert_quantity_equal( np.atleast_3d(self.q), np.array([[[1], [2]], [[3], [4]]]) * self.ureg.m ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_broadcast_to(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.broadcast_to(self.q[:, 1], (2, 2)), np.array([[2, 4], [2, 4]]) * self.ureg.m, ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_expand_dims(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.expand_dims(self.q, 0), np.array([[[1, 2], [3, 4]]]) * self.ureg.m ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_squeeze(self): - self.assertQuantityEqual(np.squeeze(self.q), self.q) - self.assertQuantityEqual( + helpers.assert_quantity_equal(np.squeeze(self.q), self.q) + helpers.assert_quantity_equal( self.q.reshape([1, 4]).squeeze(), [1, 2, 3, 4] * self.ureg.m ) # Changing number of dimensions # Joining arrays - @helpers.requires_array_function_protocol() - def test_concat_stack(self): + @helpers.requires_array_function_protocol + def test_concat_stack(self, subtests): for func in (np.concatenate, np.stack, np.hstack, np.vstack, np.dstack): - with self.subTest(func=func): - self.assertQuantityEqual( + with subtests.test(func=func): + helpers.assert_quantity_equal( func([self.q] * 2), self.Q_(func([self.q.m] * 2), self.ureg.m) ) # One or more of the args is a bare array full of zeros or NaNs - self.assertQuantityEqual( + helpers.assert_quantity_equal( func([self.q_zero_or_nan.m, self.q]), self.Q_(func([self.q_zero_or_nan.m, self.q.m]), self.ureg.m), ) @@ -206,21 +215,21 @@ class TestNumpyArrayManipulation(TestNumpyMethods): # non-NaN element nz = self.q_zero_or_nan nz.m[0, 0] = 1 - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): func([nz.m, self.q]) - @helpers.requires_array_function_protocol() - def test_block_column_stack(self): + @helpers.requires_array_function_protocol + def test_block_column_stack(self, subtests): for func in (np.block, np.column_stack): - with self.subTest(func=func): + with subtests.test(func=func): - self.assertQuantityEqual( + helpers.assert_quantity_equal( func([self.q[:, 0], self.q[:, 1]]), self.Q_(func([self.q[:, 0].m, self.q[:, 1].m]), self.ureg.m), ) # One or more of the args is a bare array full of zeros or NaNs - self.assertQuantityEqual( + helpers.assert_quantity_equal( func( [ self.q_zero_or_nan[:, 0].m, @@ -243,12 +252,12 @@ class TestNumpyArrayManipulation(TestNumpyMethods): # non-NaN element nz = self.q_zero_or_nan nz.m[0, 0] = 1 - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): func([nz[:, 0].m, self.q[:, 0]]) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_append(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.append(self.q, [[0, 0]] * self.ureg.m, axis=0), [[1, 2], [3, 4], [0, 0]] * self.ureg.m, ) @@ -256,175 +265,191 @@ class TestNumpyArrayManipulation(TestNumpyMethods): def test_astype(self): actual = self.q.astype(np.float32) expected = self.Q_(np.array([[1.0, 2.0], [3.0, 4.0]], dtype=np.float32), "m") - self.assertQuantityEqual(actual, expected) - self.assertEqual(actual.m.dtype, expected.m.dtype) + helpers.assert_quantity_equal(actual, expected) + assert actual.m.dtype == expected.m.dtype def test_item(self): - self.assertQuantityEqual(self.Q_([[0]], "m").item(), 0 * self.ureg.m) + helpers.assert_quantity_equal(self.Q_([[0]], "m").item(), 0 * self.ureg.m) class TestNumpyMathematicalFunctions(TestNumpyMethods): # https://www.numpy.org/devdocs/reference/routines.math.html # Trigonometric functions - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_unwrap(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.unwrap([0, 3 * np.pi] * self.ureg.radians), [0, np.pi] ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.unwrap([0, 540] * self.ureg.deg), [0, 180] * self.ureg.deg ) # Rounding - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_fix(self): - 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( + helpers.assert_quantity_equal(np.fix(3.14 * self.ureg.m), 3.0 * self.ureg.m) + helpers.assert_quantity_equal(np.fix(3.0 * self.ureg.m), 3.0 * self.ureg.m) + helpers.assert_quantity_equal( np.fix([2.1, 2.9, -2.1, -2.9] * self.ureg.m), [2.0, 2.0, -2.0, -2.0] * self.ureg.m, ) # Sums, products, differences - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_prod(self): axis = 0 where = [[True, False], [True, True]] - self.assertQuantityEqual(self.q.prod(), 24 * self.ureg.m ** 4) - self.assertQuantityEqual(self.q.prod(axis=axis), [3, 8] * self.ureg.m ** 2) - self.assertQuantityEqual(self.q.prod(where=where), 12 * self.ureg.m ** 3) + helpers.assert_quantity_equal(self.q.prod(), 24 * self.ureg.m ** 4) + helpers.assert_quantity_equal(self.q.prod(axis=axis), [3, 8] * self.ureg.m ** 2) + helpers.assert_quantity_equal(self.q.prod(where=where), 12 * self.ureg.m ** 3) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_prod_numpy_func(self): axis = 0 where = [[True, False], [True, True]] - self.assertQuantityEqual(np.prod(self.q), 24 * self.ureg.m ** 4) - self.assertQuantityEqual(np.prod(self.q, axis=axis), [3, 8] * self.ureg.m ** 2) - self.assertQuantityEqual(np.prod(self.q, where=where), 12 * self.ureg.m ** 3) + helpers.assert_quantity_equal(np.prod(self.q), 24 * self.ureg.m ** 4) + helpers.assert_quantity_equal( + np.prod(self.q, axis=axis), [3, 8] * self.ureg.m ** 2 + ) + helpers.assert_quantity_equal( + np.prod(self.q, where=where), 12 * self.ureg.m ** 3 + ) - self.assertRaises(DimensionalityError, np.prod, self.q, axis=axis, where=where) - self.assertQuantityEqual( + with pytest.raises(DimensionalityError): + np.prod(self.q, axis=axis, where=where) + helpers.assert_quantity_equal( np.prod(self.q, axis=axis, where=[[True, False], [False, True]]), [1, 4] * self.ureg.m, ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.prod(self.q, axis=axis, where=[True, False]), [3, 1] * self.ureg.m ** 2 ) def test_sum(self): - self.assertEqual(self.q.sum(), 10 * self.ureg.m) - self.assertQuantityEqual(self.q.sum(0), [4, 6] * self.ureg.m) - self.assertQuantityEqual(self.q.sum(1), [3, 7] * self.ureg.m) + assert self.q.sum() == 10 * self.ureg.m + helpers.assert_quantity_equal(self.q.sum(0), [4, 6] * self.ureg.m) + helpers.assert_quantity_equal(self.q.sum(1), [3, 7] * self.ureg.m) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_sum_numpy_func(self): - self.assertQuantityEqual(np.sum(self.q, axis=0), [4, 6] * self.ureg.m) - self.assertRaises(OffsetUnitCalculusError, np.sum, self.q_temperature) + helpers.assert_quantity_equal(np.sum(self.q, axis=0), [4, 6] * self.ureg.m) + with pytest.raises(OffsetUnitCalculusError): + np.sum(self.q_temperature) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_nansum_numpy_func(self): - self.assertQuantityEqual(np.nansum(self.q_nan, axis=0), [4, 2] * self.ureg.m) + helpers.assert_quantity_equal( + np.nansum(self.q_nan, axis=0), [4, 2] * self.ureg.m + ) def test_cumprod(self): - self.assertRaises(DimensionalityError, self.q.cumprod) - self.assertQuantityEqual((self.q / self.ureg.m).cumprod(), [1, 2, 6, 24]) + with pytest.raises(DimensionalityError): + self.q.cumprod() + helpers.assert_quantity_equal((self.q / self.ureg.m).cumprod(), [1, 2, 6, 24]) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_cumprod_numpy_func(self): - self.assertRaises(DimensionalityError, np.cumprod, self.q) - self.assertRaises(DimensionalityError, np.cumproduct, self.q) - self.assertQuantityEqual(np.cumprod(self.q / self.ureg.m), [1, 2, 6, 24]) - self.assertQuantityEqual(np.cumproduct(self.q / self.ureg.m), [1, 2, 6, 24]) - self.assertQuantityEqual( + with pytest.raises(DimensionalityError): + np.cumprod(self.q) + with pytest.raises(DimensionalityError): + np.cumproduct(self.q) + helpers.assert_quantity_equal(np.cumprod(self.q / self.ureg.m), [1, 2, 6, 24]) + helpers.assert_quantity_equal( + np.cumproduct(self.q / self.ureg.m), [1, 2, 6, 24] + ) + helpers.assert_quantity_equal( np.cumprod(self.q / self.ureg.m, axis=1), [[1, 2], [3, 12]] ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_nancumprod_numpy_func(self): - self.assertRaises(DimensionalityError, np.nancumprod, self.q_nan) - self.assertQuantityEqual(np.nancumprod(self.q_nan / self.ureg.m), [1, 2, 6, 6]) + with pytest.raises(DimensionalityError): + np.nancumprod(self.q_nan) + helpers.assert_quantity_equal( + np.nancumprod(self.q_nan / self.ureg.m), [1, 2, 6, 6] + ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_diff(self): - self.assertQuantityEqual(np.diff(self.q, 1), [[1], [1]] * self.ureg.m) - self.assertQuantityEqual( + helpers.assert_quantity_equal(np.diff(self.q, 1), [[1], [1]] * self.ureg.m) + helpers.assert_quantity_equal( np.diff(self.q_temperature, 1), [[1], [1]] * self.ureg.delta_degC ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_ediff1d(self): - self.assertQuantityEqual(np.ediff1d(self.q), [1, 1, 1] * self.ureg.m) - self.assertQuantityEqual( + helpers.assert_quantity_equal(np.ediff1d(self.q), [1, 1, 1] * self.ureg.m) + helpers.assert_quantity_equal( np.ediff1d(self.q_temperature), [1, 1, 1] * self.ureg.delta_degC ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_gradient(self): grad = np.gradient([[1, 1], [3, 4]] * self.ureg.m, 1 * self.ureg.J) - self.assertQuantityEqual( + helpers.assert_quantity_equal( grad[0], [[2.0, 3.0], [2.0, 3.0]] * self.ureg.m / self.ureg.J ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( grad[1], [[0.0, 0.0], [1.0, 1.0]] * self.ureg.m / self.ureg.J ) grad = np.gradient(self.Q_([[1, 1], [3, 4]], self.ureg.degC), 1 * self.ureg.J) - self.assertQuantityEqual( + helpers.assert_quantity_equal( grad[0], [[2.0, 3.0], [2.0, 3.0]] * self.ureg.delta_degC / self.ureg.J ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( grad[1], [[0.0, 0.0], [1.0, 1.0]] * self.ureg.delta_degC / self.ureg.J ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_cross(self): a = [[3, -3, 1]] * self.ureg.kPa b = [[4, 9, 2]] * self.ureg.m ** 2 - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.cross(a, b), [[-15, -2, 39]] * self.ureg.kPa * self.ureg.m ** 2 ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_trapz(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.trapz([1.0, 2.0, 3.0, 4.0] * self.ureg.J, dx=1 * self.ureg.m), 7.5 * self.ureg.J * self.ureg.m, ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_dot(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( self.q.ravel().dot(np.array([1, 0, 0, 1])), 5 * self.ureg.m ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_dot_numpy_func(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.dot(self.q.ravel(), [0, 0, 1, 0] * self.ureg.dimensionless), 3 * self.ureg.m, ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_einsum(self): a = np.arange(25).reshape(5, 5) * self.ureg.m b = np.arange(5) * self.ureg.m - self.assertQuantityEqual(np.einsum("ii", a), 60 * self.ureg.m) - self.assertQuantityEqual( + helpers.assert_quantity_equal(np.einsum("ii", a), 60 * self.ureg.m) + helpers.assert_quantity_equal( np.einsum("ii->i", a), np.array([0, 6, 12, 18, 24]) * self.ureg.m ) - self.assertQuantityEqual(np.einsum("i,i", b, b), 30 * self.ureg.m ** 2) - self.assertQuantityEqual( + helpers.assert_quantity_equal(np.einsum("i,i", b, b), 30 * self.ureg.m ** 2) + helpers.assert_quantity_equal( np.einsum("ij,j", a, b), np.array([30, 80, 130, 180, 230]) * self.ureg.m ** 2, ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_solve(self): - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( np.linalg.solve(self.q, [[3], [7]] * self.ureg.s), self.Q_([[1], [1]], "m / s"), ) @@ -433,18 +458,20 @@ class TestNumpyMathematicalFunctions(TestNumpyMethods): def test_addition_with_scalar(self): a = np.array([0, 1, 2]) b = 10.0 * self.ureg("gram/kilogram") - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( a + b, self.Q_([0.01, 1.01, 2.01], self.ureg.dimensionless) ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( b + a, self.Q_([0.01, 1.01, 2.01], self.ureg.dimensionless) ) def test_addition_with_incompatible_scalar(self): a = np.array([0, 1, 2]) b = 1.0 * self.ureg.m - self.assertRaises(DimensionalityError, op.add, a, b) - self.assertRaises(DimensionalityError, op.add, b, a) + with pytest.raises(DimensionalityError): + op.add(a, b) + with pytest.raises(DimensionalityError): + op.add(b, a) def test_power(self): arr = np.array(range(3), dtype=np.float) @@ -452,33 +479,36 @@ class TestNumpyMathematicalFunctions(TestNumpyMethods): for op_ in [op.pow, op.ipow, np.power]: q_cp = copy.copy(q) - self.assertRaises(DimensionalityError, op_, 2.0, q_cp) + with pytest.raises(DimensionalityError): + op_(2.0, q_cp) arr_cp = copy.copy(arr) arr_cp = copy.copy(arr) q_cp = copy.copy(q) - self.assertRaises(DimensionalityError, op_, q_cp, arr_cp) + with pytest.raises(DimensionalityError): + op_(q_cp, arr_cp) q_cp = copy.copy(q) q2_cp = copy.copy(q) - self.assertRaises(DimensionalityError, op_, q_cp, q2_cp) + with pytest.raises(DimensionalityError): + op_(q_cp, q2_cp) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.power(self.q, self.Q_(2)), self.Q_([[1, 4], [9, 16]], "m**2") ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( self.q ** self.Q_(2), self.Q_([[1, 4], [9, 16]], "m**2") ) self.assertNDArrayEqual(arr ** self.Q_(2), np.array([0, 1, 4])) def test_sqrt(self): q = self.Q_(100, "m**2") - self.assertQuantityEqual(np.sqrt(q), self.Q_(10, "m")) + helpers.assert_quantity_equal(np.sqrt(q), self.Q_(10, "m")) def test_cbrt(self): q = self.Q_(1000, "m**3") - self.assertQuantityEqual(np.cbrt(q), self.Q_(10, "m")) + helpers.assert_quantity_equal(np.cbrt(q), self.Q_(10, "m")) - @unittest.expectedFailure - @helpers.requires_numpy() + @pytest.mark.xfail + @helpers.requires_numpy def test_exponentiation_array_exp_2(self): arr = np.array(range(3), dtype=np.float) # q = self.Q_(copy.copy(arr), None) @@ -486,100 +516,101 @@ class TestNumpyMathematicalFunctions(TestNumpyMethods): arr_cp = copy.copy(arr) q_cp = copy.copy(q) # this fails as expected since numpy 1.8.0 but... - self.assertRaises(DimensionalityError, op.pow, arr_cp, q_cp) + with pytest.raises(DimensionalityError): + op.pow(arr_cp, q_cp) # ..not for op.ipow ! # q_cp is treated as if it is an array. The units are ignored. # Quantity.__ipow__ is never called arr_cp = copy.copy(arr) q_cp = copy.copy(q) - self.assertRaises(DimensionalityError, op.ipow, arr_cp, q_cp) + with pytest.raises(DimensionalityError): + op.ipow(arr_cp, q_cp) class TestNumpyUnclassified(TestNumpyMethods): def test_tolist(self): - self.assertEqual( - self.q.tolist(), - [[1 * self.ureg.m, 2 * self.ureg.m], [3 * self.ureg.m, 4 * self.ureg.m]], - ) - self.assertEqual(self.q_scalar.tolist(), 5 * self.ureg.m) - - with self.assertRaises(AttributeError): + with pytest.raises(AttributeError): (5 * self.ureg.m).tolist() + assert self.q.tolist() == [ + [1 * self.ureg.m, 2 * self.ureg.m], + [3 * self.ureg.m, 4 * self.ureg.m], + ] + def test_fill(self): tmp = self.q tmp.fill(6 * self.ureg.ft) - self.assertQuantityEqual(tmp, [[6, 6], [6, 6]] * self.ureg.ft) + helpers.assert_quantity_equal(tmp, [[6, 6], [6, 6]] * self.ureg.ft) tmp.fill(5 * self.ureg.m) - self.assertQuantityEqual(tmp, [[5, 5], [5, 5]] * self.ureg.m) + helpers.assert_quantity_equal(tmp, [[5, 5], [5, 5]] * self.ureg.m) def test_take(self): - self.assertQuantityEqual(self.q.take([0, 1, 2, 3]), self.q.flatten()) + helpers.assert_quantity_equal(self.q.take([0, 1, 2, 3]), self.q.flatten()) def test_put(self): q = [1.0, 2.0, 3.0, 4.0] * self.ureg.m q.put([0, 2], [10.0, 20.0] * self.ureg.m) - self.assertQuantityEqual(q, [10.0, 2.0, 20.0, 4.0] * self.ureg.m) + helpers.assert_quantity_equal(q, [10.0, 2.0, 20.0, 4.0] * self.ureg.m) q = [1.0, 2.0, 3.0, 4.0] * self.ureg.m q.put([0, 2], [1.0, 2.0] * self.ureg.mm) - self.assertQuantityEqual(q, [0.001, 2.0, 0.002, 4.0] * self.ureg.m) + helpers.assert_quantity_equal(q, [0.001, 2.0, 0.002, 4.0] * self.ureg.m) q = [1.0, 2.0, 3.0, 4.0] * self.ureg.m / self.ureg.mm q.put([0, 2], [1.0, 2.0]) - self.assertQuantityEqual( + helpers.assert_quantity_equal( q, [0.001, 2.0, 0.002, 4.0] * self.ureg.m / self.ureg.mm ) q = [1.0, 2.0, 3.0, 4.0] * self.ureg.m - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): q.put([0, 2], [4.0, 6.0] * self.ureg.J) - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): q.put([0, 2], [4.0, 6.0]) def test_repeat(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( self.q.repeat(2), [1, 1, 2, 2, 3, 3, 4, 4] * self.ureg.m ) def test_sort(self): q = [4, 5, 2, 3, 1, 6] * self.ureg.m q.sort() - self.assertQuantityEqual(q, [1, 2, 3, 4, 5, 6] * self.ureg.m) + helpers.assert_quantity_equal(q, [1, 2, 3, 4, 5, 6] * self.ureg.m) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_sort_numpy_func(self): q = [4, 5, 2, 3, 1, 6] * self.ureg.m - self.assertQuantityEqual(np.sort(q), [1, 2, 3, 4, 5, 6] * self.ureg.m) + helpers.assert_quantity_equal(np.sort(q), [1, 2, 3, 4, 5, 6] * self.ureg.m) def test_argsort(self): q = [1, 4, 5, 6, 2, 9] * self.ureg.MeV self.assertNDArrayEqual(q.argsort(), [0, 4, 1, 2, 3, 5]) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_argsort_numpy_func(self): self.assertNDArrayEqual(np.argsort(self.q, axis=0), np.array([[0, 0], [1, 1]])) def test_diagonal(self): q = [[1, 2, 3], [1, 2, 3], [1, 2, 3]] * self.ureg.m - self.assertQuantityEqual(q.diagonal(offset=1), [2, 3] * self.ureg.m) + helpers.assert_quantity_equal(q.diagonal(offset=1), [2, 3] * self.ureg.m) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_diagonal_numpy_func(self): q = [[1, 2, 3], [1, 2, 3], [1, 2, 3]] * self.ureg.m - self.assertQuantityEqual(np.diagonal(q, offset=-1), [1, 2] * self.ureg.m) + helpers.assert_quantity_equal(np.diagonal(q, offset=-1), [1, 2] * self.ureg.m) def test_compress(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( self.q.compress([False, True], axis=0), [[3, 4]] * self.ureg.m ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( self.q.compress([False, True], axis=1), [[2], [4]] * self.ureg.m ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_compress_nep18(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.compress([False, True], self.q, axis=1), [[2], [4]] * self.ureg.m ) @@ -587,9 +618,10 @@ class TestNumpyUnclassified(TestNumpyMethods): q = self.q.flatten() self.assertNDArrayEqual(q.searchsorted([1.5, 2.5] * self.ureg.m), [1, 2]) q = self.q.flatten() - self.assertRaises(DimensionalityError, q.searchsorted, [1.5, 2.5]) + with pytest.raises(DimensionalityError): + q.searchsorted([1.5, 2.5]) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_searchsorted_numpy_func(self): """Test searchsorted as numpy function.""" q = self.q.flatten() @@ -599,265 +631,278 @@ class TestNumpyUnclassified(TestNumpyMethods): q = [1, 0, 5, 6, 0, 9] * self.ureg.m self.assertNDArrayEqual(q.nonzero()[0], [0, 2, 3, 5]) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_nonzero_numpy_func(self): q = [1, 0, 5, 6, 0, 9] * self.ureg.m self.assertNDArrayEqual(np.nonzero(q)[0], [0, 2, 3, 5]) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_any_numpy_func(self): q = [0, 1] * self.ureg.m - self.assertTrue(np.any(q)) - self.assertRaises(ValueError, np.any, self.q_temperature) + assert np.any(q) + with pytest.raises(ValueError): + np.any(self.q_temperature) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_all_numpy_func(self): q = [0, 1] * self.ureg.m - self.assertFalse(np.all(q)) - self.assertRaises(ValueError, np.all, self.q_temperature) + assert not np.all(q) + with pytest.raises(ValueError): + np.all(self.q_temperature) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_count_nonzero_numpy_func(self): q = [1, 0, 5, 6, 0, 9] * self.ureg.m - self.assertEqual(np.count_nonzero(q), 4) + assert np.count_nonzero(q) == 4 def test_max(self): - self.assertEqual(self.q.max(), 4 * self.ureg.m) + assert self.q.max() == 4 * self.ureg.m def test_max_numpy_func(self): - self.assertEqual(np.max(self.q), 4 * self.ureg.m) + assert np.max(self.q) == 4 * self.ureg.m - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_max_with_axis_arg(self): - self.assertQuantityEqual(np.max(self.q, axis=1), [2, 4] * self.ureg.m) + helpers.assert_quantity_equal(np.max(self.q, axis=1), [2, 4] * self.ureg.m) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_max_with_initial_arg(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.max(self.q[..., None], axis=2, initial=3 * self.ureg.m), [[3, 3], [3, 4]] * self.ureg.m, ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_nanmax(self): - self.assertEqual(np.nanmax(self.q_nan), 3 * self.ureg.m) + assert np.nanmax(self.q_nan) == 3 * self.ureg.m def test_argmax(self): - self.assertEqual(self.q.argmax(), 3) + assert self.q.argmax() == 3 - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_argmax_numpy_func(self): self.assertNDArrayEqual(np.argmax(self.q, axis=0), np.array([1, 1])) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_nanargmax_numpy_func(self): self.assertNDArrayEqual(np.nanargmax(self.q_nan, axis=0), np.array([1, 0])) def test_maximum(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.maximum(self.q, self.Q_([0, 5], "m")), self.Q_([[1, 5], [3, 5]], "m") ) def test_min(self): - self.assertEqual(self.q.min(), 1 * self.ureg.m) + assert self.q.min() == 1 * self.ureg.m - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_min_numpy_func(self): - self.assertEqual(np.min(self.q), 1 * self.ureg.m) + assert np.min(self.q) == 1 * self.ureg.m - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_min_with_axis_arg(self): - self.assertQuantityEqual(np.min(self.q, axis=1), [1, 3] * self.ureg.m) + helpers.assert_quantity_equal(np.min(self.q, axis=1), [1, 3] * self.ureg.m) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_min_with_initial_arg(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.min(self.q[..., None], axis=2, initial=3 * self.ureg.m), [[1, 2], [3, 3]] * self.ureg.m, ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_nanmin(self): - self.assertEqual(np.nanmin(self.q_nan), 1 * self.ureg.m) + assert np.nanmin(self.q_nan) == 1 * self.ureg.m def test_argmin(self): - self.assertEqual(self.q.argmin(), 0) + assert self.q.argmin() == 0 - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_argmin_numpy_func(self): self.assertNDArrayEqual(np.argmin(self.q, axis=0), np.array([0, 0])) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_nanargmin_numpy_func(self): self.assertNDArrayEqual(np.nanargmin(self.q_nan, axis=0), np.array([0, 0])) def test_minimum(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.minimum(self.q, self.Q_([0, 5], "m")), self.Q_([[0, 2], [0, 4]], "m") ) def test_ptp(self): - self.assertEqual(self.q.ptp(), 3 * self.ureg.m) + assert self.q.ptp() == 3 * self.ureg.m - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_ptp_numpy_func(self): - self.assertQuantityEqual(np.ptp(self.q, axis=0), [2, 2] * self.ureg.m) + helpers.assert_quantity_equal(np.ptp(self.q, axis=0), [2, 2] * self.ureg.m) def test_clip(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( self.q.clip(max=2 * self.ureg.m), [[1, 2], [2, 2]] * self.ureg.m ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( self.q.clip(min=3 * self.ureg.m), [[3, 3], [3, 4]] * self.ureg.m ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( self.q.clip(min=2 * self.ureg.m, max=3 * self.ureg.m), [[2, 2], [3, 3]] * self.ureg.m, ) - self.assertRaises(DimensionalityError, self.q.clip, self.ureg.J) - self.assertRaises(DimensionalityError, self.q.clip, 1) + with pytest.raises(DimensionalityError): + self.q.clip(self.ureg.J) + with pytest.raises(DimensionalityError): + self.q.clip(1) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_clip_numpy_func(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.clip(self.q, 150 * self.ureg.cm, None), [[1.5, 2], [3, 4]] * self.ureg.m ) def test_round(self): q = [1, 1.33, 5.67, 22] * self.ureg.m - self.assertQuantityEqual(q.round(0), [1, 1, 6, 22] * self.ureg.m) - self.assertQuantityEqual(q.round(-1), [0, 0, 10, 20] * self.ureg.m) - self.assertQuantityEqual(q.round(1), [1, 1.3, 5.7, 22] * self.ureg.m) + helpers.assert_quantity_equal(q.round(0), [1, 1, 6, 22] * self.ureg.m) + helpers.assert_quantity_equal(q.round(-1), [0, 0, 10, 20] * self.ureg.m) + helpers.assert_quantity_equal(q.round(1), [1, 1.3, 5.7, 22] * self.ureg.m) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_round_numpy_func(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.around(1.0275 * self.ureg.m, decimals=2), 1.03 * self.ureg.m ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.round_(1.0275 * self.ureg.m, decimals=2), 1.03 * self.ureg.m ) def test_trace(self): - self.assertEqual(self.q.trace(), (1 + 4) * self.ureg.m) + assert self.q.trace() == (1 + 4) * self.ureg.m def test_cumsum(self): - self.assertQuantityEqual(self.q.cumsum(), [1, 3, 6, 10] * self.ureg.m) + helpers.assert_quantity_equal(self.q.cumsum(), [1, 3, 6, 10] * self.ureg.m) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_cumsum_numpy_func(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.cumsum(self.q, axis=0), [[1, 2], [4, 6]] * self.ureg.m ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_nancumsum_numpy_func(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.nancumsum(self.q_nan, axis=0), [[1, 2], [4, 2]] * self.ureg.m ) def test_mean(self): - self.assertEqual(self.q.mean(), 2.5 * self.ureg.m) + assert self.q.mean() == 2.5 * self.ureg.m - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_mean_numpy_func(self): - self.assertEqual(np.mean(self.q), 2.5 * self.ureg.m) - self.assertEqual(np.mean(self.q_temperature), self.Q_(2.5, self.ureg.degC)) + assert np.mean(self.q) == 2.5 * self.ureg.m + assert np.mean(self.q_temperature) == self.Q_(2.5, self.ureg.degC) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_nanmean_numpy_func(self): - self.assertEqual(np.nanmean(self.q_nan), 2 * self.ureg.m) + assert np.nanmean(self.q_nan) == 2 * self.ureg.m - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_average_numpy_func(self): - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( np.average(self.q, axis=0, weights=[1, 2]), [2.33333, 3.33333] * self.ureg.m, rtol=1e-5, ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_median_numpy_func(self): - self.assertEqual(np.median(self.q), 2.5 * self.ureg.m) + assert np.median(self.q) == 2.5 * self.ureg.m - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_nanmedian_numpy_func(self): - self.assertEqual(np.nanmedian(self.q_nan), 2 * self.ureg.m) + assert np.nanmedian(self.q_nan) == 2 * self.ureg.m def test_var(self): - self.assertEqual(self.q.var(), 1.25 * self.ureg.m ** 2) + assert self.q.var() == 1.25 * self.ureg.m ** 2 - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_var_numpy_func(self): - self.assertEqual(np.var(self.q), 1.25 * self.ureg.m ** 2) + assert np.var(self.q) == 1.25 * self.ureg.m ** 2 - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_nanvar_numpy_func(self): - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( np.nanvar(self.q_nan), 0.66667 * self.ureg.m ** 2, rtol=1e-5 ) def test_std(self): - self.assertQuantityAlmostEqual(self.q.std(), 1.11803 * self.ureg.m, rtol=1e-5) + helpers.assert_quantity_almost_equal( + self.q.std(), 1.11803 * self.ureg.m, rtol=1e-5 + ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_std_numpy_func(self): - self.assertQuantityAlmostEqual(np.std(self.q), 1.11803 * self.ureg.m, rtol=1e-5) - self.assertRaises(OffsetUnitCalculusError, np.std, self.q_temperature) + helpers.assert_quantity_almost_equal( + np.std(self.q), 1.11803 * self.ureg.m, rtol=1e-5 + ) + with pytest.raises(OffsetUnitCalculusError): + np.std(self.q_temperature) def test_cumprod(self): - self.assertRaises(DimensionalityError, self.q.cumprod) - self.assertQuantityEqual((self.q / self.ureg.m).cumprod(), [1, 2, 6, 24]) + with pytest.raises(DimensionalityError): + self.q.cumprod() + helpers.assert_quantity_equal((self.q / self.ureg.m).cumprod(), [1, 2, 6, 24]) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_nanstd_numpy_func(self): - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( np.nanstd(self.q_nan), 0.81650 * self.ureg.m, rtol=1e-5 ) def test_conj(self): - self.assertQuantityEqual((self.q * (1 + 1j)).conj(), self.q * (1 - 1j)) - self.assertQuantityEqual((self.q * (1 + 1j)).conjugate(), self.q * (1 - 1j)) + helpers.assert_quantity_equal((self.q * (1 + 1j)).conj(), self.q * (1 - 1j)) + helpers.assert_quantity_equal( + (self.q * (1 + 1j)).conjugate(), self.q * (1 - 1j) + ) def test_getitem(self): - self.assertRaises(IndexError, self.q.__getitem__, (0, 10)) - self.assertQuantityEqual(self.q[0], [1, 2] * self.ureg.m) - self.assertEqual(self.q[1, 1], 4 * self.ureg.m) + with pytest.raises(IndexError): + self.q.__getitem__((0, 10)) + helpers.assert_quantity_equal(self.q[0], [1, 2] * self.ureg.m) + assert self.q[1, 1] == 4 * self.ureg.m def test_setitem(self): - with self.assertRaises(TypeError): + with pytest.raises(TypeError): self.q[0, 0] = 1 - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): self.q[0, 0] = 1 * self.ureg.J - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): self.q[0] = 1 - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): self.q[0] = np.ndarray([1, 2]) - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): self.q[0] = 1 * self.ureg.J q = self.q.copy() q[0] = 1 * self.ureg.m - self.assertQuantityEqual(q, [[1, 1], [3, 4]] * self.ureg.m) + helpers.assert_quantity_equal(q, [[1, 1], [3, 4]] * self.ureg.m) q = self.q.copy() q[...] = 1 * self.ureg.m - self.assertQuantityEqual(q, [[1, 1], [1, 1]] * self.ureg.m) + helpers.assert_quantity_equal(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) + helpers.assert_quantity_equal(q, [[1, 1], [1, 1]] * self.ureg.m) # check and see that dimensionless num bers work correctly q = [0, 1, 2, 3] * self.ureg.dimensionless q[0] = 1 - self.assertQuantityEqual(q, np.asarray([1, 1, 2, 3])) + helpers.assert_quantity_equal(q, np.asarray([1, 1, 2, 3])) q[0] = self.ureg.m / self.ureg.mm - self.assertQuantityEqual(q, np.asarray([1000, 1, 2, 3])) + helpers.assert_quantity_equal(q, np.asarray([1000, 1, 2, 3])) q = [0.0, 1.0, 2.0, 3.0] * self.ureg.m / self.ureg.mm q[0] = 1.0 - self.assertQuantityEqual(q, [0.001, 1, 2, 3] * self.ureg.m / self.ureg.mm) + helpers.assert_quantity_equal(q, [0.001, 1, 2, 3] * self.ureg.m / self.ureg.mm) # Check that this properly masks the first item without warning q = self.ureg.Quantity( @@ -871,28 +916,28 @@ class TestNumpyUnclassified(TestNumpyMethods): def test_iterator(self): for q, v in zip(self.q.flatten(), [1, 2, 3, 4]): - self.assertEqual(q, v * self.ureg.m) + assert q == v * self.ureg.m def test_iterable(self): - self.assertTrue(np.iterable(self.q)) - self.assertFalse(np.iterable(1 * self.ureg.m)) + assert np.iterable(self.q) + assert not np.iterable(1 * self.ureg.m) def test_reversible_op(self): """ """ x = self.q.magnitude u = self.Q_(np.ones(x.shape)) - self.assertQuantityEqual(x / self.q, u * x / self.q) - self.assertQuantityEqual(x * self.q, u * x * self.q) - self.assertQuantityEqual(x + u, u + x) - self.assertQuantityEqual(x - u, -(u - x)) + helpers.assert_quantity_equal(x / self.q, u * x / self.q) + helpers.assert_quantity_equal(x * self.q, u * x * self.q) + helpers.assert_quantity_equal(x + u, u + x) + helpers.assert_quantity_equal(x - u, -(u - x)) - def test_pickle(self): + def test_pickle(self, subtests): for protocol in range(pickle.HIGHEST_PROTOCOL + 1): - with self.subTest(protocol): + with subtests.test(protocol): q1 = [10, 20] * self.ureg.m q2 = pickle.loads(pickle.dumps(q1, protocol)) self.assertNDArrayEqual(q1.magnitude, q2.magnitude) - self.assertEqual(q1.units, q2.units) + assert q1.units == q2.units def test_equal(self): x = self.q.magnitude @@ -900,9 +945,9 @@ class TestNumpyUnclassified(TestNumpyMethods): true = np.ones_like(x, dtype=np.bool_) false = np.zeros_like(x, dtype=np.bool_) - self.assertQuantityEqual(u, u) - self.assertQuantityEqual(u == u, u.magnitude == u.magnitude) - self.assertQuantityEqual(u == 1, u.magnitude == 1) + helpers.assert_quantity_equal(u, u) + helpers.assert_quantity_equal(u == u, u.magnitude == u.magnitude) + helpers.assert_quantity_equal(u == 1, u.magnitude == 1) v = self.Q_(np.zeros(x.shape), "m") w = self.Q_(np.ones(x.shape), "m") @@ -919,51 +964,51 @@ class TestNumpyUnclassified(TestNumpyMethods): def test_shape(self): u = self.Q_(np.arange(12)) u.shape = 4, 3 - self.assertEqual(u.magnitude.shape, (4, 3)) + assert u.magnitude.shape == (4, 3) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_shape_numpy_func(self): - self.assertEqual(np.shape(self.q), (2, 2)) + assert np.shape(self.q) == (2, 2) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_alen_numpy_func(self): - self.assertEqual(np.alen(self.q), 2) + assert np.alen(self.q) == 2 - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_ndim_numpy_func(self): - self.assertEqual(np.ndim(self.q), 2) + assert np.ndim(self.q) == 2 - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_copy_numpy_func(self): q_copy = np.copy(self.q) - self.assertQuantityEqual(self.q, q_copy) - self.assertIsNot(self.q, q_copy) + helpers.assert_quantity_equal(self.q, q_copy) + assert self.q is not q_copy - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_trim_zeros_numpy_func(self): q = [0, 4, 3, 0, 2, 2, 0, 0, 0] * self.ureg.m - self.assertQuantityEqual(np.trim_zeros(q), [4, 3, 0, 2, 2] * self.ureg.m) + helpers.assert_quantity_equal(np.trim_zeros(q), [4, 3, 0, 2, 2] * self.ureg.m) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_result_type_numpy_func(self): - self.assertEqual(np.result_type(self.q), np.dtype("int")) + assert np.result_type(self.q) == np.dtype("int") - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_nan_to_num_numpy_func(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.nan_to_num(self.q_nan, nan=-999 * self.ureg.mm), [[1, 2], [3, -0.999]] * self.ureg.m, ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_meshgrid_numpy_func(self): x = [1, 2] * self.ureg.m y = [0, 50, 100] * self.ureg.mm xx, yy = np.meshgrid(x, y) - self.assertQuantityEqual(xx, [[1, 2], [1, 2], [1, 2]] * self.ureg.m) - self.assertQuantityEqual(yy, [[0, 0], [50, 50], [100, 100]] * self.ureg.mm) + helpers.assert_quantity_equal(xx, [[1, 2], [1, 2], [1, 2]] * self.ureg.m) + helpers.assert_quantity_equal(yy, [[0, 0], [50, 50], [100, 100]] * self.ureg.mm) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_isclose_numpy_func(self): q2 = [[1000.05, 2000], [3000.00007, 4001]] * self.ureg.mm self.assertNDArrayEqual( @@ -974,12 +1019,12 @@ class TestNumpyUnclassified(TestNumpyMethods): np.array([[False, True], [True, False]]), ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_interp_numpy_func(self): x = [1, 4] * self.ureg.m xp = np.linspace(0, 3, 5) * self.ureg.m fp = self.Q_([0, 5, 10, 15, 20], self.ureg.degC) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( np.interp(x, xp, fp), self.Q_([6.66667, 20.0], self.ureg.degC), rtol=1e-5 ) @@ -987,10 +1032,12 @@ class TestNumpyUnclassified(TestNumpyMethods): xp_ = np.linspace(0, 3, 5) fp_ = [0, 5, 10, 15, 20] - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( np.interp(x_, xp_, fp), self.Q_([6.6667, 20.0], self.ureg.degC), rtol=1e-5 ) - self.assertQuantityAlmostEqual(np.interp(x, xp, fp_), [6.6667, 20.0], rtol=1e-5) + helpers.assert_quantity_almost_equal( + np.interp(x, xp, fp_), [6.6667, 20.0], rtol=1e-5 + ) def test_comparisons(self): self.assertNDArrayEqual( @@ -1000,51 +1047,50 @@ class TestNumpyUnclassified(TestNumpyMethods): self.q < 2 * self.ureg.m, np.array([[True, False], [False, False]]) ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_where(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.where(self.q >= 2 * self.ureg.m, self.q, 20 * self.ureg.m), [[20, 2], [3, 4]] * self.ureg.m, ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.where(self.q >= 2 * self.ureg.m, self.q, 0), [[0, 2], [3, 4]] * self.ureg.m, ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.where(self.q >= 2 * self.ureg.m, self.q, np.nan), [[np.nan, 2], [3, 4]] * self.ureg.m, ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.where(self.q >= 3 * self.ureg.m, 0, self.q), [[1, 2], [0, 0]] * self.ureg.m, ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.where(self.q >= 3 * self.ureg.m, np.nan, self.q), [[1, 2], [np.nan, np.nan]] * self.ureg.m, ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.where(self.q >= 2 * self.ureg.m, self.q, np.array(np.nan)), [[np.nan, 2], [3, 4]] * self.ureg.m, ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.where(self.q >= 3 * self.ureg.m, np.array(np.nan), self.q), [[1, 2], [np.nan, np.nan]] * self.ureg.m, ) - self.assertRaises( - DimensionalityError, - np.where, - self.q < 2 * self.ureg.m, - self.q, - 0 * self.ureg.J, - ) + with pytest.raises(DimensionalityError): + np.where( + self.q < 2 * self.ureg.m, + self.q, + 0 * self.ureg.J, + ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_fabs(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.fabs(self.q - 2 * self.ureg.m), self.Q_([[1, 0], [1, 2]], "m") ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_isin(self): self.assertNDArrayEqual( np.isin(self.q, self.Q_([0, 2, 4], "m")), @@ -1065,116 +1111,121 @@ class TestNumpyUnclassified(TestNumpyMethods): np.isin(self.q / self.ureg.cm, [1, 3]), np.array([[True, False], [True, False]]), ) - self.assertRaises(ValueError, np.isin, self.q.m, self.q) + with pytest.raises(ValueError): + np.isin(self.q.m, self.q) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_percentile(self): - self.assertQuantityEqual(np.percentile(self.q, 25), self.Q_(1.75, "m")) + helpers.assert_quantity_equal(np.percentile(self.q, 25), self.Q_(1.75, "m")) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_nanpercentile(self): - self.assertQuantityEqual(np.nanpercentile(self.q_nan, 25), self.Q_(1.5, "m")) + helpers.assert_quantity_equal( + np.nanpercentile(self.q_nan, 25), self.Q_(1.5, "m") + ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_quantile(self): - self.assertQuantityEqual(np.quantile(self.q, 0.25), self.Q_(1.75, "m")) + helpers.assert_quantity_equal(np.quantile(self.q, 0.25), self.Q_(1.75, "m")) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_nanquantile(self): - self.assertQuantityEqual(np.nanquantile(self.q_nan, 0.25), self.Q_(1.5, "m")) + helpers.assert_quantity_equal( + np.nanquantile(self.q_nan, 0.25), self.Q_(1.5, "m") + ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_copyto(self): a = self.q.m q = copy.copy(self.q) np.copyto(q, 2 * q, where=[True, False]) - self.assertQuantityEqual(q, self.Q_([[2, 2], [6, 4]], "m")) + helpers.assert_quantity_equal(q, self.Q_([[2, 2], [6, 4]], "m")) np.copyto(q, 0, where=[[False, False], [True, False]]) - self.assertQuantityEqual(q, self.Q_([[2, 2], [0, 4]], "m")) + helpers.assert_quantity_equal(q, self.Q_([[2, 2], [0, 4]], "m")) np.copyto(a, q) self.assertNDArrayEqual(a, np.array([[2, 2], [0, 4]])) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_tile(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.tile(self.q, 2), np.array([[1, 2, 1, 2], [3, 4, 3, 4]]) * self.ureg.m ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_rot90(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.rot90(self.q), np.array([[2, 4], [1, 3]]) * self.ureg.m ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_insert(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.insert(self.q, 1, 0 * self.ureg.m, axis=1), np.array([[1, 0, 2], [3, 0, 4]]) * self.ureg.m, ) def test_ndarray_downcast(self): - with self.assertWarns(UnitStrippedWarning): + with pytest.warns(UnitStrippedWarning): np.asarray(self.q) def test_ndarray_downcast_with_dtype(self): - with self.assertWarns(UnitStrippedWarning): + with pytest.warns(UnitStrippedWarning): qarr = np.asarray(self.q, dtype=np.float64) - self.assertEqual(qarr.dtype, np.float64) + assert qarr.dtype == np.float64 def test_array_protocol_unavailable(self): for attr in ("__array_struct__", "__array_interface__"): - self.assertRaises(AttributeError, getattr, self.q, attr) + with pytest.raises(AttributeError): + getattr(self.q, attr) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_resize(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.resize(self.q, (2, 4)), [[1, 2, 3, 4], [1, 2, 3, 4]] * self.ureg.m ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_pad(self): # Tests reproduced with modification from NumPy documentation a = [1, 2, 3, 4, 5] * self.ureg.m b = self.Q_([4.0, 6.0, 8.0, 9.0, -3.0], "degC") - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.pad(a, (2, 3), "constant"), [0, 0, 1, 2, 3, 4, 5, 0, 0, 0] * self.ureg.m ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.pad(a, (2, 3), "constant", constant_values=(0, 600 * self.ureg.cm)), [0, 0, 1, 2, 3, 4, 5, 6, 6, 6] * self.ureg.m, ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.pad( b, (2, 1), "constant", constant_values=(np.nan, self.Q_(10, "degC")) ), self.Q_([np.nan, np.nan, 4, 6, 8, 9, -3, 10], "degC"), ) - self.assertRaises( - DimensionalityError, np.pad, a, (2, 3), "constant", constant_values=4 - ) - self.assertQuantityEqual( + with pytest.raises(DimensionalityError): + np.pad(a, (2, 3), "constant", constant_values=4) + helpers.assert_quantity_equal( np.pad(a, (2, 3), "edge"), [1, 1, 1, 2, 3, 4, 5, 5, 5, 5] * self.ureg.m ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.pad(a, (2, 3), "linear_ramp"), [0, 0, 1, 2, 3, 4, 5, 3, 1, 0] * self.ureg.m, ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.pad(a, (2, 3), "linear_ramp", end_values=(5, -4) * self.ureg.m), [5, 3, 1, 2, 3, 4, 5, 2, -1, -4] * self.ureg.m, ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.pad(a, (2,), "maximum"), [5, 5, 1, 2, 3, 4, 5, 5, 5] * self.ureg.m ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.pad(a, (2,), "mean"), [3, 3, 1, 2, 3, 4, 5, 3, 3] * self.ureg.m ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.pad(a, (2,), "median"), [3, 3, 1, 2, 3, 4, 5, 3, 3] * self.ureg.m ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.pad(self.q, ((3, 2), (2, 3)), "minimum"), [ [1, 1, 1, 2, 1, 1, 1], @@ -1187,21 +1238,21 @@ class TestNumpyUnclassified(TestNumpyMethods): ] * self.ureg.m, ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.pad(a, (2, 3), "reflect"), [3, 2, 1, 2, 3, 4, 5, 4, 3, 2] * self.ureg.m ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.pad(a, (2, 3), "reflect", reflect_type="odd"), [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8] * self.ureg.m, ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.pad(a, (2, 3), "symmetric"), [2, 1, 1, 2, 3, 4, 5, 5, 4, 3] * self.ureg.m ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.pad(a, (2, 3), "symmetric", reflect_type="odd"), [0, 1, 1, 2, 3, 4, 5, 5, 6, 7] * self.ureg.m, ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.pad(a, (2, 3), "wrap"), [4, 5, 1, 2, 3, 4, 5, 1, 2, 3] * self.ureg.m ) @@ -1211,7 +1262,7 @@ class TestNumpyUnclassified(TestNumpyMethods): vector[-pad_width[1] :] = pad_value b = self.Q_(np.arange(6).reshape((2, 3)), "degC") - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.pad(b, 2, pad_with), self.Q_( [ @@ -1225,7 +1276,7 @@ class TestNumpyUnclassified(TestNumpyMethods): "degC", ), ) - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.pad(b, 2, pad_with, padder=100), self.Q_( [ @@ -1240,24 +1291,22 @@ class TestNumpyUnclassified(TestNumpyMethods): ), ) # Note: Does not support Quantity pad_with vectorized callable use - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_allclose(self): - self.assertTrue( - np.allclose([1e10, 1e-8] * self.ureg.m, [1.00001e10, 1e-9] * self.ureg.m) - ) - self.assertFalse( - np.allclose([1e10, 1e-8] * self.ureg.m, [1.00001e10, 1e-9] * self.ureg.mm) + assert np.allclose([1e10, 1e-8] * self.ureg.m, [1.00001e10, 1e-9] * self.ureg.m) + assert not np.allclose( + [1e10, 1e-8] * self.ureg.m, [1.00001e10, 1e-9] * self.ureg.mm ) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_intersect1d(self): - self.assertQuantityEqual( + helpers.assert_quantity_equal( np.intersect1d([1, 3, 4, 3] * self.ureg.m, [3, 1, 2, 1] * self.ureg.m), [1, 3] * self.ureg.m, ) -@unittest.skip +@pytest.mark.skip class TestBitTwiddlingUfuncs(TestUFuncs): """Universal functions (ufuncs) > Bittwiddling functions diff --git a/pint/testsuite/test_numpy_func.py b/pint/testsuite/test_numpy_func.py index 3a9453d..732ac61 100644 --- a/pint/testsuite/test_numpy_func.py +++ b/pint/testsuite/test_numpy_func.py @@ -1,5 +1,7 @@ from unittest.mock import patch +import pytest + import pint.numpy_func from pint import DimensionalityError, OffsetUnitCalculusError from pint.compat import np @@ -12,6 +14,7 @@ from pint.numpy_func import ( numpy_wrap, unwrap_and_wrap_consistent_units, ) +from pint.testsuite import helpers from pint.testsuite.test_numpy import TestNumpyMethods @@ -24,45 +27,43 @@ class TestNumPyFuncUtils(TestNumpyMethods): def test_function(): pass - self.assertEqual(pint.numpy_func.HANDLED_FUNCTIONS["test"], test_function) + assert pint.numpy_func.HANDLED_FUNCTIONS["test"] == test_function # Test for ufuncs @implements("test", "ufunc") def test_ufunc(): pass - self.assertEqual(pint.numpy_func.HANDLED_UFUNCS["test"], test_ufunc) + assert pint.numpy_func.HANDLED_UFUNCS["test"] == test_ufunc # Test for invalid func type - with self.assertRaises(ValueError): + with pytest.raises(ValueError): @implements("test", "invalid") def test_invalid(): pass def test_is_quantity(self): - self.assertTrue(_is_quantity(self.Q_(0))) - self.assertTrue(_is_quantity(np.arange(4) * self.ureg.m)) - self.assertFalse(_is_quantity(1.0)) - self.assertFalse(_is_quantity(np.array([1, 1, 2, 3, 5, 8]))) - self.assertFalse(_is_quantity("not-a-quantity")) + assert _is_quantity(self.Q_(0)) + assert _is_quantity(np.arange(4) * self.ureg.m) + assert not _is_quantity(1.0) + assert not _is_quantity(np.array([1, 1, 2, 3, 5, 8])) + assert not _is_quantity("not-a-quantity") # TODO (#905 follow-up): test other duck arrays that wrap or are wrapped by Pint def test_is_sequence_with_quantity_elements(self): - self.assertTrue( - _is_sequence_with_quantity_elements( - (self.Q_(0, "m"), self.Q_(32.0, "degF")) - ) - ) - self.assertTrue(_is_sequence_with_quantity_elements(np.arange(4) * self.ureg.m)) - self.assertTrue(_is_sequence_with_quantity_elements((self.Q_(0), 0))) - self.assertTrue(_is_sequence_with_quantity_elements((0, self.Q_(0)))) - self.assertFalse(_is_sequence_with_quantity_elements([1, 3, 5])) - self.assertFalse(_is_sequence_with_quantity_elements(9 * self.ureg.m)) - self.assertFalse(_is_sequence_with_quantity_elements(np.arange(4))) - self.assertFalse(_is_sequence_with_quantity_elements("0123")) - self.assertFalse(_is_sequence_with_quantity_elements([])) - self.assertFalse(_is_sequence_with_quantity_elements(np.array([]))) + assert _is_sequence_with_quantity_elements( + (self.Q_(0, "m"), self.Q_(32.0, "degF")) + ) + assert _is_sequence_with_quantity_elements(np.arange(4) * self.ureg.m) + assert _is_sequence_with_quantity_elements((self.Q_(0), 0)) + assert _is_sequence_with_quantity_elements((0, self.Q_(0))) + assert not _is_sequence_with_quantity_elements([1, 3, 5]) + assert not _is_sequence_with_quantity_elements(9 * self.ureg.m) + assert not _is_sequence_with_quantity_elements(np.arange(4)) + assert not _is_sequence_with_quantity_elements("0123") + assert not _is_sequence_with_quantity_elements([]) + assert not _is_sequence_with_quantity_elements(np.array([])) def test_convert_to_consistent_units_with_pre_calc_units(self): args, kwargs = convert_to_consistent_units( @@ -73,33 +74,31 @@ class TestNumPyFuncUtils(TestNumpyMethods): a=6378 * self.ureg.km, pre_calc_units=self.ureg.meter, ) - self.assertEqual(args[0], 0.5) + assert args[0] == 0.5 self.assertNDArrayEqual(args[1], np.array([[0, 1], [2, 3]])) self.assertNDArrayEqual(args[2], np.array([42])) - self.assertEqual(args[3][0], 0) - self.assertEqual(args[3][1], 10) - self.assertEqual(kwargs["a"], 6.378e6) + assert args[3][0] == 0 + assert args[3][1] == 10 + assert kwargs["a"] == 6.378e6 def test_convert_to_consistent_units_with_dimensionless(self): args, kwargs = convert_to_consistent_units( np.arange(2), pre_calc_units=self.ureg.g / self.ureg.kg ) self.assertNDArrayEqual(args[0], np.array([0, 1000])) - self.assertEqual(kwargs, {}) + assert kwargs == {} def test_convert_to_consistent_units_with_dimensionality_error(self): - self.assertRaises( - DimensionalityError, - convert_to_consistent_units, - self.Q_(32.0, "degF"), - pre_calc_units=self.ureg.meter, - ) - self.assertRaises( - DimensionalityError, - convert_to_consistent_units, - np.arange(4), - pre_calc_units=self.ureg.meter, - ) + with pytest.raises(DimensionalityError): + convert_to_consistent_units( + self.Q_(32.0, "degF"), + pre_calc_units=self.ureg.meter, + ) + with pytest.raises(DimensionalityError): + convert_to_consistent_units( + np.arange(4), + pre_calc_units=self.ureg.meter, + ) def test_convert_to_consistent_units_without_pre_calc_units(self): args, kwargs = convert_to_consistent_units( @@ -107,10 +106,10 @@ class TestNumPyFuncUtils(TestNumpyMethods): [1, 2, 3, 5, 7] * self.ureg.m, pre_calc_units=None, ) - self.assertEqual(args[0][0], 0) - self.assertEqual(args[0][1], 10) + assert args[0][0] == 0 + assert args[0][1] == 10 self.assertNDArrayEqual(args[1], np.array([1, 2, 3, 5, 7])) - self.assertEqual(kwargs, {}) + assert kwargs == {} def test_unwrap_and_wrap_constistent_units(self): (a,), output_wrap_a = unwrap_and_wrap_consistent_units([2, 4, 8] * self.ureg.m) @@ -120,81 +119,75 @@ class TestNumPyFuncUtils(TestNumpyMethods): self.assertNDArrayEqual(a, np.array([2, 4, 8])) self.assertNDArrayEqual(b, np.array([0, 1000, 2000, 3000])) - self.assertEqual(c, 1) + assert c == 1 - self.assertQuantityEqual(output_wrap_a(0), 0 * self.ureg.m) - self.assertQuantityEqual(output_wrap_c(0), self.Q_(0, "g/kg")) + helpers.assert_quantity_equal(output_wrap_a(0), 0 * self.ureg.m) + helpers.assert_quantity_equal(output_wrap_c(0), self.Q_(0, "g/kg")) def test_op_output_unit_sum(self): - self.assertEqual(get_op_output_unit("sum", self.ureg.m), self.ureg.m) - self.assertRaises( - OffsetUnitCalculusError, get_op_output_unit, "sum", self.ureg.degC - ) + assert get_op_output_unit("sum", self.ureg.m) == self.ureg.m + with pytest.raises(OffsetUnitCalculusError): + get_op_output_unit("sum", self.ureg.degC) def test_op_output_unit_mul(self): - self.assertEqual( + assert ( get_op_output_unit( "mul", self.ureg.s, (self.Q_(1, "m"), self.Q_(1, "m**2")) - ), - self.ureg.m ** 3, + ) + == self.ureg.m ** 3 ) def test_op_output_unit_delta(self): - self.assertEqual(get_op_output_unit("delta", self.ureg.m), self.ureg.m) - self.assertEqual( - get_op_output_unit("delta", self.ureg.degC), self.ureg.delta_degC - ) + assert get_op_output_unit("delta", self.ureg.m) == self.ureg.m + assert get_op_output_unit("delta", self.ureg.degC) == self.ureg.delta_degC def test_op_output_unit_delta_div(self): - self.assertEqual( + assert ( get_op_output_unit( "delta,div", self.ureg.m, (self.Q_(1, "m"), self.Q_(1, "s")) - ), - self.ureg.m / self.ureg.s, + ) + == self.ureg.m / self.ureg.s ) - self.assertEqual( + assert ( get_op_output_unit( "delta,div", self.ureg.degC, (self.Q_(1, "degC"), self.Q_(1, "m")) - ), - self.ureg.delta_degC / self.ureg.m, + ) + == self.ureg.delta_degC / self.ureg.m ) def test_op_output_unit_div(self): - self.assertEqual( + assert ( get_op_output_unit( "div", self.ureg.m, (self.Q_(1, "m"), self.Q_(1, "s"), self.Q_(1, "K")) - ), - self.ureg.m / self.ureg.s / self.ureg.K, + ) + == self.ureg.m / self.ureg.s / self.ureg.K ) - self.assertEqual( - get_op_output_unit("div", self.ureg.s, (1, self.Q_(1, "s"))), - self.ureg.s ** -1, + assert ( + get_op_output_unit("div", self.ureg.s, (1, self.Q_(1, "s"))) + == self.ureg.s ** -1 ) def test_op_output_unit_variance(self): - self.assertEqual(get_op_output_unit("variance", self.ureg.m), self.ureg.m ** 2) - self.assertRaises( - OffsetUnitCalculusError, get_op_output_unit, "variance", self.ureg.degC - ) + assert get_op_output_unit("variance", self.ureg.m) == self.ureg.m ** 2 + with pytest.raises(OffsetUnitCalculusError): + get_op_output_unit("variance", self.ureg.degC) def test_op_output_unit_square(self): - self.assertEqual(get_op_output_unit("square", self.ureg.m), self.ureg.m ** 2) + assert get_op_output_unit("square", self.ureg.m) == self.ureg.m ** 2 def test_op_output_unit_sqrt(self): - self.assertEqual(get_op_output_unit("sqrt", self.ureg.m), self.ureg.m ** 0.5) + assert get_op_output_unit("sqrt", self.ureg.m) == self.ureg.m ** 0.5 def test_op_output_unit_reciprocal(self): - self.assertEqual( - get_op_output_unit("reciprocal", self.ureg.m), self.ureg.m ** -1 - ) + assert get_op_output_unit("reciprocal", self.ureg.m) == self.ureg.m ** -1 def test_op_output_unit_size(self): - self.assertEqual( - get_op_output_unit("size", self.ureg.m, size=3), self.ureg.m ** 3 - ) - self.assertRaises(ValueError, get_op_output_unit, "size", self.ureg.m) + assert get_op_output_unit("size", self.ureg.m, size=3) == self.ureg.m ** 3 + with pytest.raises(ValueError): + get_op_output_unit("size", self.ureg.m) def test_numpy_wrap(self): - self.assertRaises(ValueError, numpy_wrap, "invalid", np.ones, [], {}, []) + with pytest.raises(ValueError): + numpy_wrap("invalid", np.ones, [], {}, []) # TODO (#905 follow-up): test that NotImplemented is returned when upcast types # present diff --git a/pint/testsuite/test_pint_eval.py b/pint/testsuite/test_pint_eval.py index 20f9b46..2372933 100644 --- a/pint/testsuite/test_pint_eval.py +++ b/pint/testsuite/test_pint_eval.py @@ -1,12 +1,10 @@ -import unittest - from pint.compat import tokenizer from pint.pint_eval import build_eval_tree -class TestPintEval(unittest.TestCase): +class TestPintEval: def _test_one(self, input_text, parsed): - self.assertEqual(build_eval_tree(tokenizer(input_text)).to_string(), parsed) + assert build_eval_tree(tokenizer(input_text)).to_string() == parsed def test_build_eval_tree(self): self._test_one("3", "3") diff --git a/pint/testsuite/test_pitheorem.py b/pint/testsuite/test_pitheorem.py index 40abd8c..1a49962 100644 --- a/pint/testsuite/test_pitheorem.py +++ b/pint/testsuite/test_pitheorem.py @@ -1,28 +1,24 @@ import itertools +import logging from pint import pi_theorem from pint.testsuite import QuantityTestCase class TestPiTheorem(QuantityTestCase): - - FORCE_NDARRAY = False - - def test_simple(self): + def test_simple(self, caplog): # simple movement - with self.capture_log() as buffer: - self.assertEqual( - pi_theorem({"V": "m/s", "T": "s", "L": "m"}), - [{"V": 1, "T": 1, "L": -1}], - ) + with caplog.at_level(logging.DEBUG): + assert pi_theorem({"V": "m/s", "T": "s", "L": "m"}) == [ + {"V": 1, "T": 1, "L": -1} + ] # pendulum - self.assertEqual( - pi_theorem({"T": "s", "M": "grams", "L": "m", "g": "m/s**2"}), - [{"g": 1, "T": 2, "L": -1}], - ) - self.assertEqual(len(buffer), 7) + assert pi_theorem({"T": "s", "M": "grams", "L": "m", "g": "m/s**2"}) == [ + {"g": 1, "T": 2, "L": -1} + ] + assert len(caplog.records) == 7 def test_inputs(self): V = "km/hour" @@ -39,7 +35,6 @@ class TestPiTheorem(QuantityTestCase): qv = fv(V) qt = ft(T) ql = ft(L) - self.assertEqual( - self.ureg.pi_theorem({"V": qv, "T": qt, "L": ql}), - [{"V": 1.0, "T": 1.0, "L": -1.0}], - ) + assert self.ureg.pi_theorem({"V": qv, "T": qt, "L": ql}) == [ + {"V": 1.0, "T": 1.0, "L": -1.0} + ] diff --git a/pint/testsuite/test_quantity.py b/pint/testsuite/test_quantity.py index 8b6a19e..fb1fc5d 100644 --- a/pint/testsuite/test_quantity.py +++ b/pint/testsuite/test_quantity.py @@ -1,11 +1,14 @@ import copy import datetime +import logging import math import operator as op import pickle import warnings from unittest.mock import patch +import pytest + from pint import ( DimensionalityError, OffsetUnitCalculusError, @@ -15,7 +18,6 @@ from pint import ( ) from pint.compat import np from pint.testsuite import QuantityTestCase, helpers -from pint.testsuite.parameterized import ParameterizedTestCase from pint.unit import UnitsContainer @@ -27,9 +29,9 @@ class FakeWrapper: class TestQuantity(QuantityTestCase): - FORCE_NDARRAY = False + kwargs = dict(autoconvert_offset_to_baseunit=False) - def test_quantity_creation(self): + def test_quantity_creation(self, caplog): for args in ( (4.2, "meter"), (4.2, UnitsContainer(meter=1)), @@ -39,30 +41,31 @@ class TestQuantity(QuantityTestCase): (self.Q_(4.2, "meter"),), ): x = self.Q_(*args) - self.assertEqual(x.magnitude, 4.2) - self.assertEqual(x.units, UnitsContainer(meter=1)) + assert x.magnitude == 4.2 + assert x.units == UnitsContainer(meter=1) x = self.Q_(4.2, UnitsContainer(length=1)) y = self.Q_(x) - self.assertEqual(x.magnitude, y.magnitude) - self.assertEqual(x.units, y.units) - self.assertIsNot(x, y) + assert x.magnitude == y.magnitude + assert x.units == y.units + assert x is not y x = self.Q_(4.2, None) - self.assertEqual(x.magnitude, 4.2) - self.assertEqual(x.units, UnitsContainer()) + assert x.magnitude == 4.2 + assert x.units == UnitsContainer() - with self.capture_log() as buffer: - self.assertEqual(4.2 * self.ureg.meter, self.Q_(4.2, 2 * self.ureg.meter)) - self.assertEqual(len(buffer), 1) + with caplog.at_level(logging.DEBUG): + assert 4.2 * self.ureg.meter == self.Q_(4.2, 2 * self.ureg.meter) + assert len(caplog.records) == 1 def test_quantity_bool(self): - self.assertTrue(self.Q_(1, None)) - self.assertTrue(self.Q_(1, "meter")) - self.assertFalse(self.Q_(0, None)) - self.assertFalse(self.Q_(0, "meter")) - self.assertRaises(ValueError, bool, self.Q_(0, "degC")) - self.assertFalse(self.Q_(0, "delta_degC")) + assert self.Q_(1, None) + assert self.Q_(1, "meter") + assert not self.Q_(0, None) + assert not self.Q_(0, "meter") + with pytest.raises(ValueError): + bool(self.Q_(0, "degC")) + assert not self.Q_(0, "delta_degC") def test_quantity_comparison(self): x = self.Q_(4.2, "meter") @@ -75,63 +78,61 @@ class TestQuantity(QuantityTestCase): m = Quantity(5, "meter") # Include a comparison to a directly created Quantity # identity for single object - self.assertTrue(x == x) - self.assertFalse(x != x) + assert x == x + assert not (x != x) # identity for multiple objects with same value - self.assertTrue(x == y) - self.assertFalse(x != y) + assert x == y + assert not (x != y) - self.assertTrue(x <= y) - self.assertTrue(x >= y) - self.assertFalse(x < y) - self.assertFalse(x > y) + assert x <= y + assert x >= y + assert not (x < y) + assert not (x > y) - self.assertFalse(x == z) - self.assertTrue(x != z) - self.assertTrue(x < z) + assert not (x == z) + assert x != z + assert x < z # Compare with items to the separate application registry - self.assertTrue(k >= m) # These should both be from application registry - with self.assertRaises(ValueError): + assert k >= m # These should both be from application registry + with pytest.raises(ValueError): z > m # One from local registry, one from application registry - self.assertTrue(z != j) + assert z != j - self.assertNotEqual(z, j) - self.assertEqual(self.Q_(0, "meter"), self.Q_(0, "centimeter")) - self.assertNotEqual(self.Q_(0, "meter"), self.Q_(0, "second")) + assert z != j + assert self.Q_(0, "meter") == self.Q_(0, "centimeter") + assert self.Q_(0, "meter") != self.Q_(0, "second") - self.assertLess(self.Q_(10, "meter"), self.Q_(5, "kilometer")) + assert self.Q_(10, "meter") < self.Q_(5, "kilometer") def test_quantity_comparison_convert(self): - self.assertEqual(self.Q_(1000, "millimeter"), self.Q_(1, "meter")) - self.assertEqual( - self.Q_(1000, "millimeter/min"), self.Q_(1000 / 60, "millimeter/s") - ) + assert self.Q_(1000, "millimeter") == self.Q_(1, "meter") + assert self.Q_(1000, "millimeter/min") == self.Q_(1000 / 60, "millimeter/s") def test_quantity_repr(self): x = self.Q_(4.2, UnitsContainer(meter=1)) - self.assertEqual(str(x), "4.2 meter") - self.assertEqual(repr(x), "<Quantity(4.2, 'meter')>") + assert str(x) == "4.2 meter" + assert repr(x) == "<Quantity(4.2, 'meter')>" def test_quantity_hash(self): x = self.Q_(4.2, "meter") x2 = self.Q_(4200, "millimeter") y = self.Q_(2, "second") z = self.Q_(0.5, "hertz") - self.assertEqual(hash(x), hash(x2)) + assert hash(x) == hash(x2) # Dimensionless equality - self.assertEqual(hash(y * z), hash(1.0)) + assert hash(y * z) == hash(1.0) # Dimensionless equality from a different unit registry - ureg2 = UnitRegistry(force_ndarray=self.FORCE_NDARRAY) + ureg2 = UnitRegistry(**self.kwargs) y2 = ureg2.Quantity(2, "second") z2 = ureg2.Quantity(0.5, "hertz") - self.assertEqual(hash(y * z), hash(y2 * z2)) + assert hash(y * z) == hash(y2 * z2) - def test_quantity_format(self): + def test_quantity_format(self, subtests): x = self.Q_(4.12345678, UnitsContainer(meter=2, kilogram=1, second=-1)) for spec, result in ( ("{}", str(x)), @@ -161,15 +162,15 @@ class TestQuantity(QuantityTestCase): ("{:C~}", "4.12345678 kg*m**2/s"), ("{:Lx}", r"\SI[]{4.12345678}{\kilo\gram\meter\squared\per\second}"), ): - with self.subTest(spec): - self.assertEqual(spec.format(x), result) + with subtests.test(spec): + assert spec.format(x) == result # Check the special case that prevents e.g. '3 1 / second' x = self.Q_(3, UnitsContainer(second=-1)) - self.assertEqual(f"{x}", "3 / second") + assert f"{x}" == "3 / second" - @helpers.requires_numpy() - def test_quantity_array_format(self): + @helpers.requires_numpy + def test_quantity_array_format(self, subtests): x = self.Q_( np.array([1e-16, 1.0000001, 10000000.0, 1e12, np.nan, np.inf]), "kg * m ** 2", @@ -201,30 +202,30 @@ class TestQuantity(QuantityTestCase): ), ), ): - with self.subTest(spec): - self.assertEqual(spec.format(x), result) + with subtests.test(spec): + assert spec.format(x) == result def test_format_compact(self): q1 = (200e-9 * self.ureg.s).to_compact() q1b = self.Q_(200.0, "nanosecond") - self.assertAlmostEqual(q1.magnitude, q1b.magnitude) - self.assertEqual(q1.units, q1b.units) + assert round(abs(q1.magnitude - q1b.magnitude), 7) == 0 + assert q1.units == q1b.units q2 = (1e-2 * self.ureg("kg m/s^2")).to_compact("N") q2b = self.Q_(10.0, "millinewton") - self.assertEqual(q2.magnitude, q2b.magnitude) - self.assertEqual(q2.units, q2b.units) + assert q2.magnitude == q2b.magnitude + assert q2.units == q2b.units q3 = (-1000.0 * self.ureg("meters")).to_compact() q3b = self.Q_(-1.0, "kilometer") - self.assertEqual(q3.magnitude, q3b.magnitude) - self.assertEqual(q3.units, q3b.units) + assert q3.magnitude == q3b.magnitude + assert q3.units == q3b.units - self.assertEqual(f"{q1:#.1f}", f"{q1b}") - self.assertEqual(f"{q2:#.1f}", f"{q2b}") - self.assertEqual(f"{q3:#.1f}", f"{q3b}") + assert f"{q1:#.1f}" == f"{q1b}" + assert f"{q2:#.1f}" == f"{q2b}" + assert f"{q3:#.1f}" == f"{q3b}" - def test_default_formatting(self): + def test_default_formatting(self, subtests): ureg = UnitRegistry() x = ureg.Quantity(4.12345678, UnitsContainer(meter=2, kilogram=1, second=-1)) for spec, result in ( @@ -241,21 +242,21 @@ class TestQuantity(QuantityTestCase): ("H~", "4.12345678 kg m<sup>2</sup>/s"), ("C~", "4.12345678 kg*m**2/s"), ): - with self.subTest(spec): + with subtests.test(spec): ureg.default_format = spec - self.assertEqual(f"{x}", result) + assert f"{x}" == result def test_exponent_formatting(self): ureg = UnitRegistry() x = ureg.Quantity(1e20, "meter") - self.assertEqual(f"{x:~H}", r"1×10<sup>20</sup> m") - self.assertEqual(f"{x:~L}", r"1\times 10^{20}\ \mathrm{m}") - self.assertEqual(f"{x:~P}", r"1×10²⁰ m") + assert f"{x:~H}" == r"1×10<sup>20</sup> m" + assert f"{x:~L}" == r"1\times 10^{20}\ \mathrm{m}" + assert f"{x:~P}" == r"1×10²⁰ m" x /= 1e40 - self.assertEqual(f"{x:~H}", r"1×10<sup>-20</sup> m") - self.assertEqual(f"{x:~L}", r"1\times 10^{-20}\ \mathrm{m}") - self.assertEqual(f"{x:~P}", r"1×10⁻²⁰ m") + assert f"{x:~H}" == r"1×10<sup>-20</sup> m" + assert f"{x:~L}" == r"1\times 10^{-20}\ \mathrm{m}" + assert f"{x:~P}" == r"1×10⁻²⁰ m" def test_ipython(self): alltext = [] @@ -274,54 +275,57 @@ class TestQuantity(QuantityTestCase): ureg = UnitRegistry() x = 3.5 * ureg.Unit(UnitsContainer(meter=2, kilogram=1, second=-1)) - self.assertEqual(x._repr_html_(), "3.5 kilogram meter<sup>2</sup>/second") - self.assertEqual( - x._repr_latex_(), - r"$3.5\ \frac{\mathrm{kilogram} \cdot " - r"\mathrm{meter}^{2}}{\mathrm{second}}$", + assert x._repr_html_() == "3.5 kilogram meter<sup>2</sup>/second" + assert ( + x._repr_latex_() == r"$3.5\ \frac{\mathrm{kilogram} \cdot " + r"\mathrm{meter}^{2}}{\mathrm{second}}$" ) x._repr_pretty_(Pretty, False) - self.assertEqual("".join(alltext), "3.5 kilogram·meter²/second") + assert "".join(alltext) == "3.5 kilogram·meter²/second" ureg.default_format = "~" - self.assertEqual(x._repr_html_(), "3.5 kg m<sup>2</sup>/s") - self.assertEqual( - x._repr_latex_(), - r"$3.5\ \frac{\mathrm{kg} \cdot " r"\mathrm{m}^{2}}{\mathrm{s}}$", + assert x._repr_html_() == "3.5 kg m<sup>2</sup>/s" + assert ( + x._repr_latex_() == r"$3.5\ \frac{\mathrm{kg} \cdot " + r"\mathrm{m}^{2}}{\mathrm{s}}$" ) alltext = [] x._repr_pretty_(Pretty, False) - self.assertEqual("".join(alltext), "3.5 kg·m²/s") + assert "".join(alltext) == "3.5 kg·m²/s" def test_to_base_units(self): x = self.Q_("1*inch") - self.assertQuantityAlmostEqual(x.to_base_units(), self.Q_(0.0254, "meter")) + helpers.assert_quantity_almost_equal( + x.to_base_units(), self.Q_(0.0254, "meter") + ) x = self.Q_("1*inch*inch") - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( x.to_base_units(), self.Q_(0.0254 ** 2.0, "meter*meter") ) x = self.Q_("1*inch/minute") - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( x.to_base_units(), self.Q_(0.0254 / 60.0, "meter/second") ) def test_convert(self): - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_("2 inch").to("meter"), self.Q_(2.0 * 0.0254, "meter") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_("2 meter").to("inch"), self.Q_(2.0 / 0.0254, "inch") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_("2 sidereal_year").to("second"), self.Q_(63116297.5325, "second") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_("2.54 centimeter/second").to("inch/second"), self.Q_("1 inch/second"), ) - self.assertAlmostEqual(self.Q_("2.54 centimeter").to("inch").magnitude, 1) - self.assertAlmostEqual(self.Q_("2 second").to("millisecond").magnitude, 2000) + assert round(abs(self.Q_("2.54 centimeter").to("inch").magnitude - 1), 7) == 0 + assert ( + round(abs(self.Q_("2 second").to("millisecond").magnitude - 2000), 7) == 0 + ) - @helpers.requires_numpy() + @helpers.requires_numpy def test_convert_numpy(self): # Conversions with single units take a different codepath than @@ -335,187 +339,194 @@ class TestQuantity(QuantityTestCase): q = self.Q_(a, src) qac = self.Q_(ac, src).to(dst) r = q.to(dst) - self.assertQuantityAlmostEqual(qac, r) - self.assertIsNot(r, q) - self.assertIsNot(r._magnitude, a) + helpers.assert_quantity_almost_equal(qac, r) + assert r is not q + assert r._magnitude is not a def test_convert_from(self): x = self.Q_("2*inch") meter = self.ureg.meter # from quantity - self.assertQuantityAlmostEqual(meter.from_(x), self.Q_(2.0 * 0.0254, "meter")) - self.assertQuantityAlmostEqual(meter.m_from(x), 2.0 * 0.0254) + helpers.assert_quantity_almost_equal( + meter.from_(x), self.Q_(2.0 * 0.0254, "meter") + ) + helpers.assert_quantity_almost_equal(meter.m_from(x), 2.0 * 0.0254) # from unit - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( meter.from_(self.ureg.inch), self.Q_(0.0254, "meter") ) - self.assertQuantityAlmostEqual(meter.m_from(self.ureg.inch), 0.0254) + helpers.assert_quantity_almost_equal(meter.m_from(self.ureg.inch), 0.0254) # from number - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( meter.from_(2, strict=False), self.Q_(2.0, "meter") ) - self.assertQuantityAlmostEqual(meter.m_from(2, strict=False), 2.0) + helpers.assert_quantity_almost_equal(meter.m_from(2, strict=False), 2.0) # from number (strict mode) - self.assertRaises(ValueError, meter.from_, 2) - self.assertRaises(ValueError, meter.m_from, 2) + with pytest.raises(ValueError): + meter.from_(2) + with pytest.raises(ValueError): + meter.m_from(2) - @helpers.requires_numpy() + @helpers.requires_numpy def test_retain_unit(self): # Test that methods correctly retain units and do not degrade into # ordinary ndarrays. List contained in __copy_units. a = np.ones((3, 2)) q = self.Q_(a, "km") - self.assertEqual(q.u, q.reshape(2, 3).u) - self.assertEqual(q.u, q.swapaxes(0, 1).u) - self.assertEqual(q.u, q.mean().u) - self.assertEqual(q.u, np.compress((q == q[0, 0]).any(0), q).u) + assert q.u == q.reshape(2, 3).u + assert q.u == q.swapaxes(0, 1).u + assert q.u == q.mean().u + assert q.u == np.compress((q == q[0, 0]).any(0), q).u def test_context_attr(self): - self.assertEqual(self.ureg.meter, self.Q_(1, "meter")) + assert self.ureg.meter == self.Q_(1, "meter") def test_both_symbol(self): - self.assertEqual(self.Q_(2, "ms"), self.Q_(2, "millisecond")) - self.assertEqual(self.Q_(2, "cm"), self.Q_(2, "centimeter")) + assert self.Q_(2, "ms") == self.Q_(2, "millisecond") + assert self.Q_(2, "cm") == self.Q_(2, "centimeter") def test_dimensionless_units(self): - self.assertAlmostEqual( - self.Q_(360, "degree").to("radian").magnitude, 2 * math.pi + assert ( + round(abs(self.Q_(360, "degree").to("radian").magnitude - 2 * math.pi), 7) + == 0 + ) + assert ( + round(abs(self.Q_(2 * math.pi, "radian") - self.Q_(360, "degree")), 7) == 0 ) - self.assertAlmostEqual(self.Q_(2 * math.pi, "radian"), self.Q_(360, "degree")) - self.assertEqual(self.Q_(1, "radian").dimensionality, UnitsContainer()) - self.assertTrue(self.Q_(1, "radian").dimensionless) - self.assertFalse(self.Q_(1, "radian").unitless) + assert self.Q_(1, "radian").dimensionality == UnitsContainer() + assert self.Q_(1, "radian").dimensionless + assert not self.Q_(1, "radian").unitless - self.assertEqual(self.Q_(1, "meter") / self.Q_(1, "meter"), 1) - self.assertEqual((self.Q_(1, "meter") / self.Q_(1, "mm")).to(""), 1000) + assert self.Q_(1, "meter") / self.Q_(1, "meter") == 1 + assert (self.Q_(1, "meter") / self.Q_(1, "mm")).to("") == 1000 - self.assertEqual(self.Q_(10) // self.Q_(360, "degree"), 1) - self.assertEqual(self.Q_(400, "degree") // self.Q_(2 * math.pi), 1) - self.assertEqual(self.Q_(400, "degree") // (2 * math.pi), 1) - self.assertEqual(7 // self.Q_(360, "degree"), 1) + assert self.Q_(10) // self.Q_(360, "degree") == 1 + assert self.Q_(400, "degree") // self.Q_(2 * math.pi) == 1 + assert self.Q_(400, "degree") // (2 * math.pi) == 1 + assert 7 // self.Q_(360, "degree") == 1 def test_offset(self): - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(0, "kelvin").to("kelvin"), self.Q_(0, "kelvin") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(0, "degC").to("kelvin"), self.Q_(273.15, "kelvin") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(0, "degF").to("kelvin"), self.Q_(255.372222, "kelvin"), rtol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(100, "kelvin").to("kelvin"), self.Q_(100, "kelvin") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(100, "degC").to("kelvin"), self.Q_(373.15, "kelvin") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(100, "degF").to("kelvin"), self.Q_(310.92777777, "kelvin"), rtol=0.01, ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(0, "kelvin").to("degC"), self.Q_(-273.15, "degC") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(100, "kelvin").to("degC"), self.Q_(-173.15, "degC") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(0, "kelvin").to("degF"), self.Q_(-459.67, "degF"), rtol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(100, "kelvin").to("degF"), self.Q_(-279.67, "degF"), rtol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(32, "degF").to("degC"), self.Q_(0, "degC"), atol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(100, "degC").to("degF"), self.Q_(212, "degF"), atol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(54, "degF").to("degC"), self.Q_(12.2222, "degC"), atol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(12, "degC").to("degF"), self.Q_(53.6, "degF"), atol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(12, "kelvin").to("degC"), self.Q_(-261.15, "degC"), atol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(12, "degC").to("kelvin"), self.Q_(285.15, "kelvin"), atol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(12, "kelvin").to("degR"), self.Q_(21.6, "degR"), atol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(12, "degR").to("kelvin"), self.Q_(6.66666667, "kelvin"), atol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(12, "degC").to("degR"), self.Q_(513.27, "degR"), atol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(12, "degR").to("degC"), self.Q_(-266.483333, "degC"), atol=0.01 ) def test_offset_delta(self): - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(0, "delta_degC").to("kelvin"), self.Q_(0, "kelvin") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(0, "delta_degF").to("kelvin"), self.Q_(0, "kelvin"), rtol=0.01 ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(100, "kelvin").to("delta_degC"), self.Q_(100, "delta_degC") ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(100, "kelvin").to("delta_degF"), self.Q_(180, "delta_degF"), rtol=0.01, ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(100, "delta_degF").to("kelvin"), self.Q_(55.55555556, "kelvin"), rtol=0.01, ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(100, "delta_degC").to("delta_degF"), self.Q_(180, "delta_degF"), rtol=0.01, ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(100, "delta_degF").to("delta_degC"), self.Q_(55.55555556, "delta_degC"), rtol=0.01, ) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( self.Q_(12.3, "delta_degC").to("delta_degF"), self.Q_(22.14, "delta_degF"), rtol=0.01, ) - def test_pickle(self): + def test_pickle(self, subtests): for protocol in range(pickle.HIGHEST_PROTOCOL + 1): for magnitude, unit in ((32, ""), (2.4, ""), (32, "m/s"), (2.4, "m/s")): - with self.subTest(protocol=protocol, magnitude=magnitude, unit=unit): + with subtests.test(protocol=protocol, magnitude=magnitude, unit=unit): q1 = self.Q_(magnitude, unit) q2 = pickle.loads(pickle.dumps(q1, protocol)) - self.assertEqual(q1, q2) + assert q1 == q2 - @helpers.requires_numpy() + @helpers.requires_numpy def test_from_sequence(self): u_array_ref = self.Q_([200, 1000], "g") u_array_ref_reversed = self.Q_([1000, 200], "g") @@ -523,36 +534,36 @@ class TestQuantity(QuantityTestCase): u_seq_reversed = u_seq[::-1] u_array = self.Q_.from_sequence(u_seq) - self.assertTrue(all(u_array == u_array_ref)) + assert all(u_array == u_array_ref) u_array_2 = self.Q_.from_sequence(u_seq_reversed) - self.assertTrue(all(u_array_2 == u_array_ref_reversed)) - self.assertFalse(u_array_2.u == u_array_ref_reversed.u) + assert all(u_array_2 == u_array_ref_reversed) + assert not (u_array_2.u == u_array_ref_reversed.u) u_array_3 = self.Q_.from_sequence(u_seq_reversed, units="g") - self.assertTrue(all(u_array_3 == u_array_ref_reversed)) - self.assertTrue(u_array_3.u == u_array_ref_reversed.u) + assert all(u_array_3 == u_array_ref_reversed) + assert u_array_3.u == u_array_ref_reversed.u - with self.assertRaises(ValueError): + with pytest.raises(ValueError): self.Q_.from_sequence([]) u_array_5 = self.Q_.from_list(u_seq) - self.assertTrue(all(u_array_5 == u_array_ref)) + assert all(u_array_5 == u_array_ref) - @helpers.requires_numpy() + @helpers.requires_numpy def test_iter(self): # Verify that iteration gives element as Quantity with same units x = self.Q_([0, 1, 2, 3], "m") - self.assertQuantityEqual(next(iter(x)), self.Q_(0, "m")) + helpers.assert_quantity_equal(next(iter(x)), self.Q_(0, "m")) def test_notiter(self): # Verify that iter() crashes immediately, without needing to draw any # element from it, if the magnitude isn't iterable x = self.Q_(1, "m") - with self.assertRaises(TypeError): + with pytest.raises(TypeError): iter(x) - @helpers.requires_array_function_protocol() + @helpers.requires_array_function_protocol def test_no_longer_array_function_warning_on_creation(self): # Test that warning is no longer raised on first creation with warnings.catch_warnings(): @@ -561,88 +572,87 @@ class TestQuantity(QuantityTestCase): @helpers.requires_not_numpy() def test_no_ndarray_coercion_without_numpy(self): - self.assertRaises(ValueError, self.Q_(1, "m").__array__) + with pytest.raises(ValueError): + self.Q_(1, "m").__array__() @patch("pint.compat.upcast_types", [FakeWrapper]) def test_upcast_type_rejection_on_creation(self): - self.assertRaises(TypeError, self.Q_, FakeWrapper(42), "m") - self.assertEqual(FakeWrapper(self.Q_(42, "m")).q, self.Q_(42, "m")) + with pytest.raises(TypeError): + self.Q_(FakeWrapper(42), "m") + assert FakeWrapper(self.Q_(42, "m")).q == self.Q_(42, "m") class TestQuantityToCompact(QuantityTestCase): def assertQuantityAlmostIdentical(self, q1, q2): - self.assertEqual(q1.units, q2.units) - self.assertAlmostEqual(q1.magnitude, q2.magnitude) + assert q1.units == q2.units + assert round(abs(q1.magnitude - q2.magnitude), 7) == 0 - def compareQuantity_compact(self, q, expected_compact, unit=None): - self.assertQuantityAlmostIdentical(q.to_compact(unit=unit), expected_compact) + def compare_quantity_compact(self, q, expected_compact, unit=None): + helpers.assert_quantity_almost_equal(q.to_compact(unit=unit), expected_compact) def test_dimensionally_simple_units(self): ureg = self.ureg - self.compareQuantity_compact(1 * ureg.m, 1 * ureg.m) - self.compareQuantity_compact(1e-9 * ureg.m, 1 * ureg.nm) + self.compare_quantity_compact(1 * ureg.m, 1 * ureg.m) + self.compare_quantity_compact(1e-9 * ureg.m, 1 * ureg.nm) def test_power_units(self): ureg = self.ureg - self.compareQuantity_compact(900 * ureg.m ** 2, 900 * ureg.m ** 2) - self.compareQuantity_compact(1e7 * ureg.m ** 2, 10 * ureg.km ** 2) + self.compare_quantity_compact(900 * ureg.m ** 2, 900 * ureg.m ** 2) + self.compare_quantity_compact(1e7 * ureg.m ** 2, 10 * ureg.km ** 2) def test_inverse_units(self): ureg = self.ureg - self.compareQuantity_compact(1 / ureg.m, 1 / ureg.m) - self.compareQuantity_compact(100e9 / ureg.m, 100 / ureg.nm) + self.compare_quantity_compact(1 / ureg.m, 1 / ureg.m) + self.compare_quantity_compact(100e9 / ureg.m, 100 / ureg.nm) def test_inverse_square_units(self): ureg = self.ureg - self.compareQuantity_compact(1 / ureg.m ** 2, 1 / ureg.m ** 2) - self.compareQuantity_compact(1e11 / ureg.m ** 2, 1e5 / ureg.mm ** 2) + self.compare_quantity_compact(1 / ureg.m ** 2, 1 / ureg.m ** 2) + self.compare_quantity_compact(1e11 / ureg.m ** 2, 1e5 / ureg.mm ** 2) def test_fractional_units(self): ureg = self.ureg # Typing denominator first to provoke potential error - self.compareQuantity_compact(20e3 * ureg("hr^(-1) m"), 20 * ureg.km / ureg.hr) + self.compare_quantity_compact(20e3 * ureg("hr^(-1) m"), 20 * ureg.km / ureg.hr) def test_fractional_exponent_units(self): ureg = self.ureg - self.compareQuantity_compact(1 * ureg.m ** 0.5, 1 * ureg.m ** 0.5) - self.compareQuantity_compact(1e-2 * ureg.m ** 0.5, 10 * ureg.um ** 0.5) + self.compare_quantity_compact(1 * ureg.m ** 0.5, 1 * ureg.m ** 0.5) + self.compare_quantity_compact(1e-2 * ureg.m ** 0.5, 10 * ureg.um ** 0.5) def test_derived_units(self): ureg = self.ureg - self.compareQuantity_compact(0.5 * ureg.megabyte, 500 * ureg.kilobyte) - self.compareQuantity_compact(1e-11 * ureg.N, 10 * ureg.pN) + self.compare_quantity_compact(0.5 * ureg.megabyte, 500 * ureg.kilobyte) + self.compare_quantity_compact(1e-11 * ureg.N, 10 * ureg.pN) def test_unit_parameter(self): ureg = self.ureg - self.compareQuantity_compact( + self.compare_quantity_compact( self.Q_(100e-9, "kg m / s^2"), 100 * ureg.nN, ureg.N ) - self.compareQuantity_compact( + self.compare_quantity_compact( self.Q_(101.3e3, "kg/m/s^2"), 101.3 * ureg.kPa, ureg.Pa ) def test_limits_magnitudes(self): ureg = self.ureg - self.compareQuantity_compact(0 * ureg.m, 0 * ureg.m) - self.compareQuantity_compact(float("inf") * ureg.m, float("inf") * ureg.m) + self.compare_quantity_compact(0 * ureg.m, 0 * ureg.m) + self.compare_quantity_compact(float("inf") * ureg.m, float("inf") * ureg.m) def test_nonnumeric_magnitudes(self): ureg = self.ureg x = "some string" * ureg.m - with self.assertWarns(RuntimeWarning): - self.compareQuantity_compact(x, x) + with pytest.warns(RuntimeWarning): + self.compare_quantity_compact(x, x) def test_very_large_to_compact(self): # This should not raise an IndexError - self.compareQuantity_compact( + self.compare_quantity_compact( self.Q_(10000, "yottameter"), self.Q_(10 ** 28, "meter").to_compact() ) class TestQuantityBasicMath(QuantityTestCase): - - FORCE_NDARRAY = False - def _test_inplace(self, operator, value1, value2, expected_result, unit=None): if isinstance(value1, str): value1 = self.Q_(value1) @@ -662,10 +672,10 @@ class TestQuantityBasicMath(QuantityTestCase): id2 = id(value2) value1 = operator(value1, value2) value2_cpy = copy.copy(value2) - self.assertQuantityAlmostEqual(value1, expected_result) - self.assertEqual(id1, id(value1)) - self.assertQuantityAlmostEqual(value2, value2_cpy) - self.assertEqual(id2, id(value2)) + helpers.assert_quantity_almost_equal(value1, expected_result) + assert id1 == id(value1) + helpers.assert_quantity_almost_equal(value2, value2_cpy) + assert id2 == id(value2) def _test_not_inplace(self, operator, value1, value2, expected_result, unit=None): if isinstance(value1, str): @@ -688,11 +698,11 @@ class TestQuantityBasicMath(QuantityTestCase): result = operator(value1, value2) - self.assertQuantityAlmostEqual(expected_result, result) - self.assertQuantityAlmostEqual(value1, value1_cpy) - self.assertQuantityAlmostEqual(value2, value2_cpy) - self.assertNotEqual(id(result), id1) - self.assertNotEqual(id(result), id2) + helpers.assert_quantity_almost_equal(expected_result, result) + helpers.assert_quantity_almost_equal(value1, value1_cpy) + helpers.assert_quantity_almost_equal(value2, value2_cpy) + assert id(result) != id1 + assert id(result) != id2 def _test_quantity_add_sub(self, unit, func): x = self.Q_(unit, "centimeter") @@ -704,17 +714,23 @@ class TestQuantityBasicMath(QuantityTestCase): func(op.add, x, y, self.Q_(unit + 2.54 * unit, "centimeter")) func(op.add, y, x, self.Q_(unit + unit / (2.54 * unit), "inch")) func(op.add, a, unit, self.Q_(unit + unit, None)) - self.assertRaises(DimensionalityError, op.add, 10, x) - self.assertRaises(DimensionalityError, op.add, x, 10) - self.assertRaises(DimensionalityError, op.add, x, z) + with pytest.raises(DimensionalityError): + op.add(10, x) + with pytest.raises(DimensionalityError): + op.add(x, 10) + with pytest.raises(DimensionalityError): + op.add(x, z) func(op.sub, x, x, self.Q_(unit - unit, "centimeter")) func(op.sub, x, y, self.Q_(unit - 2.54 * unit, "centimeter")) func(op.sub, y, x, self.Q_(unit - unit / (2.54 * unit), "inch")) func(op.sub, a, unit, self.Q_(unit - unit, None)) - self.assertRaises(DimensionalityError, op.sub, 10, x) - self.assertRaises(DimensionalityError, op.sub, x, 10) - self.assertRaises(DimensionalityError, op.sub, x, z) + with pytest.raises(DimensionalityError): + op.sub(10, x) + with pytest.raises(DimensionalityError): + op.sub(x, 10) + with pytest.raises(DimensionalityError): + op.sub(x, z) def _test_quantity_iadd_isub(self, unit, func): x = self.Q_(unit, "centimeter") @@ -726,17 +742,23 @@ class TestQuantityBasicMath(QuantityTestCase): func(op.iadd, x, y, self.Q_(unit + 2.54 * unit, "centimeter")) func(op.iadd, y, x, self.Q_(unit + unit / 2.54, "inch")) func(op.iadd, a, unit, self.Q_(unit + unit, None)) - self.assertRaises(DimensionalityError, op.iadd, 10, x) - self.assertRaises(DimensionalityError, op.iadd, x, 10) - self.assertRaises(DimensionalityError, op.iadd, x, z) + with pytest.raises(DimensionalityError): + op.iadd(10, x) + with pytest.raises(DimensionalityError): + op.iadd(x, 10) + with pytest.raises(DimensionalityError): + op.iadd(x, z) func(op.isub, x, x, self.Q_(unit - unit, "centimeter")) func(op.isub, x, y, self.Q_(unit - 2.54, "centimeter")) func(op.isub, y, x, self.Q_(unit - unit / 2.54, "inch")) func(op.isub, a, unit, self.Q_(unit - unit, None)) - self.assertRaises(DimensionalityError, op.sub, 10, x) - self.assertRaises(DimensionalityError, op.sub, x, 10) - self.assertRaises(DimensionalityError, op.sub, x, z) + with pytest.raises(DimensionalityError): + op.sub(10, x) + with pytest.raises(DimensionalityError): + op.sub(x, 10) + with pytest.raises(DimensionalityError): + op.sub(x, z) def _test_quantity_mul_div(self, unit, func): func(op.mul, unit * 10.0, "4.2*meter", "42*meter", unit) @@ -757,24 +779,36 @@ class TestQuantityBasicMath(QuantityTestCase): def _test_quantity_floordiv(self, unit, func): a = self.Q_("10*meter") b = self.Q_("3*second") - self.assertRaises(DimensionalityError, op.floordiv, a, b) - self.assertRaises(DimensionalityError, op.floordiv, 3, b) - self.assertRaises(DimensionalityError, op.floordiv, a, 3) - self.assertRaises(DimensionalityError, op.ifloordiv, a, b) - self.assertRaises(DimensionalityError, op.ifloordiv, 3, b) - self.assertRaises(DimensionalityError, op.ifloordiv, a, 3) + with pytest.raises(DimensionalityError): + op.floordiv(a, b) + with pytest.raises(DimensionalityError): + op.floordiv(3, b) + with pytest.raises(DimensionalityError): + op.floordiv(a, 3) + with pytest.raises(DimensionalityError): + op.ifloordiv(a, b) + with pytest.raises(DimensionalityError): + op.ifloordiv(3, b) + with pytest.raises(DimensionalityError): + op.ifloordiv(a, 3) func(op.floordiv, unit * 10.0, "4.2*meter/meter", 2, unit) func(op.floordiv, "10*meter", "4.2*inch", 93, unit) def _test_quantity_mod(self, unit, func): a = self.Q_("10*meter") b = self.Q_("3*second") - self.assertRaises(DimensionalityError, op.mod, a, b) - self.assertRaises(DimensionalityError, op.mod, 3, b) - self.assertRaises(DimensionalityError, op.mod, a, 3) - self.assertRaises(DimensionalityError, op.imod, a, b) - self.assertRaises(DimensionalityError, op.imod, 3, b) - self.assertRaises(DimensionalityError, op.imod, a, 3) + with pytest.raises(DimensionalityError): + op.mod(a, b) + with pytest.raises(DimensionalityError): + op.mod(3, b) + with pytest.raises(DimensionalityError): + op.mod(a, 3) + with pytest.raises(DimensionalityError): + op.imod(a, b) + with pytest.raises(DimensionalityError): + op.imod(3, b) + with pytest.raises(DimensionalityError): + op.imod(a, 3) func(op.mod, unit * 10.0, "4.2*meter/meter", 1.6, unit) def _test_quantity_ifloordiv(self, unit, func): @@ -788,25 +822,25 @@ class TestQuantityBasicMath(QuantityTestCase): b = self.Q_(b) q, r = divmod(a, b) - self.assertEqual(q, a // b) - self.assertEqual(r, a % b) - self.assertEqual(a, (q * b) + r) - self.assertEqual(q, math.floor(q)) + assert q == a // b + assert r == a % b + assert a == (q * b) + r + assert q == math.floor(q) if b > (0 * b): - self.assertTrue((0 * b) <= r < b) + assert (0 * b) <= r < b else: - self.assertTrue((0 * b) >= r > b) + assert (0 * b) >= r > b if isinstance(a, self.Q_): - self.assertEqual(r.units, a.units) + assert r.units == a.units else: - self.assertTrue(r.unitless) - self.assertTrue(q.unitless) + assert r.unitless + assert q.unitless copy_a = copy.copy(a) a %= b - self.assertEqual(a, r) + assert a == r copy_a //= b - self.assertEqual(copy_a, q) + assert copy_a == q def _test_quantity_divmod(self): self._test_quantity_divmod_one("10*meter", "4.2*inch") @@ -822,9 +856,12 @@ class TestQuantityBasicMath(QuantityTestCase): a = self.Q_("10*meter") b = self.Q_("3*second") - self.assertRaises(DimensionalityError, divmod, a, b) - self.assertRaises(DimensionalityError, divmod, 3, b) - self.assertRaises(DimensionalityError, divmod, a, 3) + with pytest.raises(DimensionalityError): + divmod(a, b) + with pytest.raises(DimensionalityError): + divmod(3, b) + with pytest.raises(DimensionalityError): + divmod(a, 3) def _test_numeric(self, unit, ifunc): self._test_quantity_add_sub(unit, self._test_not_inplace) @@ -844,7 +881,7 @@ class TestQuantityBasicMath(QuantityTestCase): self._test_numeric(fractions.Fraction(1, 1), self._test_not_inplace) - @helpers.requires_numpy() + @helpers.requires_numpy def test_nparray(self): self._test_numeric(np.ones((1, 3)), self._test_inplace) @@ -858,176 +895,160 @@ class TestQuantityBasicMath(QuantityTestCase): zy = self.Q_(fun(y.magnitude), "meter") rx = fun(x) ry = fun(y) - self.assertEqual(rx, zx, "while testing {0}".format(fun)) - self.assertEqual(ry, zy, "while testing {0}".format(fun)) - self.assertIsNot(rx, zx, "while testing {0}".format(fun)) - self.assertIsNot(ry, zy, "while testing {0}".format(fun)) + assert rx == zx, "while testing {0}".format(fun) + assert ry == zy, "while testing {0}".format(fun) + assert rx is not zx, "while testing {0}".format(fun) + assert ry is not zy, "while testing {0}".format(fun) def test_quantity_float_complex(self): x = self.Q_(-4.2, None) y = self.Q_(4.2, None) z = self.Q_(1, "meter") for fun in (float, complex): - self.assertEqual(fun(x), fun(x.magnitude)) - self.assertEqual(fun(y), fun(y.magnitude)) - self.assertRaises(DimensionalityError, fun, z) + assert fun(x) == fun(x.magnitude) + assert fun(y) == fun(y.magnitude) + with pytest.raises(DimensionalityError): + fun(z) class TestQuantityNeutralAdd(QuantityTestCase): """Addition to zero or NaN is allowed between a Quantity and a non-Quantity""" - FORCE_NDARRAY = False - def test_bare_zero(self): v = self.Q_(2.0, "m") - self.assertEqual(v + 0, v) - self.assertEqual(v - 0, v) - self.assertEqual(0 + v, v) - self.assertEqual(0 - v, -v) + assert v + 0 == v + assert v - 0 == v + assert 0 + v == v + assert 0 - v == -v def test_bare_zero_inplace(self): v = self.Q_(2.0, "m") v2 = self.Q_(2.0, "m") v2 += 0 - self.assertEqual(v2, v) + assert v2 == v v2 = self.Q_(2.0, "m") v2 -= 0 - self.assertEqual(v2, v) + assert v2 == v v2 = 0 v2 += v - self.assertEqual(v2, v) + assert v2 == v v2 = 0 v2 -= v - self.assertEqual(v2, -v) + assert v2 == -v def test_bare_nan(self): v = self.Q_(2.0, "m") - self.assertQuantityEqual(v + math.nan, self.Q_(math.nan, v.units)) - self.assertQuantityEqual(v - math.nan, self.Q_(math.nan, v.units)) - self.assertQuantityEqual(math.nan + v, self.Q_(math.nan, v.units)) - self.assertQuantityEqual(math.nan - v, self.Q_(math.nan, v.units)) + helpers.assert_quantity_equal(v + math.nan, self.Q_(math.nan, v.units)) + helpers.assert_quantity_equal(v - math.nan, self.Q_(math.nan, v.units)) + helpers.assert_quantity_equal(math.nan + v, self.Q_(math.nan, v.units)) + helpers.assert_quantity_equal(math.nan - v, self.Q_(math.nan, v.units)) def test_bare_nan_inplace(self): v = self.Q_(2.0, "m") v2 = self.Q_(2.0, "m") v2 += math.nan - self.assertQuantityEqual(v2, self.Q_(math.nan, v.units)) + helpers.assert_quantity_equal(v2, self.Q_(math.nan, v.units)) v2 = self.Q_(2.0, "m") v2 -= math.nan - self.assertQuantityEqual(v2, self.Q_(math.nan, v.units)) + helpers.assert_quantity_equal(v2, self.Q_(math.nan, v.units)) v2 = math.nan v2 += v - self.assertQuantityEqual(v2, self.Q_(math.nan, v.units)) + helpers.assert_quantity_equal(v2, self.Q_(math.nan, v.units)) v2 = math.nan v2 -= v - self.assertQuantityEqual(v2, self.Q_(math.nan, v.units)) + helpers.assert_quantity_equal(v2, self.Q_(math.nan, v.units)) - @helpers.requires_numpy() + @helpers.requires_numpy def test_bare_zero_or_nan_numpy(self): z = np.array([0.0, np.nan]) v = self.Q_([1.0, 2.0], "m") e = self.Q_([1.0, np.nan], "m") - self.assertQuantityEqual(z + v, e) - self.assertQuantityEqual(z - v, -e) - self.assertQuantityEqual(v + z, e) - self.assertQuantityEqual(v - z, e) + helpers.assert_quantity_equal(z + v, e) + helpers.assert_quantity_equal(z - v, -e) + helpers.assert_quantity_equal(v + z, e) + helpers.assert_quantity_equal(v - z, e) # If any element is non-zero and non-NaN, raise DimensionalityError nz = np.array([0.0, 1.0]) - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): nz + v - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): nz - v - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): v + nz - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): v - nz # Mismatched shape z = np.array([0.0, np.nan, 0.0]) v = self.Q_([1.0, 2.0], "m") for x, y in ((z, v), (v, z)): - with self.assertRaises(ValueError): + with pytest.raises(ValueError): x + y - with self.assertRaises(ValueError): + with pytest.raises(ValueError): x - y - @helpers.requires_numpy() + @helpers.requires_numpy def test_bare_zero_or_nan_numpy_inplace(self): z = np.array([0.0, np.nan]) v = self.Q_([1.0, 2.0], "m") e = self.Q_([1.0, np.nan], "m") v += z - self.assertQuantityEqual(v, e) + helpers.assert_quantity_equal(v, e) v = self.Q_([1.0, 2.0], "m") v -= z - self.assertQuantityEqual(v, e) + helpers.assert_quantity_equal(v, e) v = self.Q_([1.0, 2.0], "m") z = np.array([0.0, np.nan]) z += v - self.assertQuantityEqual(z, e) + helpers.assert_quantity_equal(z, e) v = self.Q_([1.0, 2.0], "m") z = np.array([0.0, np.nan]) z -= v - self.assertQuantityEqual(z, -e) + helpers.assert_quantity_equal(z, -e) class TestDimensions(QuantityTestCase): - - FORCE_NDARRAY = False - def test_get_dimensionality(self): get = self.ureg.get_dimensionality - self.assertEqual(get("[time]"), UnitsContainer({"[time]": 1})) - self.assertEqual( - get(UnitsContainer({"[time]": 1})), UnitsContainer({"[time]": 1}) - ) - self.assertEqual(get("seconds"), UnitsContainer({"[time]": 1})) - self.assertEqual( - get(UnitsContainer({"seconds": 1})), UnitsContainer({"[time]": 1}) - ) - self.assertEqual(get("[speed]"), UnitsContainer({"[length]": 1, "[time]": -1})) - self.assertEqual( - get("[acceleration]"), UnitsContainer({"[length]": 1, "[time]": -2}) - ) + assert get("[time]") == UnitsContainer({"[time]": 1}) + assert get(UnitsContainer({"[time]": 1})) == UnitsContainer({"[time]": 1}) + assert get("seconds") == UnitsContainer({"[time]": 1}) + assert get(UnitsContainer({"seconds": 1})) == UnitsContainer({"[time]": 1}) + assert get("[speed]") == UnitsContainer({"[length]": 1, "[time]": -1}) + assert get("[acceleration]") == UnitsContainer({"[length]": 1, "[time]": -2}) def test_dimensionality(self): x = self.Q_(42, "centimeter") x.to_base_units() x = self.Q_(42, "meter*second") - self.assertEqual( - x.dimensionality, UnitsContainer({"[length]": 1.0, "[time]": 1.0}) - ) + assert x.dimensionality == UnitsContainer({"[length]": 1.0, "[time]": 1.0}) x = self.Q_(42, "meter*second*second") - self.assertEqual( - x.dimensionality, UnitsContainer({"[length]": 1.0, "[time]": 2.0}) - ) + assert x.dimensionality == UnitsContainer({"[length]": 1.0, "[time]": 2.0}) x = self.Q_(42, "inch*second*second") - self.assertEqual( - x.dimensionality, UnitsContainer({"[length]": 1.0, "[time]": 2.0}) - ) - self.assertTrue(self.Q_(42, None).dimensionless) - self.assertFalse(self.Q_(42, "meter").dimensionless) - self.assertTrue((self.Q_(42, "meter") / self.Q_(1, "meter")).dimensionless) - self.assertFalse((self.Q_(42, "meter") / self.Q_(1, "second")).dimensionless) - self.assertTrue((self.Q_(42, "meter") / self.Q_(1, "inch")).dimensionless) + assert x.dimensionality == UnitsContainer({"[length]": 1.0, "[time]": 2.0}) + assert self.Q_(42, None).dimensionless + assert not self.Q_(42, "meter").dimensionless + assert (self.Q_(42, "meter") / self.Q_(1, "meter")).dimensionless + assert not (self.Q_(42, "meter") / self.Q_(1, "second")).dimensionless + assert (self.Q_(42, "meter") / self.Q_(1, "inch")).dimensionless def test_inclusion(self): dim = self.Q_(42, "meter").dimensionality - self.assertTrue("[length]" in dim) - self.assertFalse("[time]" in dim) + assert "[length]" in dim + assert not ("[time]" in dim) dim = (self.Q_(42, "meter") / self.Q_(11, "second")).dimensionality - self.assertTrue("[length]" in dim) - self.assertTrue("[time]" in dim) + assert "[length]" in dim + assert "[time]" in dim dim = self.Q_(20.785, "J/(mol)").dimensionality for dimension in ("[length]", "[mass]", "[substance]", "[time]"): - self.assertTrue(dimension in dim) - self.assertFalse("[angle]" in dim) + assert dimension in dim + assert not ("[angle]" in dim) class TestQuantityWithDefaultRegistry(TestDimensions): @classmethod - def setUpClass(cls): + def setup_class(cls): from pint import _DEFAULT_REGISTRY cls.ureg = _DEFAULT_REGISTRY @@ -1036,17 +1057,19 @@ class TestQuantityWithDefaultRegistry(TestDimensions): class TestDimensionsWithDefaultRegistry(TestDimensions): @classmethod - def setUpClass(cls): + def setup_class(cls): from pint import _DEFAULT_REGISTRY cls.ureg = _DEFAULT_REGISTRY cls.Q_ = cls.ureg.Quantity -class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): - def setup(self): - self.ureg.autoconvert_offset_to_baseunit = False - self.ureg.default_as_delta = True +class TestOffsetUnitMath(QuantityTestCase): + @classmethod + def setup_class(cls): + super().setup_class() + cls.ureg.autoconvert_offset_to_baseunit = False + cls.ureg.default_as_delta = True additions = [ # --- input tuple -------------------- | -- expected result -- @@ -1088,7 +1111,7 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): (((100, "delta_degF"), (10, "delta_degF")), (110, "delta_degF")), ] - @ParameterizedTestCase.parameterize(("input", "expected_output"), additions) + @pytest.mark.parametrize(("input_tuple", "expected"), additions) def test_addition(self, input_tuple, expected): self.ureg.autoconvert_offset_to_baseunit = False qin1, qin2 = input_tuple @@ -1096,14 +1119,15 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): # update input tuple with new values to have correct values on failure input_tuple = q1, q2 if expected == "error": - self.assertRaises(OffsetUnitCalculusError, op.add, q1, q2) + with pytest.raises(OffsetUnitCalculusError): + op.add(q1, q2) else: expected = self.Q_(*expected) - self.assertEqual(op.add(q1, q2).units, expected.units) - self.assertQuantityAlmostEqual(op.add(q1, q2), expected, atol=0.01) + assert op.add(q1, q2).units == expected.units + helpers.assert_quantity_almost_equal(op.add(q1, q2), expected, atol=0.01) - @helpers.requires_numpy() - @ParameterizedTestCase.parameterize(("input", "expected_output"), additions) + @helpers.requires_numpy + @pytest.mark.parametrize(("input_tuple", "expected"), additions) def test_inplace_addition(self, input_tuple, expected): self.ureg.autoconvert_offset_to_baseunit = False (q1v, q1u), (q2v, q2u) = input_tuple @@ -1117,12 +1141,15 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): q1, q2 = Q_(*qin1), Q_(*qin2) q1_cp = copy.copy(q1) if expected == "error": - self.assertRaises(OffsetUnitCalculusError, op.iadd, q1_cp, q2) + with pytest.raises(OffsetUnitCalculusError): + op.iadd(q1_cp, q2) else: expected = np.array([expected[0]] * 2, dtype=np.float), expected[1] - self.assertEqual(op.iadd(q1_cp, q2).units, Q_(*expected).units) + assert op.iadd(q1_cp, q2).units == Q_(*expected).units q1_cp = copy.copy(q1) - self.assertQuantityAlmostEqual(op.iadd(q1_cp, q2), Q_(*expected), atol=0.01) + helpers.assert_quantity_almost_equal( + op.iadd(q1_cp, q2), Q_(*expected), atol=0.01 + ) subtractions = [ (((100, "kelvin"), (10, "kelvin")), (90, "kelvin")), @@ -1163,22 +1190,23 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): (((100, "delta_degF"), (10, "delta_degF")), (90, "delta_degF")), ] - @ParameterizedTestCase.parameterize(("input", "expected_output"), subtractions) + @pytest.mark.parametrize(("input_tuple", "expected"), subtractions) def test_subtraction(self, input_tuple, expected): self.ureg.autoconvert_offset_to_baseunit = False qin1, qin2 = input_tuple q1, q2 = self.Q_(*qin1), self.Q_(*qin2) input_tuple = q1, q2 if expected == "error": - self.assertRaises(OffsetUnitCalculusError, op.sub, q1, q2) + with pytest.raises(OffsetUnitCalculusError): + op.sub(q1, q2) else: expected = self.Q_(*expected) - self.assertEqual(op.sub(q1, q2).units, expected.units) - self.assertQuantityAlmostEqual(op.sub(q1, q2), expected, atol=0.01) + assert op.sub(q1, q2).units == expected.units + helpers.assert_quantity_almost_equal(op.sub(q1, q2), expected, atol=0.01) - # @unittest.expectedFailure - @helpers.requires_numpy() - @ParameterizedTestCase.parameterize(("input", "expected_output"), subtractions) + # @pytest.mark.xfail + @helpers.requires_numpy + @pytest.mark.parametrize(("input_tuple", "expected"), subtractions) def test_inplace_subtraction(self, input_tuple, expected): self.ureg.autoconvert_offset_to_baseunit = False (q1v, q1u), (q2v, q2u) = input_tuple @@ -1192,12 +1220,15 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): q1, q2 = Q_(*qin1), Q_(*qin2) q1_cp = copy.copy(q1) if expected == "error": - self.assertRaises(OffsetUnitCalculusError, op.isub, q1_cp, q2) + with pytest.raises(OffsetUnitCalculusError): + op.isub(q1_cp, q2) else: expected = np.array([expected[0]] * 2, dtype=np.float), expected[1] - self.assertEqual(op.isub(q1_cp, q2).units, Q_(*expected).units) + assert op.isub(q1_cp, q2).units == Q_(*expected).units q1_cp = copy.copy(q1) - self.assertQuantityAlmostEqual(op.isub(q1_cp, q2), Q_(*expected), atol=0.01) + helpers.assert_quantity_almost_equal( + op.isub(q1_cp, q2), Q_(*expected), atol=0.01 + ) multiplications = [ (((100, "kelvin"), (10, "kelvin")), (1000, "kelvin**2")), @@ -1238,21 +1269,22 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): (((100, "delta_degF"), (10, "delta_degF")), (1000, "delta_degF**2")), ] - @ParameterizedTestCase.parameterize(("input", "expected_output"), multiplications) + @pytest.mark.parametrize(("input_tuple", "expected"), multiplications) def test_multiplication(self, input_tuple, expected): self.ureg.autoconvert_offset_to_baseunit = False qin1, qin2 = input_tuple q1, q2 = self.Q_(*qin1), self.Q_(*qin2) input_tuple = q1, q2 if expected == "error": - self.assertRaises(OffsetUnitCalculusError, op.mul, q1, q2) + with pytest.raises(OffsetUnitCalculusError): + op.mul(q1, q2) else: expected = self.Q_(*expected) - self.assertEqual(op.mul(q1, q2).units, expected.units) - self.assertQuantityAlmostEqual(op.mul(q1, q2), expected, atol=0.01) + assert op.mul(q1, q2).units == expected.units + helpers.assert_quantity_almost_equal(op.mul(q1, q2), expected, atol=0.01) - @helpers.requires_numpy() - @ParameterizedTestCase.parameterize(("input", "expected_output"), multiplications) + @helpers.requires_numpy + @pytest.mark.parametrize(("input_tuple", "expected"), multiplications) def test_inplace_multiplication(self, input_tuple, expected): self.ureg.autoconvert_offset_to_baseunit = False (q1v, q1u), (q2v, q2u) = input_tuple @@ -1266,12 +1298,15 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): q1, q2 = Q_(*qin1), Q_(*qin2) q1_cp = copy.copy(q1) if expected == "error": - self.assertRaises(OffsetUnitCalculusError, op.imul, q1_cp, q2) + with pytest.raises(OffsetUnitCalculusError): + op.imul(q1_cp, q2) else: expected = np.array([expected[0]] * 2, dtype=np.float), expected[1] - self.assertEqual(op.imul(q1_cp, q2).units, Q_(*expected).units) + assert op.imul(q1_cp, q2).units == Q_(*expected).units q1_cp = copy.copy(q1) - self.assertQuantityAlmostEqual(op.imul(q1_cp, q2), Q_(*expected), atol=0.01) + helpers.assert_quantity_almost_equal( + op.imul(q1_cp, q2), Q_(*expected), atol=0.01 + ) divisions = [ (((100, "kelvin"), (10, "kelvin")), (10, "")), @@ -1312,21 +1347,24 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): (((100, "delta_degF"), (10, "delta_degF")), (10, "")), ] - @ParameterizedTestCase.parameterize(("input", "expected_output"), divisions) + @pytest.mark.parametrize(("input_tuple", "expected"), divisions) def test_truedivision(self, input_tuple, expected): self.ureg.autoconvert_offset_to_baseunit = False qin1, qin2 = input_tuple q1, q2 = self.Q_(*qin1), self.Q_(*qin2) input_tuple = q1, q2 if expected == "error": - self.assertRaises(OffsetUnitCalculusError, op.truediv, q1, q2) + with pytest.raises(OffsetUnitCalculusError): + op.truediv(q1, q2) else: expected = self.Q_(*expected) - self.assertEqual(op.truediv(q1, q2).units, expected.units) - self.assertQuantityAlmostEqual(op.truediv(q1, q2), expected, atol=0.01) + assert op.truediv(q1, q2).units == expected.units + helpers.assert_quantity_almost_equal( + op.truediv(q1, q2), expected, atol=0.01 + ) - @helpers.requires_numpy() - @ParameterizedTestCase.parameterize(("input", "expected_output"), divisions) + @helpers.requires_numpy + @pytest.mark.parametrize(("input_tuple", "expected"), divisions) def test_inplace_truedivision(self, input_tuple, expected): self.ureg.autoconvert_offset_to_baseunit = False (q1v, q1u), (q2v, q2u) = input_tuple @@ -1340,12 +1378,13 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): q1, q2 = Q_(*qin1), Q_(*qin2) q1_cp = copy.copy(q1) if expected == "error": - self.assertRaises(OffsetUnitCalculusError, op.itruediv, q1_cp, q2) + with pytest.raises(OffsetUnitCalculusError): + op.itruediv(q1_cp, q2) else: expected = np.array([expected[0]] * 2, dtype=np.float), expected[1] - self.assertEqual(op.itruediv(q1_cp, q2).units, Q_(*expected).units) + assert op.itruediv(q1_cp, q2).units == Q_(*expected).units q1_cp = copy.copy(q1) - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( op.itruediv(q1_cp, q2), Q_(*expected), atol=0.01 ) @@ -1372,8 +1411,8 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): (((100, "delta_degF"), (10, "degF")), (26092.78, "delta_degF*kelvin")), ] - @ParameterizedTestCase.parameterize( - ("input", "expected_output"), multiplications_with_autoconvert_to_baseunit + @pytest.mark.parametrize( + ("input_tuple", "expected"), multiplications_with_autoconvert_to_baseunit ) def test_multiplication_with_autoconvert(self, input_tuple, expected): self.ureg.autoconvert_offset_to_baseunit = True @@ -1381,15 +1420,16 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): q1, q2 = self.Q_(*qin1), self.Q_(*qin2) input_tuple = q1, q2 if expected == "error": - self.assertRaises(OffsetUnitCalculusError, op.mul, q1, q2) + with pytest.raises(OffsetUnitCalculusError): + op.mul(q1, q2) else: expected = self.Q_(*expected) - self.assertEqual(op.mul(q1, q2).units, expected.units) - self.assertQuantityAlmostEqual(op.mul(q1, q2), expected, atol=0.01) + assert op.mul(q1, q2).units == expected.units + helpers.assert_quantity_almost_equal(op.mul(q1, q2), expected, atol=0.01) - @helpers.requires_numpy() - @ParameterizedTestCase.parameterize( - ("input", "expected_output"), multiplications_with_autoconvert_to_baseunit + @helpers.requires_numpy + @pytest.mark.parametrize( + ("input_tuple", "expected"), multiplications_with_autoconvert_to_baseunit ) def test_inplace_multiplication_with_autoconvert(self, input_tuple, expected): self.ureg.autoconvert_offset_to_baseunit = True @@ -1404,12 +1444,15 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): q1, q2 = Q_(*qin1), Q_(*qin2) q1_cp = copy.copy(q1) if expected == "error": - self.assertRaises(OffsetUnitCalculusError, op.imul, q1_cp, q2) + with pytest.raises(OffsetUnitCalculusError): + op.imul(q1_cp, q2) else: expected = np.array([expected[0]] * 2, dtype=np.float), expected[1] - self.assertEqual(op.imul(q1_cp, q2).units, Q_(*expected).units) + assert op.imul(q1_cp, q2).units == Q_(*expected).units q1_cp = copy.copy(q1) - self.assertQuantityAlmostEqual(op.imul(q1_cp, q2), Q_(*expected), atol=0.01) + helpers.assert_quantity_almost_equal( + op.imul(q1_cp, q2), Q_(*expected), atol=0.01 + ) multiplications_with_scalar = [ (((10, "kelvin"), 2), (20.0, "kelvin")), @@ -1421,9 +1464,7 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): (((10, "degC**-2"), 2), "error"), ] - @ParameterizedTestCase.parameterize( - ("input", "expected_output"), multiplications_with_scalar - ) + @pytest.mark.parametrize(("input_tuple", "expected"), multiplications_with_scalar) def test_multiplication_with_scalar(self, input_tuple, expected): self.ureg.default_as_delta = False in1, in2 = input_tuple @@ -1433,11 +1474,12 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): in1, in2 = in1, self.Q_(*in2) input_tuple = in1, in2 # update input_tuple for better tracebacks if expected == "error": - self.assertRaises(OffsetUnitCalculusError, op.mul, in1, in2) + with pytest.raises(OffsetUnitCalculusError): + op.mul(in1, in2) else: expected = self.Q_(*expected) - self.assertEqual(op.mul(in1, in2).units, expected.units) - self.assertQuantityAlmostEqual(op.mul(in1, in2), expected, atol=0.01) + assert op.mul(in1, in2).units == expected.units + helpers.assert_quantity_almost_equal(op.mul(in1, in2), expected, atol=0.01) divisions_with_scalar = [ # without / with autoconvert to base unit (((10, "kelvin"), 2), [(5.0, "kelvin"), (5.0, "kelvin")]), @@ -1451,9 +1493,7 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): ((2, (10, "degC**-2")), ["error", "error"]), ] - @ParameterizedTestCase.parameterize( - ("input", "expected_output"), divisions_with_scalar - ) + @pytest.mark.parametrize(("input_tuple", "expected"), divisions_with_scalar) def test_division_with_scalar(self, input_tuple, expected): self.ureg.default_as_delta = False in1, in2 = input_tuple @@ -1466,11 +1506,12 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): for i, mode in enumerate([False, True]): self.ureg.autoconvert_offset_to_baseunit = mode if expected_copy[i] == "error": - self.assertRaises(OffsetUnitCalculusError, op.truediv, in1, in2) + with pytest.raises(OffsetUnitCalculusError): + op.truediv(in1, in2) else: expected = self.Q_(*expected_copy[i]) - self.assertEqual(op.truediv(in1, in2).units, expected.units) - self.assertQuantityAlmostEqual(op.truediv(in1, in2), expected) + assert op.truediv(in1, in2).units == expected.units + helpers.assert_quantity_almost_equal(op.truediv(in1, in2), expected) exponentiation = [ # resuls without / with autoconvert (((10, "degC"), 1), [(10, "degC"), (10, "degC")]), @@ -1491,7 +1532,7 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): ), ] - @ParameterizedTestCase.parameterize(("input", "expected_output"), exponentiation) + @pytest.mark.parametrize(("input_tuple", "expected"), exponentiation) def test_exponentiation(self, input_tuple, expected): self.ureg.default_as_delta = False in1, in2 = input_tuple @@ -1506,19 +1547,18 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): for i, mode in enumerate([False, True]): self.ureg.autoconvert_offset_to_baseunit = mode if expected_copy[i] == "error": - self.assertRaises( - (OffsetUnitCalculusError, DimensionalityError), op.pow, in1, in2 - ) + with pytest.raises((OffsetUnitCalculusError, DimensionalityError)): + op.pow(in1, in2) else: if type(expected_copy[i]) is tuple: expected = self.Q_(*expected_copy[i]) - self.assertEqual(op.pow(in1, in2).units, expected.units) + assert op.pow(in1, in2).units == expected.units else: expected = expected_copy[i] - self.assertQuantityAlmostEqual(op.pow(in1, in2), expected) + helpers.assert_quantity_almost_equal(op.pow(in1, in2), expected) - @helpers.requires_numpy() - @ParameterizedTestCase.parameterize(("input", "expected_output"), exponentiation) + @helpers.requires_numpy + @pytest.mark.parametrize(("input_tuple", "expected"), exponentiation) def test_inplace_exponentiation(self, input_tuple, expected): self.ureg.default_as_delta = False in1, in2 = input_tuple @@ -1538,21 +1578,20 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): self.ureg.autoconvert_offset_to_baseunit = mode in1_cp = copy.copy(in1) if expected_copy[i] == "error": - self.assertRaises( - (OffsetUnitCalculusError, DimensionalityError), op.ipow, in1_cp, in2 - ) + with pytest.raises((OffsetUnitCalculusError, DimensionalityError)): + op.ipow(in1_cp, in2) else: if type(expected_copy[i]) is tuple: expected = self.Q_( np.array([expected_copy[i][0]] * 2, dtype=np.float), expected_copy[i][1], ) - self.assertEqual(op.ipow(in1_cp, in2).units, expected.units) + assert op.ipow(in1_cp, in2).units == expected.units else: expected = np.array([expected_copy[i]] * 2, dtype=np.float) in1_cp = copy.copy(in1) - self.assertQuantityAlmostEqual(op.ipow(in1_cp, in2), expected) + helpers.assert_quantity_almost_equal(op.ipow(in1_cp, in2), expected) # matmul is only a ufunc since 1.16 @helpers.requires_numpy_at_least("1.16") @@ -1560,12 +1599,12 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase): A = [[1, 2], [3, 4]] * self.ureg.m B = np.array([[0, -1], [-1, 0]]) b = [[1], [0]] * self.ureg.m - self.assertQuantityEqual(A @ B, [[-2, -1], [-4, -3]] * self.ureg.m) - self.assertQuantityEqual(A @ b, [[1], [3]] * self.ureg.m ** 2) - self.assertQuantityEqual(B @ b, [[0], [-1]] * self.ureg.m) + helpers.assert_quantity_equal(A @ B, [[-2, -1], [-4, -3]] * self.ureg.m) + helpers.assert_quantity_equal(A @ b, [[1], [3]] * self.ureg.m ** 2) + helpers.assert_quantity_equal(B @ b, [[0], [-1]] * self.ureg.m) -class TestDimensionReduction(QuantityTestCase): +class TestDimensionReduction: def _calc_mass(self, ureg): density = 3 * ureg.g / ureg.L volume = 32 * ureg.milliliter @@ -1579,59 +1618,59 @@ class TestDimensionReduction(QuantityTestCase): def test_mul_and_div_reduction(self): ureg = UnitRegistry(auto_reduce_dimensions=True) mass = self._calc_mass(ureg) - self.assertEqual(mass.units, ureg.g) + assert mass.units == ureg.g ureg = UnitRegistry(auto_reduce_dimensions=False) mass = self._calc_mass(ureg) - self.assertEqual(mass.units, ureg.g / ureg.L * ureg.milliliter) + assert mass.units == ureg.g / ureg.L * ureg.milliliter - @helpers.requires_numpy() + @helpers.requires_numpy def test_imul_and_div_reduction(self): ureg = UnitRegistry(auto_reduce_dimensions=True, force_ndarray=True) mass = self._icalc_mass(ureg) - self.assertEqual(mass.units, ureg.g) + assert mass.units == ureg.g ureg = UnitRegistry(auto_reduce_dimensions=False, force_ndarray=True) mass = self._icalc_mass(ureg) - self.assertEqual(mass.units, ureg.g / ureg.L * ureg.milliliter) + assert mass.units == ureg.g / ureg.L * ureg.milliliter def test_reduction_to_dimensionless(self): ureg = UnitRegistry(auto_reduce_dimensions=True) x = (10 * ureg.feet) / (3 * ureg.inches) - self.assertEqual(x.units, UnitsContainer({})) + assert x.units == UnitsContainer({}) ureg = UnitRegistry(auto_reduce_dimensions=False) x = (10 * ureg.feet) / (3 * ureg.inches) - self.assertEqual(x.units, ureg.feet / ureg.inches) + assert x.units == ureg.feet / ureg.inches def test_nocoerce_creation(self): ureg = UnitRegistry(auto_reduce_dimensions=True) x = 1 * ureg.foot - self.assertEqual(x.units, ureg.foot) + assert x.units == ureg.foot class TestTimedelta(QuantityTestCase): def test_add_sub(self): d = datetime.datetime(year=1968, month=1, day=10, hour=3, minute=42, second=24) after = d + 3 * self.ureg.second - self.assertEqual(d + datetime.timedelta(seconds=3), after) + assert d + datetime.timedelta(seconds=3) == after after = 3 * self.ureg.second + d - self.assertEqual(d + datetime.timedelta(seconds=3), after) + assert d + datetime.timedelta(seconds=3) == after after = d - 3 * self.ureg.second - self.assertEqual(d - datetime.timedelta(seconds=3), after) - with self.assertRaises(DimensionalityError): + assert d - datetime.timedelta(seconds=3) == after + with pytest.raises(DimensionalityError): 3 * self.ureg.second - d def test_iadd_isub(self): d = datetime.datetime(year=1968, month=1, day=10, hour=3, minute=42, second=24) after = copy.copy(d) after += 3 * self.ureg.second - self.assertEqual(d + datetime.timedelta(seconds=3), after) + assert d + datetime.timedelta(seconds=3) == after after = 3 * self.ureg.second after += d - self.assertEqual(d + datetime.timedelta(seconds=3), after) + assert d + datetime.timedelta(seconds=3) == after after = copy.copy(d) after -= 3 * self.ureg.second - self.assertEqual(d - datetime.timedelta(seconds=3), after) + assert d - datetime.timedelta(seconds=3) == after after = 3 * self.ureg.second - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): after -= d @@ -1642,19 +1681,19 @@ class TestCompareNeutral(QuantityTestCase): def test_equal_zero(self): self.ureg.autoconvert_offset_to_baseunit = False - self.assertTrue(self.Q_(0, "J") == 0) - self.assertFalse(self.Q_(0, "J") == self.Q_(0, "")) - self.assertFalse(self.Q_(5, "J") == 0) + assert self.Q_(0, "J") == 0 + assert not (self.Q_(0, "J") == self.Q_(0, "")) + assert not (self.Q_(5, "J") == 0) def test_equal_nan(self): # nan == nan returns False self.ureg.autoconvert_offset_to_baseunit = False - self.assertFalse(self.Q_(math.nan, "J") == 0) - self.assertFalse(self.Q_(math.nan, "J") == math.nan) - self.assertFalse(self.Q_(math.nan, "J") == self.Q_(math.nan, "")) - self.assertFalse(self.Q_(5, "J") == math.nan) + assert not (self.Q_(math.nan, "J") == 0) + assert not (self.Q_(math.nan, "J") == math.nan) + assert not (self.Q_(math.nan, "J") == self.Q_(math.nan, "")) + assert not (self.Q_(5, "J") == math.nan) - @helpers.requires_numpy() + @helpers.requires_numpy def test_equal_zero_nan_NP(self): self.ureg.autoconvert_offset_to_baseunit = False aeq = np.testing.assert_array_equal @@ -1664,7 +1703,7 @@ class TestCompareNeutral(QuantityTestCase): self.Q_([0, 1, 2], "J") == np.array([0, 0, np.nan]), np.asarray([True, False, False]), ) - self.assertFalse(self.Q_(np.arange(4), "J") == np.zeros(3)) + assert not (self.Q_(np.arange(4), "J") == np.zeros(3)) def test_offset_equal_zero(self): ureg = self.ureg @@ -1672,10 +1711,13 @@ class TestCompareNeutral(QuantityTestCase): q0 = ureg.Quantity(-273.15, "degC") q1 = ureg.Quantity(0, "degC") q2 = ureg.Quantity(5, "degC") - self.assertRaises(OffsetUnitCalculusError, q0.__eq__, 0) - self.assertRaises(OffsetUnitCalculusError, q1.__eq__, 0) - self.assertRaises(OffsetUnitCalculusError, q2.__eq__, 0) - self.assertFalse(q0 == ureg.Quantity(0, "")) + with pytest.raises(OffsetUnitCalculusError): + q0.__eq__(0) + with pytest.raises(OffsetUnitCalculusError): + q1.__eq__(0) + with pytest.raises(OffsetUnitCalculusError): + q2.__eq__(0) + assert not (q0 == ureg.Quantity(0, "")) def test_offset_autoconvert_equal_zero(self): ureg = self.ureg @@ -1683,10 +1725,10 @@ class TestCompareNeutral(QuantityTestCase): q0 = ureg.Quantity(-273.15, "degC") q1 = ureg.Quantity(0, "degC") q2 = ureg.Quantity(5, "degC") - self.assertTrue(q0 == 0) - self.assertFalse(q1 == 0) - self.assertFalse(q2 == 0) - self.assertFalse(q0 == ureg.Quantity(0, "")) + assert q0 == 0 + assert not (q1 == 0) + assert not (q2 == 0) + assert not (q0 == ureg.Quantity(0, "")) def test_gt_zero(self): self.ureg.autoconvert_offset_to_baseunit = False @@ -1695,12 +1737,12 @@ class TestCompareNeutral(QuantityTestCase): q0less = self.Q_(0, "") qpos = self.Q_(5, "J") qneg = self.Q_(-5, "J") - self.assertTrue(qpos > q0) - self.assertTrue(qpos > 0) - self.assertFalse(qneg > 0) - with self.assertRaises(DimensionalityError): + assert qpos > q0 + assert qpos > 0 + assert not (qneg > 0) + with pytest.raises(DimensionalityError): qpos > q0less - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): qpos > q0m def test_gt_nan(self): @@ -1709,14 +1751,14 @@ class TestCompareNeutral(QuantityTestCase): qnm = self.Q_(math.nan, "m") qnless = self.Q_(math.nan, "") qpos = self.Q_(5, "J") - self.assertFalse(qpos > qn) - self.assertFalse(qpos > math.nan) - with self.assertRaises(DimensionalityError): + assert not (qpos > qn) + assert not (qpos > math.nan) + with pytest.raises(DimensionalityError): qpos > qnless - with self.assertRaises(DimensionalityError): + with pytest.raises(DimensionalityError): qpos > qnm - @helpers.requires_numpy() + @helpers.requires_numpy def test_gt_zero_nan_NP(self): self.ureg.autoconvert_offset_to_baseunit = False qpos = self.Q_(5, "J") @@ -1728,7 +1770,7 @@ class TestCompareNeutral(QuantityTestCase): self.Q_(np.arange(-2, 3), "J") > np.array([np.nan, 0, 0, 0, np.nan]), np.asarray([False, False, False, True, False]), ) - with self.assertRaises(ValueError): + with pytest.raises(ValueError): self.Q_(np.arange(-1, 2), "J") > np.zeros(4) def test_offset_gt_zero(self): @@ -1737,10 +1779,14 @@ class TestCompareNeutral(QuantityTestCase): q0 = ureg.Quantity(-273.15, "degC") q1 = ureg.Quantity(0, "degC") q2 = ureg.Quantity(5, "degC") - self.assertRaises(OffsetUnitCalculusError, q0.__gt__, 0) - self.assertRaises(OffsetUnitCalculusError, q1.__gt__, 0) - self.assertRaises(OffsetUnitCalculusError, q2.__gt__, 0) - self.assertRaises(DimensionalityError, q1.__gt__, ureg.Quantity(0, "")) + with pytest.raises(OffsetUnitCalculusError): + q0.__gt__(0) + with pytest.raises(OffsetUnitCalculusError): + q1.__gt__(0) + with pytest.raises(OffsetUnitCalculusError): + q2.__gt__(0) + with pytest.raises(DimensionalityError): + q1.__gt__(ureg.Quantity(0, "")) def test_offset_autoconvert_gt_zero(self): ureg = self.ureg @@ -1748,7 +1794,8 @@ class TestCompareNeutral(QuantityTestCase): q0 = ureg.Quantity(-273.15, "degC") q1 = ureg.Quantity(0, "degC") q2 = ureg.Quantity(5, "degC") - self.assertFalse(q0 > 0) - self.assertTrue(q1 > 0) - self.assertTrue(q2 > 0) - self.assertRaises(DimensionalityError, q1.__gt__, ureg.Quantity(0, "")) + assert not (q0 > 0) + assert q1 > 0 + assert q2 > 0 + with pytest.raises(DimensionalityError): + q1.__gt__(ureg.Quantity(0, "")) diff --git a/pint/testsuite/test_systems.py b/pint/testsuite/test_systems.py index ffe084d..92d77a9 100644 --- a/pint/testsuite/test_systems.py +++ b/pint/testsuite/test_systems.py @@ -1,8 +1,10 @@ +import pytest + from pint import UnitRegistry from pint.testsuite import QuantityTestCase -class TestGroup(QuantityTestCase): +class TestGroup: def _build_empty_reg_root(self): ureg = UnitRegistry(None) grp = ureg.get_group("root") @@ -13,13 +15,13 @@ class TestGroup(QuantityTestCase): ureg, root = self._build_empty_reg_root() d = ureg._groups - self.assertEqual(root._used_groups, set()) - self.assertEqual(root._used_by, set()) + assert root._used_groups == set() + assert root._used_by == set() root.add_units("meter", "second", "meter") - self.assertEqual(root._unit_names, {"meter", "second"}) - self.assertEqual(root.members, {"meter", "second"}) + assert root._unit_names == {"meter", "second"} + assert root.members == {"meter", "second"} - self.assertEqual(d.keys(), {"root"}) + assert d.keys() == {"root"} def test_cyclic(self): ureg, root = self._build_empty_reg_root() @@ -27,22 +29,25 @@ class TestGroup(QuantityTestCase): g3 = ureg.Group("g3") g2.add_groups("g3") - self.assertRaises(ValueError, g2.add_groups, "root") - self.assertRaises(ValueError, g3.add_groups, "g2") - self.assertRaises(ValueError, g3.add_groups, "root") + with pytest.raises(ValueError): + g2.add_groups("root") + with pytest.raises(ValueError): + g3.add_groups("g2") + with pytest.raises(ValueError): + g3.add_groups("root") def test_groups_programatically(self): ureg, root = self._build_empty_reg_root() d = ureg._groups g2 = ureg.Group("g2") - self.assertEqual(d.keys(), {"root", "g2"}) + assert d.keys() == {"root", "g2"} - self.assertEqual(root._used_groups, {"g2"}) - self.assertEqual(root._used_by, set()) + assert root._used_groups == {"g2"} + assert root._used_by == set() - self.assertEqual(g2._used_groups, set()) - self.assertEqual(g2._used_by, {"root"}) + assert g2._used_groups == set() + assert g2._used_by == {"root"} def test_simple(self): lines = ["@group mygroup", "meter", "second"] @@ -52,13 +57,13 @@ class TestGroup(QuantityTestCase): grp = ureg.Group.from_lines(lines, lambda x: None) - self.assertEqual(d.keys(), {"root", "mygroup"}) + assert d.keys() == {"root", "mygroup"} - self.assertEqual(grp.name, "mygroup") - self.assertEqual(grp._unit_names, {"meter", "second"}) - self.assertEqual(grp._used_groups, set()) - self.assertEqual(grp._used_by, {root.name}) - self.assertEqual(grp.members, frozenset(["meter", "second"])) + assert grp.name == "mygroup" + assert grp._unit_names == {"meter", "second"} + assert grp._used_groups == set() + assert grp._used_by == {root.name} + assert grp.members == frozenset(["meter", "second"]) def test_using1(self): lines = ["@group mygroup using group1", "meter", "second"] @@ -66,10 +71,10 @@ class TestGroup(QuantityTestCase): ureg, root = self._build_empty_reg_root() ureg.Group("group1") grp = ureg.Group.from_lines(lines, lambda x: None) - self.assertEqual(grp.name, "mygroup") - self.assertEqual(grp._unit_names, {"meter", "second"}) - self.assertEqual(grp._used_groups, {"group1"}) - self.assertEqual(grp.members, frozenset(["meter", "second"])) + assert grp.name == "mygroup" + assert grp._unit_names == {"meter", "second"} + assert grp._used_groups == {"group1"} + assert grp.members == frozenset(["meter", "second"]) def test_using2(self): lines = ["@group mygroup using group1,group2", "meter", "second"] @@ -78,10 +83,10 @@ class TestGroup(QuantityTestCase): ureg.Group("group1") ureg.Group("group2") grp = ureg.Group.from_lines(lines, lambda x: None) - self.assertEqual(grp.name, "mygroup") - self.assertEqual(grp._unit_names, {"meter", "second"}) - self.assertEqual(grp._used_groups, {"group1", "group2"}) - self.assertEqual(grp.members, frozenset(["meter", "second"])) + assert grp.name == "mygroup" + assert grp._unit_names == {"meter", "second"} + assert grp._used_groups == {"group1", "group2"} + assert grp.members == frozenset(["meter", "second"]) def test_spaces(self): lines = ["@group mygroup using group1 , group2", " meter ", " second "] @@ -90,10 +95,10 @@ class TestGroup(QuantityTestCase): ureg.Group("group1") ureg.Group("group2") grp = ureg.Group.from_lines(lines, lambda x: None) - self.assertEqual(grp.name, "mygroup") - self.assertEqual(grp._unit_names, {"meter", "second"}) - self.assertEqual(grp._used_groups, {"group1", "group2"}) - self.assertEqual(grp.members, frozenset(["meter", "second"])) + assert grp.name == "mygroup" + assert grp._unit_names == {"meter", "second"} + assert grp._used_groups == {"group1", "group2"} + assert grp.members == frozenset(["meter", "second"]) def test_invalidate_members(self): lines = ["@group mygroup using group1", "meter", "second"] @@ -101,17 +106,17 @@ class TestGroup(QuantityTestCase): ureg, root = self._build_empty_reg_root() ureg.Group("group1") grp = ureg.Group.from_lines(lines, lambda x: None) - self.assertIs(root._computed_members, None) - self.assertIs(grp._computed_members, None) - self.assertEqual(grp.members, frozenset(["meter", "second"])) - self.assertIs(root._computed_members, None) - self.assertIsNot(grp._computed_members, None) - self.assertEqual(root.members, frozenset(["meter", "second"])) - self.assertIsNot(root._computed_members, None) - self.assertIsNot(grp._computed_members, None) + assert root._computed_members is None + assert grp._computed_members is None + assert grp.members == frozenset(["meter", "second"]) + assert root._computed_members is None + assert grp._computed_members is not None + assert root.members == frozenset(["meter", "second"]) + assert root._computed_members is not None + assert grp._computed_members is not None grp.invalidate_members() - self.assertIs(root._computed_members, None) - self.assertIs(grp._computed_members, None) + assert root._computed_members is None + assert grp._computed_members is None def test_with_defintions(self): lines = [ @@ -129,7 +134,7 @@ class TestGroup(QuantityTestCase): ureg, root = self._build_empty_reg_root() ureg.Group.from_lines(lines, define) - self.assertEqual(["kings_leg", "kings_head"], defs) + assert ["kings_leg", "kings_head"] == defs def test_members_including(self): ureg, root = self._build_empty_reg_root() @@ -144,10 +149,10 @@ class TestGroup(QuantityTestCase): g3.add_units("meter", "second") g3.add_groups("group1", "group2") - self.assertEqual(root.members, frozenset(["meter", "second", "newton", "inch"])) - self.assertEqual(g1.members, frozenset(["second", "inch"])) - self.assertEqual(g2.members, frozenset(["second", "newton"])) - self.assertEqual(g3.members, frozenset(["meter", "second", "newton", "inch"])) + assert root.members == frozenset(["meter", "second", "newton", "inch"]) + assert g1.members == frozenset(["second", "inch"]) + assert g2.members == frozenset(["second", "newton"]) + assert g3.members == frozenset(["meter", "second", "newton", "inch"]) def test_get_compatible_units(self): ureg = UnitRegistry() @@ -155,7 +160,7 @@ class TestGroup(QuantityTestCase): g = ureg.get_group("test-imperial") g.add_units("inch", "yard", "pint") c = ureg.get_compatible_units("meter", "test-imperial") - self.assertEqual(c, frozenset([ureg.inch, ureg.yard])) + assert c == frozenset([ureg.inch, ureg.yard]) class TestSystem(QuantityTestCase): @@ -185,7 +190,7 @@ class TestSystem(QuantityTestCase): ureg, root = self._build_empty_reg_root() root.add_units("second") s = ureg.System.from_lines(lines, lambda x: x) - self.assertEqual(s.members, frozenset(["second"])) + assert s.members == frozenset(["second"]) def test_get_compatible_units(self): sysname = "mysys1" @@ -195,13 +200,13 @@ class TestSystem(QuantityTestCase): g.add_units("inch", "yard", "pint") c = ureg.get_compatible_units("meter", "test-imperial") - self.assertEqual(c, frozenset([ureg.inch, ureg.yard])) + assert c == frozenset([ureg.inch, ureg.yard]) lines = ["@system %s using test-imperial" % sysname, "inch"] ureg.System.from_lines(lines, lambda x: x) c = ureg.get_compatible_units("meter", sysname) - self.assertEqual(c, frozenset([ureg.inch, ureg.yard])) + assert c == frozenset([ureg.inch, ureg.yard]) def test_get_base_units(self): sysname = "mysys2" @@ -217,12 +222,12 @@ class TestSystem(QuantityTestCase): # base_factor, destination_units c = ureg.get_base_units("inch", system=sysname) - self.assertAlmostEqual(c[0], 1) - self.assertEqual(c[1], {"inch": 1}) + assert round(abs(c[0] - 1), 7) == 0 + assert c[1] == {"inch": 1} c = ureg.get_base_units("cm", system=sysname) - self.assertAlmostEqual(c[0], 1.0 / 2.54) - self.assertEqual(c[1], {"inch": 1}) + assert round(abs(c[0] - 1.0 / 2.54), 7) == 0 + assert c[1] == {"inch": 1} def test_get_base_units_different_exponent(self): sysname = "mysys3" @@ -239,20 +244,20 @@ class TestSystem(QuantityTestCase): # base_factor, destination_units c = ureg.get_base_units("inch", system=sysname) - self.assertAlmostEqual(c[0], 0.326, places=3) - self.assertEqual(c[1], {"pint": 1.0 / 3}) + assert round(abs(c[0] - 0.326), 3) == 0 + assert c[1] == {"pint": 1.0 / 3} c = ureg.get_base_units("cm", system=sysname) - self.assertAlmostEqual(c[0], 0.1283, places=3) - self.assertEqual(c[1], {"pint": 1.0 / 3}) + assert round(abs(c[0] - 0.1283), 3) == 0 + assert c[1] == {"pint": 1.0 / 3} c = ureg.get_base_units("inch**2", system=sysname) - self.assertAlmostEqual(c[0], 0.326 ** 2, places=3) - self.assertEqual(c[1], {"pint": 2.0 / 3}) + assert round(abs(c[0] - 0.326 ** 2), 3) == 0 + assert c[1] == {"pint": 2.0 / 3} c = ureg.get_base_units("cm**2", system=sysname) - self.assertAlmostEqual(c[0], 0.1283 ** 2, places=3) - self.assertEqual(c[1], {"pint": 2.0 / 3}) + assert round(abs(c[0] - 0.1283 ** 2), 3) == 0 + assert c[1] == {"pint": 2.0 / 3} def test_get_base_units_relation(self): sysname = "mysys4" @@ -267,12 +272,12 @@ class TestSystem(QuantityTestCase): ureg._systems[s.name] = s # base_factor, destination_units c = ureg.get_base_units("inch", system=sysname) - self.assertAlmostEqual(c[0], 0.056, places=2) - self.assertEqual(c[1], {"mph": 1, "second": 1}) + assert round(abs(c[0] - 0.056), 2) == 0 + assert c[1] == {"mph": 1, "second": 1} c = ureg.get_base_units("kph", system=sysname) - self.assertAlmostEqual(c[0], 0.6213, places=3) - self.assertEqual(c[1], {"mph": 1}) + assert round(abs(c[0] - 0.6213), 3) == 0 + assert c[1] == {"mph": 1} def test_members_nowarning(self): ureg = self.ureg diff --git a/pint/testsuite/test_umath.py b/pint/testsuite/test_umath.py index e11f7d8..bc2db9b 100644 --- a/pint/testsuite/test_umath.py +++ b/pint/testsuite/test_umath.py @@ -1,6 +1,8 @@ -from pint import DimensionalityError +import pytest + +from pint import DimensionalityError, UnitRegistry from pint.compat import np -from pint.testsuite import QuantityTestCase, helpers +from pint.testsuite import helpers # Following http://docs.scipy.org/doc/numpy/reference/ufuncs.html @@ -8,10 +10,17 @@ if np: pi = np.pi -@helpers.requires_numpy() -class TestUFuncs(QuantityTestCase): +@helpers.requires_numpy +class TestUFuncs: + @classmethod + def setup_class(cls): + cls.ureg = UnitRegistry(force_ndarray=True) + cls.Q_ = cls.ureg.Quantity - FORCE_NDARRAY = True + @classmethod + def teardown_class(cls): + cls.ureg = None + cls.Q_ = None @property def qless(self): @@ -84,12 +93,10 @@ class TestUFuncs(QuantityTestCase): if ou is not None: res = self.Q_(res, ou) - self.assertQuantityAlmostEqual(qm, res, rtol=rtol, msg=err_msg) + helpers.assert_quantity_almost_equal(qm, res, rtol=rtol, msg=err_msg) for x1 in raise_with: - with self.assertRaises( - DimensionalityError, msg=f"At {func.__name__} with {x1}" - ): + with pytest.raises(DimensionalityError): func(x1) def _testn(self, func, ok_with, raise_with=(), results=None): @@ -170,10 +177,10 @@ class TestUFuncs(QuantityTestCase): if ou is not None: re = self.Q_(re, ou) - self.assertQuantityAlmostEqual(qm, re, rtol=rtol, msg=err_msg) + helpers.assert_quantity_almost_equal(qm, re, rtol=rtol, msg=err_msg) for x1 in raise_with: - with self.assertRaises(ValueError, msg=f"At {func.__name__} with {x1}"): + with pytest.raises(ValueError): func(x1) def _test2( @@ -239,12 +246,10 @@ class TestUFuncs(QuantityTestCase): if ou is not None: res = self.Q_(res, ou) - self.assertQuantityAlmostEqual(qm, res, rtol=rtol, msg=err_msg) + helpers.assert_quantity_almost_equal(qm, res, rtol=rtol, msg=err_msg) for x2 in raise_with: - with self.assertRaises( - DimensionalityError, msg=f"At {func.__name__} with {x1} and {x2}" - ): + with pytest.raises(DimensionalityError): func(x1, x2) def _testn2(self, func, x1, ok_with, raise_with=()): @@ -268,7 +273,7 @@ class TestUFuncs(QuantityTestCase): self._test2(func, x1, ok_with, raise_with, output_units=None) -@helpers.requires_numpy() +@helpers.requires_numpy class TestMathUfuncs(TestUFuncs): """Universal functions (ufunc) > Math operations @@ -416,7 +421,7 @@ class TestMathUfuncs(TestUFuncs): self._test1(np.reciprocal, (self.q2, self.qs, self.qless, self.qi), (), -1) -@helpers.requires_numpy() +@helpers.requires_numpy class TestTrigUfuncs(TestUFuncs): """Universal functions (ufunc) > Trigonometric functions @@ -552,13 +557,9 @@ class TestTrigUfuncs(TestUFuncs): ) def test_hypot(self): - self.assertTrue( - np.hypot(3.0 * self.ureg.m, 4.0 * self.ureg.m) == 5.0 * self.ureg.m - ) - self.assertTrue( - np.hypot(3.0 * self.ureg.m, 400.0 * self.ureg.cm) == 5.0 * self.ureg.m - ) - with self.assertRaises(DimensionalityError): + assert np.hypot(3.0 * self.ureg.m, 4.0 * self.ureg.m) == 5.0 * self.ureg.m + assert np.hypot(3.0 * self.ureg.m, 400.0 * self.ureg.cm) == 5.0 * self.ureg.m + with pytest.raises(DimensionalityError): np.hypot(1.0 * self.ureg.m, 2.0 * self.ureg.J) def test_sinh(self): diff --git a/pint/testsuite/test_unit.py b/pint/testsuite/test_unit.py index dcb3e97..c729333 100644 --- a/pint/testsuite/test_unit.py +++ b/pint/testsuite/test_unit.py @@ -1,8 +1,11 @@ import copy import functools +import logging import math import re +import pytest + from pint import ( DefinitionSyntaxError, DimensionalityError, @@ -11,27 +14,27 @@ from pint import ( ) from pint.compat import np from pint.registry import LazyRegistry, UnitRegistry -from pint.testsuite import CaseInsensitveQuantityTestCase, QuantityTestCase, helpers -from pint.testsuite.parameterized import ParameterizedTestCase +from pint.testsuite import QuantityTestCase, helpers from pint.util import ParserHelper, UnitsContainer class TestUnit(QuantityTestCase): def test_creation(self): for arg in ("meter", UnitsContainer(meter=1), self.U_("m")): - self.assertEqual(self.U_(arg)._units, UnitsContainer(meter=1)) - self.assertRaises(TypeError, self.U_, 1) + assert self.U_(arg)._units == UnitsContainer(meter=1) + with pytest.raises(TypeError): + self.U_(1) def test_deepcopy(self): x = self.U_(UnitsContainer(meter=1)) - self.assertEqual(x, copy.deepcopy(x)) + assert x == copy.deepcopy(x) def test_unit_repr(self): x = self.U_(UnitsContainer(meter=1)) - self.assertEqual(str(x), "meter") - self.assertEqual(repr(x), "<Unit('meter')>") + assert str(x) == "meter" + assert repr(x) == "<Unit('meter')>" - def test_unit_formatting(self): + def test_unit_formatting(self, subtests): x = self.U_(UnitsContainer(meter=2, kilogram=1, second=-1)) for spec, result in ( ("{}", str(x)), @@ -51,10 +54,10 @@ class TestUnit(QuantityTestCase): ("{:H~}", "kg m<sup>2</sup>/s"), ("{:C~}", "kg*m**2/s"), ): - with self.subTest(spec): - self.assertEqual(spec.format(x), result) + with subtests.test(spec): + assert spec.format(x) == result - def test_unit_default_formatting(self): + def test_unit_default_formatting(self, subtests): ureg = UnitRegistry() x = ureg.Unit(UnitsContainer(meter=2, kilogram=1, second=-1)) for spec, result in ( @@ -71,11 +74,11 @@ class TestUnit(QuantityTestCase): ("H~", "kg m<sup>2</sup>/s"), ("C~", "kg*m**2/s"), ): - with self.subTest(spec): + with subtests.test(spec): ureg.default_format = spec - self.assertEqual(f"{x}", result, f"Failed for {spec}, {result}") + assert f"{x}" == result, f"Failed for {spec}, {result}" - def test_unit_formatting_snake_case(self): + def test_unit_formatting_snake_case(self, subtests): # Test that snake_case units are escaped where appropriate ureg = UnitRegistry() x = ureg.Unit(UnitsContainer(oil_barrel=1)) @@ -90,9 +93,9 @@ class TestUnit(QuantityTestCase): ("H~", "oil_bbl"), ("C~", "oil_bbl"), ): - with self.subTest(spec): + with subtests.test(spec): ureg.default_format = spec - self.assertEqual(f"{x}", result, f"Failed for {spec}, {result}") + assert f"{x}" == result, f"Failed for {spec}, {result}" def test_ipython(self): alltext = [] @@ -104,118 +107,119 @@ class TestUnit(QuantityTestCase): ureg = UnitRegistry() x = ureg.Unit(UnitsContainer(meter=2, kilogram=1, second=-1)) - self.assertEqual(x._repr_html_(), "kilogram meter<sup>2</sup>/second") - self.assertEqual( - x._repr_latex_(), - r"$\frac{\mathrm{kilogram} \cdot " r"\mathrm{meter}^{2}}{\mathrm{second}}$", + assert x._repr_html_() == "kilogram meter<sup>2</sup>/second" + assert ( + x._repr_latex_() == r"$\frac{\mathrm{kilogram} \cdot " + r"\mathrm{meter}^{2}}{\mathrm{second}}$" ) x._repr_pretty_(Pretty, False) - self.assertEqual("".join(alltext), "kilogram·meter²/second") + assert "".join(alltext) == "kilogram·meter²/second" ureg.default_format = "~" - self.assertEqual(x._repr_html_(), "kg m<sup>2</sup>/s") - self.assertEqual( - x._repr_latex_(), r"$\frac{\mathrm{kg} \cdot \mathrm{m}^{2}}{\mathrm{s}}$" + assert x._repr_html_() == "kg m<sup>2</sup>/s" + assert ( + x._repr_latex_() == r"$\frac{\mathrm{kg} \cdot \mathrm{m}^{2}}{\mathrm{s}}$" ) alltext = [] x._repr_pretty_(Pretty, False) - self.assertEqual("".join(alltext), "kg·m²/s") + assert "".join(alltext) == "kg·m²/s" def test_unit_mul(self): x = self.U_("m") - self.assertEqual(x * 1, self.Q_(1, "m")) - self.assertEqual(x * 0.5, self.Q_(0.5, "m")) - self.assertEqual(x * self.Q_(1, "m"), self.Q_(1, "m**2")) - self.assertEqual(1 * x, self.Q_(1, "m")) + assert x * 1 == self.Q_(1, "m") + assert x * 0.5 == self.Q_(0.5, "m") + assert x * self.Q_(1, "m") == self.Q_(1, "m**2") + assert 1 * x == self.Q_(1, "m") def test_unit_div(self): x = self.U_("m") - self.assertEqual(x / 1, self.Q_(1, "m")) - self.assertEqual(x / 0.5, self.Q_(2.0, "m")) - self.assertEqual(x / self.Q_(1, "m"), self.Q_(1)) + assert x / 1 == self.Q_(1, "m") + assert x / 0.5 == self.Q_(2.0, "m") + assert x / self.Q_(1, "m") == self.Q_(1) def test_unit_rdiv(self): x = self.U_("m") - self.assertEqual(1 / x, self.Q_(1, "1/m")) + assert 1 / x == self.Q_(1, "1/m") def test_unit_pow(self): x = self.U_("m") - self.assertEqual(x ** 2, self.U_("m**2")) + assert x ** 2 == self.U_("m**2") def test_unit_hash(self): x = self.U_("m") - self.assertEqual(hash(x), hash(x._units)) + assert hash(x) == hash(x._units) def test_unit_eqs(self): x = self.U_("m") - self.assertEqual(x, self.U_("m")) - self.assertNotEqual(x, self.U_("cm")) + assert x == self.U_("m") + assert x != self.U_("cm") - self.assertEqual(x, self.Q_(1, "m")) - self.assertNotEqual(x, self.Q_(2, "m")) + assert x == self.Q_(1, "m") + assert x != self.Q_(2, "m") - self.assertEqual(x, UnitsContainer({"meter": 1})) + assert x == UnitsContainer({"meter": 1}) y = self.U_("cm/m") - self.assertEqual(y, 0.01) + assert y == 0.01 - self.assertEqual(self.U_("byte") == self.U_("byte"), True) - self.assertEqual(self.U_("byte") != self.U_("byte"), False) + assert self.U_("byte") == self.U_("byte") + assert not (self.U_("byte") != self.U_("byte")) def test_unit_cmp(self): x = self.U_("m") - self.assertLess(x, self.U_("km")) - self.assertGreater(x, self.U_("mm")) + assert x < self.U_("km") + assert x > self.U_("mm") y = self.U_("m/mm") - self.assertGreater(y, 1) - self.assertLess(y, 1e6) + assert y > 1 + assert y < 1e6 def test_dimensionality(self): x = self.U_("m") - self.assertEqual(x.dimensionality, UnitsContainer({"[length]": 1})) + assert x.dimensionality == UnitsContainer({"[length]": 1}) def test_dimensionless(self): - self.assertTrue(self.U_("m/mm").dimensionless) - self.assertFalse(self.U_("m").dimensionless) + assert self.U_("m/mm").dimensionless + assert not self.U_("m").dimensionless def test_unit_casting(self): - self.assertEqual(int(self.U_("m/mm")), 1000) - self.assertEqual(float(self.U_("mm/m")), 1e-3) - self.assertEqual(complex(self.U_("mm/mm")), 1 + 0j) + assert int(self.U_("m/mm")) == 1000 + assert float(self.U_("mm/m")) == 1e-3 + assert complex(self.U_("mm/mm")) == 1 + 0j - @helpers.requires_numpy() + @helpers.requires_numpy def test_array_interface(self): import numpy as np x = self.U_("m") arr = np.ones(10) - self.assertQuantityEqual(arr * x, self.Q_(arr, "m")) - self.assertQuantityEqual(arr / x, self.Q_(arr, "1/m")) - self.assertQuantityEqual(x / arr, self.Q_(arr, "m")) + helpers.assert_quantity_equal(arr * x, self.Q_(arr, "m")) + helpers.assert_quantity_equal(arr / x, self.Q_(arr, "1/m")) + helpers.assert_quantity_equal(x / arr, self.Q_(arr, "m")) class TestRegistry(QuantityTestCase): - - FORCE_NDARRAY = False - - def setup(self): - self.ureg.autoconvert_offset_to_baseunit = False + @classmethod + def setup_class(cls): + super().setup_class() + cls.ureg.autoconvert_offset_to_baseunit = False def test_base(self): ureg = UnitRegistry(None) ureg.define("meter = [length]") - self.assertRaises(DefinitionSyntaxError, ureg.define, "meter = [length]") - self.assertRaises(TypeError, ureg.define, list()) + with pytest.raises(DefinitionSyntaxError): + ureg.define("meter = [length]") + with pytest.raises(TypeError): + ureg.define(list()) ureg.define("degC = kelvin; offset: 273.15") def test_define(self): ureg = UnitRegistry(None) - self.assertIsInstance(dir(ureg), list) - self.assertGreater(len(dir(ureg)), 0) + assert isinstance(dir(ureg), list) + assert len(dir(ureg)) > 0 def test_load(self): import pkg_resources @@ -225,10 +229,9 @@ class TestRegistry(QuantityTestCase): data = pkg_resources.resource_filename(unit.__name__, "default_en.txt") ureg1 = UnitRegistry() ureg2 = UnitRegistry(data) - self.assertEqual(dir(ureg1), dir(ureg2)) - self.assertRaises( - ValueError, UnitRegistry(None).load_definitions, "notexisting" - ) + assert dir(ureg1) == dir(ureg2) + with pytest.raises(ValueError): + UnitRegistry(None).load_definitions("notexisting") def test_default_format(self): ureg = UnitRegistry() @@ -237,130 +240,109 @@ class TestRegistry(QuantityTestCase): s2 = f"{q:~}" ureg.default_format = "~" s3 = f"{q}" - self.assertEqual(s2, s3) - self.assertNotEqual(s1, s3) - self.assertEqual(ureg.default_format, "~") + assert s2 == s3 + assert s1 != s3 + assert ureg.default_format == "~" def test_iterate(self): ureg = UnitRegistry() - self.assertTrue("meter" in list(ureg)) + assert "meter" in list(ureg) def test_parse_number(self): - self.assertEqual(self.ureg.parse_expression("pi"), math.pi) - self.assertEqual(self.ureg.parse_expression("x", x=2), 2) - self.assertEqual(self.ureg.parse_expression("x", x=2.3), 2.3) - self.assertEqual(self.ureg.parse_expression("x * y", x=2.3, y=3), 2.3 * 3) - self.assertEqual(self.ureg.parse_expression("x", x=(1 + 1j)), (1 + 1j)) + assert self.ureg.parse_expression("pi") == math.pi + assert self.ureg.parse_expression("x", x=2) == 2 + assert self.ureg.parse_expression("x", x=2.3) == 2.3 + assert self.ureg.parse_expression("x * y", x=2.3, y=3) == 2.3 * 3 + assert self.ureg.parse_expression("x", x=(1 + 1j)) == (1 + 1j) def test_parse_single(self): - self.assertEqual( - self.ureg.parse_expression("meter"), self.Q_(1, UnitsContainer(meter=1.0)) + assert self.ureg.parse_expression("meter") == self.Q_( + 1, UnitsContainer(meter=1.0) ) - self.assertEqual( - self.ureg.parse_expression("second"), self.Q_(1, UnitsContainer(second=1.0)) + assert self.ureg.parse_expression("second") == self.Q_( + 1, UnitsContainer(second=1.0) ) def test_parse_alias(self): - self.assertEqual( - self.ureg.parse_expression("metre"), self.Q_(1, UnitsContainer(meter=1.0)) + assert self.ureg.parse_expression("metre") == self.Q_( + 1, UnitsContainer(meter=1.0) ) def test_parse_plural(self): - self.assertEqual( - self.ureg.parse_expression("meters"), self.Q_(1, UnitsContainer(meter=1.0)) + assert self.ureg.parse_expression("meters") == self.Q_( + 1, UnitsContainer(meter=1.0) ) def test_parse_prefix(self): - self.assertEqual( - self.ureg.parse_expression("kilometer"), - self.Q_(1, UnitsContainer(kilometer=1.0)), + assert self.ureg.parse_expression("kilometer") == self.Q_( + 1, UnitsContainer(kilometer=1.0) ) def test_parse_complex(self): - self.assertEqual( - self.ureg.parse_expression("kilometre"), - self.Q_(1, UnitsContainer(kilometer=1.0)), + assert self.ureg.parse_expression("kilometre") == self.Q_( + 1, UnitsContainer(kilometer=1.0) ) - self.assertEqual( - self.ureg.parse_expression("kilometres"), - self.Q_(1, UnitsContainer(kilometer=1.0)), + assert self.ureg.parse_expression("kilometres") == self.Q_( + 1, UnitsContainer(kilometer=1.0) ) def test_parse_mul_div(self): - self.assertEqual( - self.ureg.parse_expression("meter*meter"), - self.Q_(1, UnitsContainer(meter=2.0)), + assert self.ureg.parse_expression("meter*meter") == self.Q_( + 1, UnitsContainer(meter=2.0) ) - self.assertEqual( - self.ureg.parse_expression("meter**2"), - self.Q_(1, UnitsContainer(meter=2.0)), + assert self.ureg.parse_expression("meter**2") == self.Q_( + 1, UnitsContainer(meter=2.0) ) - self.assertEqual( - self.ureg.parse_expression("meter*second"), - self.Q_(1, UnitsContainer(meter=1.0, second=1)), + assert self.ureg.parse_expression("meter*second") == self.Q_( + 1, UnitsContainer(meter=1.0, second=1) ) - self.assertEqual( - self.ureg.parse_expression("meter/second"), - self.Q_(1, UnitsContainer(meter=1.0, second=-1)), + assert self.ureg.parse_expression("meter/second") == self.Q_( + 1, UnitsContainer(meter=1.0, second=-1) ) - self.assertEqual( - self.ureg.parse_expression("meter/second**2"), - self.Q_(1, UnitsContainer(meter=1.0, second=-2)), + assert self.ureg.parse_expression("meter/second**2") == self.Q_( + 1, UnitsContainer(meter=1.0, second=-2) ) def test_parse_pretty(self): - self.assertEqual( - self.ureg.parse_expression("meter/second²"), - self.Q_(1, UnitsContainer(meter=1.0, second=-2)), + assert self.ureg.parse_expression("meter/second²") == self.Q_( + 1, UnitsContainer(meter=1.0, second=-2) ) - self.assertEqual( - self.ureg.parse_expression("m³/s³"), - self.Q_(1, UnitsContainer(meter=3.0, second=-3)), + assert self.ureg.parse_expression("m³/s³") == self.Q_( + 1, UnitsContainer(meter=3.0, second=-3) ) - self.assertEqual( - self.ureg.parse_expression("meter² · second"), - self.Q_(1, UnitsContainer(meter=2.0, second=1)), + assert self.ureg.parse_expression("meter² · second") == self.Q_( + 1, UnitsContainer(meter=2.0, second=1) ) - self.assertEqual( - self.ureg.parse_expression("meter⁰.⁵·second"), - self.Q_(1, UnitsContainer(meter=0.5, second=1)), + assert self.ureg.parse_expression("meter⁰.⁵·second") == self.Q_( + 1, UnitsContainer(meter=0.5, second=1) ) - self.assertEqual( - self.ureg.parse_expression("meter³⁷/second⁴.³²¹"), - self.Q_(1, UnitsContainer(meter=37, second=-4.321)), + assert self.ureg.parse_expression("meter³⁷/second⁴.³²¹") == self.Q_( + 1, UnitsContainer(meter=37, second=-4.321) ) def test_parse_factor(self): - self.assertEqual( - self.ureg.parse_expression("42*meter"), - self.Q_(42, UnitsContainer(meter=1.0)), + assert self.ureg.parse_expression("42*meter") == self.Q_( + 42, UnitsContainer(meter=1.0) ) - self.assertEqual( - self.ureg.parse_expression("meter*42"), - self.Q_(42, UnitsContainer(meter=1.0)), + assert self.ureg.parse_expression("meter*42") == self.Q_( + 42, UnitsContainer(meter=1.0) ) def test_rep_and_parse(self): q = self.Q_(1, "g/(m**2*s)") - self.assertEqual(self.Q_(q.magnitude, str(q.units)), q) + assert self.Q_(q.magnitude, str(q.units)) == q def test_as_delta(self): parse = self.ureg.parse_units - self.assertEqual(parse("kelvin", as_delta=True), UnitsContainer(kelvin=1)) - self.assertEqual(parse("kelvin", as_delta=False), UnitsContainer(kelvin=1)) - self.assertEqual( - parse("kelvin**(-1)", as_delta=True), UnitsContainer(kelvin=-1) - ) - self.assertEqual( - parse("kelvin**(-1)", as_delta=False), UnitsContainer(kelvin=-1) - ) - self.assertEqual(parse("kelvin**2", as_delta=True), UnitsContainer(kelvin=2)) - self.assertEqual(parse("kelvin**2", as_delta=False), UnitsContainer(kelvin=2)) - self.assertEqual( - parse("kelvin*meter", as_delta=True), UnitsContainer(kelvin=1, meter=1) - ) - self.assertEqual( - parse("kelvin*meter", as_delta=False), UnitsContainer(kelvin=1, meter=1) + assert parse("kelvin", as_delta=True) == UnitsContainer(kelvin=1) + assert parse("kelvin", as_delta=False) == UnitsContainer(kelvin=1) + assert parse("kelvin**(-1)", as_delta=True) == UnitsContainer(kelvin=-1) + assert parse("kelvin**(-1)", as_delta=False) == UnitsContainer(kelvin=-1) + assert parse("kelvin**2", as_delta=True) == UnitsContainer(kelvin=2) + assert parse("kelvin**2", as_delta=False) == UnitsContainer(kelvin=2) + assert parse("kelvin*meter", as_delta=True) == UnitsContainer(kelvin=1, meter=1) + assert parse("kelvin*meter", as_delta=False) == UnitsContainer( + kelvin=1, meter=1 ) def test_parse_expression_with_preprocessor(self): @@ -373,22 +355,19 @@ class TestRegistry(QuantityTestCase): ) ) # Test equality - self.assertEqual( - self.ureg.parse_expression("42 m2"), self.Q_(42, UnitsContainer(meter=2.0)) + assert self.ureg.parse_expression("42 m2") == self.Q_( + 42, UnitsContainer(meter=2.0) ) - self.assertEqual( - self.ureg.parse_expression("1e6 Hz s-2"), - self.Q_(1e6, UnitsContainer(second=-3.0)), + assert self.ureg.parse_expression("1e6 Hz s-2") == self.Q_( + 1e6, UnitsContainer(second=-3.0) ) - self.assertEqual( - self.ureg.parse_expression("3 metre3"), - self.Q_(3, UnitsContainer(meter=3.0)), + assert self.ureg.parse_expression("3 metre3") == self.Q_( + 3, UnitsContainer(meter=3.0) ) # Clean up and test previously expected value self.ureg.preprocessors.pop() - self.assertEqual( - self.ureg.parse_expression("1e6 Hz s-2"), - self.Q_(999998.0, UnitsContainer()), + assert self.ureg.parse_expression("1e6 Hz s-2") == self.Q_( + 999998.0, UnitsContainer() ) def test_parse_unit_with_preprocessor(self): @@ -401,36 +380,38 @@ class TestRegistry(QuantityTestCase): ) ) # Test equality - self.assertEqual(self.ureg.parse_units("m2"), UnitsContainer(meter=2.0)) - self.assertEqual(self.ureg.parse_units("m-2"), UnitsContainer(meter=-2.0)) + assert self.ureg.parse_units("m2") == UnitsContainer(meter=2.0) + assert self.ureg.parse_units("m-2") == UnitsContainer(meter=-2.0) # Clean up self.ureg.preprocessors.pop() def test_name(self): - self.assertRaises(UndefinedUnitError, self.ureg.get_name, "asdf") + with pytest.raises(UndefinedUnitError): + self.ureg.get_name("asdf") def test_symbol(self): - self.assertRaises(UndefinedUnitError, self.ureg.get_symbol, "asdf") + with pytest.raises(UndefinedUnitError): + self.ureg.get_symbol("asdf") - self.assertEqual(self.ureg.get_symbol("meter"), "m") - self.assertEqual(self.ureg.get_symbol("second"), "s") - self.assertEqual(self.ureg.get_symbol("hertz"), "Hz") + assert self.ureg.get_symbol("meter") == "m" + assert self.ureg.get_symbol("second") == "s" + assert self.ureg.get_symbol("hertz") == "Hz" - self.assertEqual(self.ureg.get_symbol("kilometer"), "km") - self.assertEqual(self.ureg.get_symbol("megahertz"), "MHz") - self.assertEqual(self.ureg.get_symbol("millisecond"), "ms") + assert self.ureg.get_symbol("kilometer") == "km" + assert self.ureg.get_symbol("megahertz") == "MHz" + assert self.ureg.get_symbol("millisecond") == "ms" def test_imperial_symbol(self): - self.assertEqual(self.ureg.get_symbol("inch"), "in") - self.assertEqual(self.ureg.get_symbol("foot"), "ft") - self.assertEqual(self.ureg.get_symbol("inches"), "in") - self.assertEqual(self.ureg.get_symbol("feet"), "ft") - self.assertEqual(self.ureg.get_symbol("international_foot"), "ft") - self.assertEqual(self.ureg.get_symbol("international_inch"), "in") + assert self.ureg.get_symbol("inch") == "in" + assert self.ureg.get_symbol("foot") == "ft" + assert self.ureg.get_symbol("inches") == "in" + assert self.ureg.get_symbol("feet") == "ft" + assert self.ureg.get_symbol("international_foot") == "ft" + assert self.ureg.get_symbol("international_inch") == "in" def test_pint(self): - self.assertLess(self.ureg.pint, self.ureg.liter) - self.assertLess(self.ureg.pint, self.ureg.imperial_pint) + assert self.ureg.pint < self.ureg.liter + assert self.ureg.pint < self.ureg.imperial_pint def test_wraps(self): def func(x): @@ -438,78 +419,90 @@ class TestRegistry(QuantityTestCase): ureg = self.ureg - self.assertRaises(TypeError, ureg.wraps, (3 * ureg.meter, [None])) - self.assertRaises(TypeError, ureg.wraps, (None, [3 * ureg.meter])) + with pytest.raises(TypeError): + ureg.wraps((3 * ureg.meter, [None])) + with pytest.raises(TypeError): + ureg.wraps((None, [3 * ureg.meter])) f0 = ureg.wraps(None, [None])(func) - self.assertEqual(f0(3.0), 3.0) + assert f0(3.0) == 3.0 f0 = ureg.wraps(None, None)(func) - self.assertEqual(f0(3.0), 3.0) + assert f0(3.0) == 3.0 f1 = ureg.wraps(None, ["meter"])(func) - self.assertRaises(ValueError, f1, 3.0) - self.assertEqual(f1(3.0 * ureg.centimeter), 0.03) - self.assertEqual(f1(3.0 * ureg.meter), 3.0) - self.assertRaises(DimensionalityError, f1, 3 * ureg.second) + with pytest.raises(ValueError): + f1(3.0) + assert f1(3.0 * ureg.centimeter) == 0.03 + assert f1(3.0 * ureg.meter) == 3.0 + with pytest.raises(DimensionalityError): + f1(3 * ureg.second) f1b = ureg.wraps(None, [ureg.meter])(func) - self.assertRaises(ValueError, f1b, 3.0) - self.assertEqual(f1b(3.0 * ureg.centimeter), 0.03) - self.assertEqual(f1b(3.0 * ureg.meter), 3.0) - self.assertRaises(DimensionalityError, f1b, 3 * ureg.second) + with pytest.raises(ValueError): + f1b(3.0) + assert f1b(3.0 * ureg.centimeter) == 0.03 + assert f1b(3.0 * ureg.meter) == 3.0 + with pytest.raises(DimensionalityError): + f1b(3 * ureg.second) f1c = ureg.wraps("meter", [ureg.meter])(func) - self.assertEqual(f1c(3.0 * ureg.centimeter), 0.03 * ureg.meter) - self.assertEqual(f1c(3.0 * ureg.meter), 3.0 * ureg.meter) - self.assertRaises(DimensionalityError, f1c, 3 * ureg.second) + assert f1c(3.0 * ureg.centimeter) == 0.03 * ureg.meter + assert f1c(3.0 * ureg.meter) == 3.0 * ureg.meter + with pytest.raises(DimensionalityError): + f1c(3 * ureg.second) f1d = ureg.wraps(ureg.meter, [ureg.meter])(func) - self.assertEqual(f1d(3.0 * ureg.centimeter), 0.03 * ureg.meter) - self.assertEqual(f1d(3.0 * ureg.meter), 3.0 * ureg.meter) - self.assertRaises(DimensionalityError, f1d, 3 * ureg.second) + assert f1d(3.0 * ureg.centimeter) == 0.03 * ureg.meter + assert f1d(3.0 * ureg.meter) == 3.0 * ureg.meter + with pytest.raises(DimensionalityError): + f1d(3 * ureg.second) f1 = ureg.wraps(None, "meter")(func) - self.assertRaises(ValueError, f1, 3.0) - self.assertEqual(f1(3.0 * ureg.centimeter), 0.03) - self.assertEqual(f1(3.0 * ureg.meter), 3.0) - self.assertRaises(DimensionalityError, f1, 3 * ureg.second) + with pytest.raises(ValueError): + f1(3.0) + assert f1(3.0 * ureg.centimeter) == 0.03 + assert f1(3.0 * ureg.meter) == 3.0 + with pytest.raises(DimensionalityError): + f1(3 * ureg.second) f2 = ureg.wraps("centimeter", ["meter"])(func) - self.assertRaises(ValueError, f2, 3.0) - self.assertEqual(f2(3.0 * ureg.centimeter), 0.03 * ureg.centimeter) - self.assertEqual(f2(3.0 * ureg.meter), 3 * ureg.centimeter) + with pytest.raises(ValueError): + f2(3.0) + assert f2(3.0 * ureg.centimeter) == 0.03 * ureg.centimeter + assert f2(3.0 * ureg.meter) == 3 * ureg.centimeter f3 = ureg.wraps("centimeter", ["meter"], strict=False)(func) - self.assertEqual(f3(3), 3 * ureg.centimeter) - self.assertEqual(f3(3.0 * ureg.centimeter), 0.03 * ureg.centimeter) - self.assertEqual(f3(3.0 * ureg.meter), 3.0 * ureg.centimeter) + assert f3(3) == 3 * ureg.centimeter + assert f3(3.0 * ureg.centimeter) == 0.03 * ureg.centimeter + assert f3(3.0 * ureg.meter) == 3.0 * ureg.centimeter def gfunc(x, y): return x + y g0 = ureg.wraps(None, [None, None])(gfunc) - self.assertEqual(g0(3, 1), 4) + assert g0(3, 1) == 4 g1 = ureg.wraps(None, ["meter", "centimeter"])(gfunc) - self.assertRaises(ValueError, g1, 3 * ureg.meter, 1) - self.assertEqual(g1(3 * ureg.meter, 1 * ureg.centimeter), 4) - self.assertEqual(g1(3 * ureg.meter, 1 * ureg.meter), 3 + 100) + with pytest.raises(ValueError): + g1(3 * ureg.meter, 1) + assert g1(3 * ureg.meter, 1 * ureg.centimeter) == 4 + assert g1(3 * ureg.meter, 1 * ureg.meter) == 3 + 100 def hfunc(x, y): return x, y h0 = ureg.wraps(None, [None, None])(hfunc) - self.assertEqual(h0(3, 1), (3, 1)) + assert h0(3, 1) == (3, 1) h1 = ureg.wraps(["meter", "centimeter"], [None, None])(hfunc) - self.assertEqual(h1(3, 1), [3 * ureg.meter, 1 * ureg.cm]) + assert h1(3, 1) == [3 * ureg.meter, 1 * ureg.cm] h2 = ureg.wraps(("meter", "centimeter"), [None, None])(hfunc) - self.assertEqual(h2(3, 1), (3 * ureg.meter, 1 * ureg.cm)) + assert h2(3, 1) == (3 * ureg.meter, 1 * ureg.cm) h3 = ureg.wraps((None,), (None, None))(hfunc) - self.assertEqual(h3(3, 1), (3, 1)) + assert h3(3, 1) == (3, 1) def test_wrap_referencing(self): @@ -527,29 +520,27 @@ class TestRegistry(QuantityTestCase): rst = 3.0 * ureg.meter + 1.0 * ureg.centimeter g0 = ureg.wraps("=A", ["=A", "=A"])(gfunc) - self.assertEqual(g0(3.0 * ureg.meter, 1.0 * ureg.centimeter), rst.to("meter")) - self.assertEqual(g0(3, 1), 4) + assert g0(3.0 * ureg.meter, 1.0 * ureg.centimeter) == rst.to("meter") + assert g0(3, 1) == 4 g1 = ureg.wraps("=A", ["=A", "=A"])(gfunc) - self.assertEqual( - g1(3.0 * ureg.meter, 1.0 * ureg.centimeter), rst.to("centimeter") - ) + assert g1(3.0 * ureg.meter, 1.0 * ureg.centimeter) == rst.to("centimeter") g2 = ureg.wraps("=A", ["=A", "=A"])(gfunc) - self.assertEqual(g2(3.0 * ureg.meter, 1.0 * ureg.centimeter), rst.to("meter")) + assert g2(3.0 * ureg.meter, 1.0 * ureg.centimeter) == rst.to("meter") g3 = ureg.wraps("=A**2", ["=A", "=A**2"])(gfunc2) a = 3.0 * ureg.meter b = (2.0 * ureg.centimeter) ** 2 - self.assertEqual(g3(a, b), gfunc2(a, b)) - self.assertEqual(g3(3, 2), gfunc2(3, 2)) + assert g3(a, b) == gfunc2(a, b) + assert g3(3, 2) == gfunc2(3, 2) g4 = ureg.wraps("=A**2 * B", ["=A", "=B"])(gfunc3) - self.assertEqual( - g4(3.0 * ureg.meter, 2.0 * ureg.second), ureg("(3*meter)**2 * 2 *second") + assert g4(3.0 * ureg.meter, 2.0 * ureg.second) == ureg( + "(3*meter)**2 * 2 *second" ) - self.assertEqual(g4(3.0 * ureg.meter, 2.0), ureg("(3*meter)**2 * 2")) - self.assertEqual(g4(3.0, 2.0 * ureg.second), ureg("3**2 * 2 * second")) + assert g4(3.0 * ureg.meter, 2.0) == ureg("(3*meter)**2 * 2") + assert g4(3.0, 2.0 * ureg.second) == ureg("3**2 * 2 * second") def test_check(self): def func(x): @@ -558,55 +549,62 @@ class TestRegistry(QuantityTestCase): ureg = self.ureg f0 = ureg.check("[length]")(func) - self.assertRaises(DimensionalityError, f0, 3.0) - self.assertEqual(f0(3.0 * ureg.centimeter), 0.03 * ureg.meter) - self.assertRaises(DimensionalityError, f0, 3.0 * ureg.kilogram) + with pytest.raises(DimensionalityError): + f0(3.0) + assert f0(3.0 * ureg.centimeter) == 0.03 * ureg.meter + with pytest.raises(DimensionalityError): + f0(3.0 * ureg.kilogram) f0b = ureg.check(ureg.meter)(func) - self.assertRaises(DimensionalityError, f0b, 3.0) - self.assertEqual(f0b(3.0 * ureg.centimeter), 0.03 * ureg.meter) - self.assertRaises(DimensionalityError, f0b, 3.0 * ureg.kilogram) + with pytest.raises(DimensionalityError): + f0b(3.0) + assert f0b(3.0 * ureg.centimeter) == 0.03 * ureg.meter + with pytest.raises(DimensionalityError): + f0b(3.0 * ureg.kilogram) def gfunc(x, y): return x / y g0 = ureg.check(None, None)(gfunc) - self.assertEqual(g0(6, 2), 3) - self.assertEqual(g0(6 * ureg.parsec, 2), 3 * ureg.parsec) + assert g0(6, 2) == 3 + assert g0(6 * ureg.parsec, 2) == 3 * ureg.parsec g1 = ureg.check("[speed]", "[time]")(gfunc) - self.assertRaises(DimensionalityError, g1, 3.0, 1) - self.assertRaises(DimensionalityError, g1, 1 * ureg.parsec, 1 * ureg.angstrom) - self.assertRaises(TypeError, g1, 1 * ureg.km / ureg.hour, 1 * ureg.hour, 3.0) - self.assertEqual( - g1(3.6 * ureg.km / ureg.hour, 1 * ureg.second), - 1 * ureg.meter / ureg.second ** 2, - ) - - self.assertRaises(TypeError, ureg.check("[speed]"), gfunc) - self.assertRaises(TypeError, ureg.check("[speed]", "[time]", "[mass]"), gfunc) + with pytest.raises(DimensionalityError): + g1(3.0, 1) + with pytest.raises(DimensionalityError): + g1(1 * ureg.parsec, 1 * ureg.angstrom) + with pytest.raises(TypeError): + g1(1 * ureg.km / ureg.hour, 1 * ureg.hour, 3.0) + assert ( + g1(3.6 * ureg.km / ureg.hour, 1 * ureg.second) + == 1 * ureg.meter / ureg.second ** 2 + ) + + with pytest.raises(TypeError): + ureg.check("[speed]")(gfunc) + with pytest.raises(TypeError): + ureg.check("[speed]", "[time]", "[mass]")(gfunc) def test_to_ref_vs_to(self): self.ureg.autoconvert_offset_to_baseunit = True q = 8.0 * self.ureg.inch t = 8.0 * self.ureg.degF dt = 8.0 * self.ureg.delta_degF - self.assertEqual( - q.to("yard").magnitude, self.ureg._units["inch"].converter.to_reference(8.0) - ) - self.assertEqual( - t.to("kelvin").magnitude, - self.ureg._units["degF"].converter.to_reference(8.0), - ) - self.assertEqual( - dt.to("kelvin").magnitude, - self.ureg._units["delta_degF"].converter.to_reference(8.0), - ) - - def test_redefinition(self): + assert q.to("yard").magnitude == self.ureg._units[ + "inch" + ].converter.to_reference(8.0) + assert t.to("kelvin").magnitude == self.ureg._units[ + "degF" + ].converter.to_reference(8.0) + assert dt.to("kelvin").magnitude == self.ureg._units[ + "delta_degF" + ].converter.to_reference(8.0) + + def test_redefinition(self, caplog): d = UnitRegistry().define - with self.capture_log() as buffer: + with caplog.at_level(logging.DEBUG): d("meter = [fruits]") d("kilo- = 1000") d("[speed] = [vegetables]") @@ -615,16 +613,15 @@ class TestRegistry(QuantityTestCase): d("bla = 3.2 meter = inch") d("myk- = 1000 = kilo-") - self.assertEqual(len(buffer), 5) + assert len(caplog.records) == 5 def test_convert_parse_str(self): ureg = self.ureg - self.assertEqual( - ureg.convert(1, "meter", "inch"), - ureg.convert(1, UnitsContainer(meter=1), UnitsContainer(inch=1)), + assert ureg.convert(1, "meter", "inch") == ureg.convert( + 1, UnitsContainer(meter=1), UnitsContainer(inch=1) ) - @helpers.requires_numpy() + @helpers.requires_numpy def test_convert_inplace(self): ureg = self.ureg @@ -640,11 +637,11 @@ class TestRegistry(QuantityTestCase): r1 = ureg.convert(a, src, dst) np.testing.assert_allclose(r1, v * ac) - self.assertIsNot(r1, a) + assert r1 is not a r2 = ureg.convert(a, src, dst, inplace=True) np.testing.assert_allclose(r2, v * ac) - self.assertIs(r2, a) + assert r2 is a def test_repeated_convert(self): # Because of caching, repeated conversions were failing. @@ -660,114 +657,98 @@ class TestRegistry(QuantityTestCase): def test_parse_units(self): ureg = self.ureg - self.assertEqual(ureg.parse_units(""), ureg.Unit("")) - self.assertRaises(ValueError, ureg.parse_units, "2 * meter") + assert ureg.parse_units("") == ureg.Unit("") + with pytest.raises(ValueError): + ureg.parse_units("2 * meter") def test_parse_string_pattern(self): ureg = self.ureg - self.assertEqual( - ureg.parse_pattern("10'11", r"{foot}'{inch}"), - [ureg.Quantity(10.0, "foot"), ureg.Quantity(11.0, "inch")], - ) + assert ureg.parse_pattern("10'11", r"{foot}'{inch}") == [ + ureg.Quantity(10.0, "foot"), + ureg.Quantity(11.0, "inch"), + ] def test_parse_string_pattern_no_preprocess(self): """Were preprocessors enabled, this would be interpreted as 10*11, not two separate units, and thus cause the parsing to fail""" ureg = self.ureg - self.assertEqual( - ureg.parse_pattern("10 11", r"{kg} {lb}"), - [ureg.Quantity(10.0, "kilogram"), ureg.Quantity(11.0, "pound")], - ) + assert ureg.parse_pattern("10 11", r"{kg} {lb}") == [ + ureg.Quantity(10.0, "kilogram"), + ureg.Quantity(11.0, "pound"), + ] def test_parse_pattern_many_results(self): ureg = self.ureg - self.assertEqual( - ureg.parse_pattern( - "1.5kg or 2kg will be fine, if you do not have 3kg", - r"{kg}kg", - many=True, - ), - [ - [ureg.Quantity(1.5, "kilogram")], - [ureg.Quantity(2.0, "kilogram")], - [ureg.Quantity(3.0, "kilogram")], - ], - ) + assert ureg.parse_pattern( + "1.5kg or 2kg will be fine, if you do not have 3kg", + r"{kg}kg", + many=True, + ) == [ + [ureg.Quantity(1.5, "kilogram")], + [ureg.Quantity(2.0, "kilogram")], + [ureg.Quantity(3.0, "kilogram")], + ] def test_parse_pattern_many_results_two_units(self): ureg = self.ureg - self.assertEqual( - ureg.parse_pattern("10'10 or 10'11", "{foot}'{inch}", many=True), - [ - [ureg.Quantity(10.0, "foot"), ureg.Quantity(10.0, "inch")], - [ureg.Quantity(10.0, "foot"), ureg.Quantity(11.0, "inch")], - ], - ) + assert ureg.parse_pattern("10'10 or 10'11", "{foot}'{inch}", many=True) == [ + [ureg.Quantity(10.0, "foot"), ureg.Quantity(10.0, "inch")], + [ureg.Quantity(10.0, "foot"), ureg.Quantity(11.0, "inch")], + ] def test_case_sensitivity(self): ureg = self.ureg # Default - self.assertRaises(UndefinedUnitError, ureg.parse_units, "Meter") - self.assertRaises(UndefinedUnitError, ureg.parse_units, "j") + with pytest.raises(UndefinedUnitError): + ureg.parse_units("Meter") + with pytest.raises(UndefinedUnitError): + ureg.parse_units("j") # Force True - self.assertRaises( - UndefinedUnitError, ureg.parse_units, "Meter", case_sensitive=True - ) - self.assertRaises( - UndefinedUnitError, ureg.parse_units, "j", case_sensitive=True - ) + with pytest.raises(UndefinedUnitError): + ureg.parse_units("Meter", case_sensitive=True) + with pytest.raises(UndefinedUnitError): + ureg.parse_units("j", case_sensitive=True) # Force False - self.assertEqual( - ureg.parse_units("Meter", case_sensitive=False), UnitsContainer(meter=1) - ) - self.assertEqual( - ureg.parse_units("j", case_sensitive=False), UnitsContainer(joule=1) + assert ureg.parse_units("Meter", case_sensitive=False) == UnitsContainer( + meter=1 ) + assert ureg.parse_units("j", case_sensitive=False) == UnitsContainer(joule=1) -class TestCaseInsensitiveRegistry(CaseInsensitveQuantityTestCase): +class TestCaseInsensitiveRegistry(QuantityTestCase): + + kwargs = dict(case_sensitive=False) + def test_case_sensitivity(self): ureg = self.ureg # Default - self.assertEqual(ureg.parse_units("Meter"), UnitsContainer(meter=1)) - self.assertEqual(ureg.parse_units("j"), UnitsContainer(joule=1)) + assert ureg.parse_units("Meter") == UnitsContainer(meter=1) + assert ureg.parse_units("j") == UnitsContainer(joule=1) # Force True - self.assertRaises( - UndefinedUnitError, ureg.parse_units, "Meter", case_sensitive=True - ) - self.assertRaises( - UndefinedUnitError, ureg.parse_units, "j", case_sensitive=True - ) + with pytest.raises(UndefinedUnitError): + ureg.parse_units("Meter", case_sensitive=True) + with pytest.raises(UndefinedUnitError): + ureg.parse_units("j", case_sensitive=True) # Force False - self.assertEqual( - ureg.parse_units("Meter", case_sensitive=False), UnitsContainer(meter=1) - ) - self.assertEqual( - ureg.parse_units("j", case_sensitive=False), UnitsContainer(joule=1) + assert ureg.parse_units("Meter", case_sensitive=False) == UnitsContainer( + meter=1 ) + assert ureg.parse_units("j", case_sensitive=False) == UnitsContainer(joule=1) class TestCompatibleUnits(QuantityTestCase): - FORCE_NDARRAY = False - - def setUp(self): - super().setUp() - self.ureg = UnitRegistry(force_ndarray=self.FORCE_NDARRAY) - self.Q_ = self.ureg.Quantity - self.U_ = self.ureg.Unit - def _test(self, input_units): gd = self.ureg.get_dimensionality dim = gd(input_units) equiv = self.ureg.get_compatible_units(input_units) for eq in equiv: - self.assertEqual(gd(eq), dim) - self.assertEqual(equiv, self.ureg.get_compatible_units(dim)) + assert gd(eq) == dim + assert equiv == self.ureg.get_compatible_units(dim) def _test2(self, units1, units2): equiv1 = self.ureg.get_compatible_units(units1) equiv2 = self.ureg.get_compatible_units(units2) - self.assertEqual(equiv1, equiv2) + assert equiv1 == equiv2 def test_many(self): self._test(self.ureg.meter) @@ -793,31 +774,30 @@ class TestCompatibleUnits(QuantityTestCase): for eq in equiv: dim = gd(eq) result.add(dim) - self.assertIn(dim, valid) + assert dim in valid - self.assertEqual(len(result), len(valid)) + assert len(result) == len(valid) def test_get_base_units(self): ureg = UnitRegistry() - self.assertEqual(ureg.get_base_units(""), (1, ureg.Unit(""))) - self.assertEqual(ureg.get_base_units("pi"), (math.pi, ureg.Unit(""))) - self.assertEqual(ureg.get_base_units("ln10"), (math.log(10), ureg.Unit(""))) - self.assertEqual( - ureg.get_base_units("meter"), ureg.get_base_units(ParserHelper(meter=1)) + assert ureg.get_base_units("") == (1, ureg.Unit("")) + assert ureg.get_base_units("pi") == (math.pi, ureg.Unit("")) + assert ureg.get_base_units("ln10") == (math.log(10), ureg.Unit("")) + assert ureg.get_base_units("meter") == ureg.get_base_units( + ParserHelper(meter=1) ) def test_get_compatible_units(self): ureg = UnitRegistry() - self.assertEqual(ureg.get_compatible_units(""), frozenset()) - self.assertEqual( - ureg.get_compatible_units("meter"), - ureg.get_compatible_units(ParserHelper(meter=1)), + assert ureg.get_compatible_units("") == frozenset() + assert ureg.get_compatible_units("meter") == ureg.get_compatible_units( + ParserHelper(meter=1) ) class TestRegistryWithDefaultRegistry(TestRegistry): @classmethod - def setUpClass(cls): + def setup_class(cls): from pint import _DEFAULT_REGISTRY cls.ureg = _DEFAULT_REGISTRY @@ -826,25 +806,31 @@ class TestRegistryWithDefaultRegistry(TestRegistry): def test_lazy(self): x = LazyRegistry() x.test = "test" - self.assertIsInstance(x, UnitRegistry) + assert isinstance(x, UnitRegistry) y = LazyRegistry() y("meter") - self.assertIsInstance(y, UnitRegistry) + assert isinstance(y, UnitRegistry) def test_redefinition(self): d = self.ureg.define - self.assertRaises(DefinitionSyntaxError, d, "meter = [time]") - self.assertRaises(RedefinitionError, d, "meter = [newdim]") - self.assertRaises(RedefinitionError, d, "kilo- = 1000") - self.assertRaises(RedefinitionError, d, "[speed] = [length]") + with pytest.raises(DefinitionSyntaxError): + d("meter = [time]") + with pytest.raises(RedefinitionError): + d("meter = [newdim]") + with pytest.raises(RedefinitionError): + d("kilo- = 1000") + with pytest.raises(RedefinitionError): + d("[speed] = [length]") # aliases - self.assertIn("inch", self.ureg._units) - self.assertRaises(RedefinitionError, d, "bla = 3.2 meter = inch") - self.assertRaises(RedefinitionError, d, "myk- = 1000 = kilo-") + assert "inch" in self.ureg._units + with pytest.raises(RedefinitionError): + d("bla = 3.2 meter = inch") + with pytest.raises(RedefinitionError): + d("myk- = 1000 = kilo-") -class TestConvertWithOffset(QuantityTestCase, ParameterizedTestCase): +class TestConvertWithOffset(QuantityTestCase): # The dicts in convert_with_offset are used to create a UnitsContainer. # We create UnitsContainer to avoid any auto-conversion of units. @@ -894,24 +880,24 @@ class TestConvertWithOffset(QuantityTestCase, ParameterizedTestCase): (({"degC": 1, "kelvin": 1}, {"kelvin": 2}), "error"), ] - @ParameterizedTestCase.parameterize( - ("input", "expected_output"), convert_with_offset - ) + @pytest.mark.parametrize(("input_tuple", "expected"), convert_with_offset) def test_to_and_from_offset_units(self, input_tuple, expected): src, dst = input_tuple src, dst = UnitsContainer(src), UnitsContainer(dst) value = 10.0 convert = self.ureg.convert if isinstance(expected, str): - self.assertRaises(DimensionalityError, convert, value, src, dst) + with pytest.raises(DimensionalityError): + convert(value, src, dst) if src != dst: - self.assertRaises(DimensionalityError, convert, value, dst, src) + with pytest.raises(DimensionalityError): + convert(value, dst, src) else: - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( convert(value, src, dst), expected, atol=0.001 ) if src != dst: - self.assertQuantityAlmostEqual( + helpers.assert_quantity_almost_equal( convert(expected, dst, src), value, atol=0.001 ) @@ -933,13 +919,17 @@ class TestConvertWithOffset(QuantityTestCase, ParameterizedTestCase): # Test that new aliases work # Test that pre-existing aliases and symbol are not eliminated for a in ("can", "alias1", "alias2", "alias3", "alias4", "alias5"): - self.assertEqual(ureg.Unit(a), ureg.Unit("canonical")) + assert ureg.Unit(a) == ureg.Unit("canonical") # Test that aliases defined multiple times are not duplicated - self.assertEqual( - ureg._units["canonical"].aliases, - ("alias1", "alias2", "alias3", "alias4", "alias5"), + assert ureg._units["canonical"].aliases == ( + "alias1", + "alias2", + "alias3", + "alias4", + "alias5", ) # Define against unknown name - self.assertRaises(KeyError, ureg.define, "@alias notexist = something") + with pytest.raises(KeyError): + ureg.define("@alias notexist = something") diff --git a/pint/testsuite/test_util.py b/pint/testsuite/test_util.py index 5f71173..d2eebe5 100644 --- a/pint/testsuite/test_util.py +++ b/pint/testsuite/test_util.py @@ -3,7 +3,8 @@ import copy import math import operator as op -from pint.testsuite import BaseTestCase, QuantityTestCase +import pytest + from pint.util import ( ParserHelper, UnitsContainer, @@ -19,7 +20,7 @@ from pint.util import ( ) -class TestUnitsContainer(QuantityTestCase): +class TestUnitsContainer: def _test_inplace(self, operator, value1, value2, expected_result): value1 = copy.copy(value1) value2 = copy.copy(value2) @@ -27,11 +28,11 @@ class TestUnitsContainer(QuantityTestCase): id2 = id(value2) value1 = operator(value1, value2) value2_cpy = copy.copy(value2) - self.assertEqual(value1, expected_result) + assert value1 == expected_result # Inplace operation creates copies - self.assertNotEqual(id1, id(value1)) - self.assertEqual(value2, value2_cpy) - self.assertEqual(id2, id(value2)) + assert id1 != id(value1) + assert value2 == value2_cpy + assert id2 == id(value2) def _test_not_inplace(self, operator, value1, value2, expected_result): id1 = id(value1) @@ -42,48 +43,48 @@ class TestUnitsContainer(QuantityTestCase): result = operator(value1, value2) - self.assertEqual(expected_result, result) - self.assertEqual(value1, value1_cpy) - self.assertEqual(value2, value2_cpy) - self.assertNotEqual(id(result), id1) - self.assertNotEqual(id(result), id2) + assert expected_result == result + assert value1 == value1_cpy + assert value2 == value2_cpy + assert id(result) != id1 + assert id(result) != id2 def test_unitcontainer_creation(self): x = UnitsContainer(meter=1, second=2) y = UnitsContainer({"meter": 1, "second": 2}) - self.assertIsInstance(x["meter"], int) - self.assertEqual(x, y) - self.assertIsNot(x, y) + assert isinstance(x["meter"], int) + assert x == y + assert x is not y z = copy.copy(x) - self.assertEqual(x, z) - self.assertIsNot(x, z) + assert x == z + assert x is not z z = UnitsContainer(x) - self.assertEqual(x, z) - self.assertIsNot(x, z) + assert x == z + assert x is not z def test_unitcontainer_repr(self): x = UnitsContainer() - self.assertEqual(str(x), "dimensionless") - self.assertEqual(repr(x), "<UnitsContainer({})>") + assert str(x) == "dimensionless" + assert repr(x) == "<UnitsContainer({})>" x = UnitsContainer(meter=1, second=2) - self.assertEqual(str(x), "meter * second ** 2") - self.assertEqual(repr(x), "<UnitsContainer({'meter': 1, 'second': 2})>") + assert str(x) == "meter * second ** 2" + assert repr(x) == "<UnitsContainer({'meter': 1, 'second': 2})>" x = UnitsContainer(meter=1, second=2.5) - self.assertEqual(str(x), "meter * second ** 2.5") - self.assertEqual(repr(x), "<UnitsContainer({'meter': 1, 'second': 2.5})>") + assert str(x) == "meter * second ** 2.5" + assert repr(x) == "<UnitsContainer({'meter': 1, 'second': 2.5})>" def test_unitcontainer_bool(self): - self.assertTrue(UnitsContainer(meter=1, second=2)) - self.assertFalse(UnitsContainer()) + assert UnitsContainer(meter=1, second=2) + assert not UnitsContainer() def test_unitcontainer_comp(self): x = UnitsContainer(meter=1, second=2) y = UnitsContainer(meter=1.0, second=2) z = UnitsContainer(meter=1, second=3) - self.assertTrue(x == y) - self.assertFalse(x != y) - self.assertFalse(x == z) - self.assertTrue(x != z) + assert x == y + assert not (x != y) + assert not (x == z) + assert x != z def test_unitcontainer_arithmetic(self): x = UnitsContainer(meter=1) @@ -104,72 +105,75 @@ class TestUnitsContainer(QuantityTestCase): x = UnitsContainer(meter=1) y = UnitsContainer(second=1) z = UnitsContainer(meter=1, second=-2) - self.assertEqual(x, "meter") - self.assertEqual("meter", x) - self.assertNotEqual(x, "meter ** 2") - self.assertNotEqual(x, "meter * meter") - self.assertNotEqual(x, "second") - self.assertEqual(y, "second") - self.assertEqual(z, "meter/second/second") + assert x == "meter" + assert "meter" == x + assert x != "meter ** 2" + assert x != "meter * meter" + assert x != "second" + assert y == "second" + assert z == "meter/second/second" def test_invalid(self): - self.assertRaises(TypeError, UnitsContainer, {1: 2}) - self.assertRaises(TypeError, UnitsContainer, {"1": "2"}) + with pytest.raises(TypeError): + UnitsContainer({1: 2}) + with pytest.raises(TypeError): + UnitsContainer({"1": "2"}) d = UnitsContainer() - self.assertRaises(TypeError, d.__mul__, list()) - self.assertRaises(TypeError, d.__pow__, list()) - self.assertRaises(TypeError, d.__truediv__, list()) - self.assertRaises(TypeError, d.__rtruediv__, list()) + with pytest.raises(TypeError): + d.__mul__(list()) + with pytest.raises(TypeError): + d.__pow__(list()) + with pytest.raises(TypeError): + d.__truediv__(list()) + with pytest.raises(TypeError): + d.__rtruediv__(list()) -class TestToUnitsContainer(BaseTestCase): +class TestToUnitsContainer: def test_str_conversion(self): - self.assertEqual(to_units_container("m"), UnitsContainer(m=1)) + assert to_units_container("m") == UnitsContainer(m=1) def test_uc_conversion(self): a = UnitsContainer(m=1) - self.assertIs(to_units_container(a), a) + assert to_units_container(a) is a def test_quantity_conversion(self): from pint.registry import UnitRegistry ureg = UnitRegistry() - self.assertEqual( - to_units_container(ureg.Quantity(1, UnitsContainer(m=1))), - UnitsContainer(m=1), - ) + assert to_units_container( + ureg.Quantity(1, UnitsContainer(m=1)) + ) == UnitsContainer(m=1) def test_unit_conversion(self): from pint import Unit - self.assertEqual( - to_units_container(Unit(UnitsContainer(m=1))), UnitsContainer(m=1) - ) + assert to_units_container(Unit(UnitsContainer(m=1))) == UnitsContainer(m=1) def test_dict_conversion(self): - self.assertEqual(to_units_container(dict(m=1)), UnitsContainer(m=1)) + assert to_units_container(dict(m=1)) == UnitsContainer(m=1) -class TestParseHelper(BaseTestCase): +class TestParseHelper: def test_basic(self): # Parse Helper ar mutables, so we build one everytime x = lambda: ParserHelper(1, meter=2) xp = lambda: ParserHelper(1, meter=2) y = lambda: ParserHelper(2, meter=2) - self.assertEqual(x(), xp()) - self.assertNotEqual(x(), y()) - self.assertEqual(ParserHelper.from_string(""), ParserHelper()) - self.assertEqual(repr(x()), "<ParserHelper(1, {'meter': 2})>") + assert x() == xp() + assert x() != y() + assert ParserHelper.from_string("") == ParserHelper() + assert repr(x()) == "<ParserHelper(1, {'meter': 2})>" - self.assertEqual(ParserHelper(2), 2) + assert ParserHelper(2) == 2 - self.assertEqual(x(), dict(meter=2)) - self.assertEqual(x(), "meter ** 2") - self.assertNotEqual(y(), dict(meter=2)) - self.assertNotEqual(y(), "meter ** 2") + assert x() == dict(meter=2) + assert x() == "meter ** 2" + assert y() != dict(meter=2) + assert y() != "meter ** 2" - self.assertNotEqual(xp(), object()) + assert xp() != object() def test_calculate(self): # Parse Helper ar mutables, so we build one everytime @@ -177,43 +181,43 @@ class TestParseHelper(BaseTestCase): y = lambda: ParserHelper(2.0, meter=-2) z = lambda: ParserHelper(2.0, meter=2) - self.assertEqual(x() * 4.0, ParserHelper(4.0, meter=2)) - self.assertEqual(x() * y(), ParserHelper(2.0)) - self.assertEqual(x() * "second", ParserHelper(1.0, meter=2, second=1)) + assert x() * 4.0 == ParserHelper(4.0, meter=2) + assert x() * y() == ParserHelper(2.0) + assert x() * "second" == ParserHelper(1.0, meter=2, second=1) - self.assertEqual(x() / 4.0, ParserHelper(0.25, meter=2)) - self.assertEqual(x() / "second", ParserHelper(1.0, meter=2, second=-1)) - self.assertEqual(x() / z(), ParserHelper(0.5)) + assert x() / 4.0 == ParserHelper(0.25, meter=2) + assert x() / "second" == ParserHelper(1.0, meter=2, second=-1) + assert x() / z() == ParserHelper(0.5) - self.assertEqual(4.0 / z(), ParserHelper(2.0, meter=-2)) - self.assertEqual("seconds" / z(), ParserHelper(0.5, seconds=1, meter=-2)) - self.assertEqual(dict(seconds=1) / z(), ParserHelper(0.5, seconds=1, meter=-2)) + assert 4.0 / z() == ParserHelper(2.0, meter=-2) + assert "seconds" / z() == ParserHelper(0.5, seconds=1, meter=-2) + assert dict(seconds=1) / z() == ParserHelper(0.5, seconds=1, meter=-2) def _test_eval_token(self, expected, expression, use_decimal=False): token = next(tokenizer(expression)) actual = ParserHelper.eval_token(token, use_decimal=use_decimal) - self.assertEqual(expected, actual) - self.assertEqual(type(expected), type(actual)) + assert expected == actual + assert type(expected) == type(actual) def test_eval_token(self): self._test_eval_token(1000.0, "1e3") self._test_eval_token(1000.0, "1E3") self._test_eval_token(1000, "1000") - def test_nan(self): + def test_nan(self, subtests): for s in ("nan", "NAN", "NaN", "123 NaN nan NAN 456"): - with self.subTest(s): + with subtests.test(s): p = ParserHelper.from_string(s + " kg") assert math.isnan(p.scale) - self.assertEqual(dict(p), {"kg": 1}) + assert dict(p) == {"kg": 1} -class TestStringProcessor(BaseTestCase): +class TestStringProcessor: def _test(self, bef, aft): for pattern in ("{}", "+{}+"): b = pattern.format(bef) a = pattern.format(aft) - self.assertEqual(string_preprocessor(b), a) + assert string_preprocessor(b) == a def test_square_cube(self): self._test("bcd^3", "bcd**3") @@ -267,95 +271,98 @@ class TestStringProcessor(BaseTestCase): self._test("water_60F", "water_60F") -class TestGraph(BaseTestCase): +class TestGraph: def test_start_not_in_graph(self): g = collections.defaultdict(set) g[1] = {2} g[2] = {3} - self.assertIs(find_connected_nodes(g, 9), None) + assert find_connected_nodes(g, 9) is None def test_shortest_path(self): g = collections.defaultdict(set) g[1] = {2} g[2] = {3} p = find_shortest_path(g, 1, 2) - self.assertEqual(p, [1, 2]) + assert p == [1, 2] p = find_shortest_path(g, 1, 3) - self.assertEqual(p, [1, 2, 3]) + assert p == [1, 2, 3] p = find_shortest_path(g, 3, 1) - self.assertIs(p, None) + assert p is None g = collections.defaultdict(set) g[1] = {2} g[2] = {3, 1} g[3] = {2} p = find_shortest_path(g, 1, 2) - self.assertEqual(p, [1, 2]) + assert p == [1, 2] p = find_shortest_path(g, 1, 3) - self.assertEqual(p, [1, 2, 3]) + assert p == [1, 2, 3] p = find_shortest_path(g, 3, 1) - self.assertEqual(p, [3, 2, 1]) + assert p == [3, 2, 1] p = find_shortest_path(g, 2, 1) - self.assertEqual(p, [2, 1]) + assert p == [2, 1] -class TestMatrix(BaseTestCase): +class TestMatrix: def test_matrix_to_string(self): - self.assertEqual( - matrix_to_string([[1, 2], [3, 4]], row_headers=None, col_headers=None), - "1\t2\n" "3\t4", + assert ( + matrix_to_string([[1, 2], [3, 4]], row_headers=None, col_headers=None) + == "1\t2\n" + "3\t4" ) - self.assertEqual( + assert ( matrix_to_string( [[1, 2], [3, 4]], row_headers=None, col_headers=None, fmtfun=lambda x: f"{x:.2f}", - ), - "1.00\t2.00\n" "3.00\t4.00", + ) + == "1.00\t2.00\n" + "3.00\t4.00" ) - self.assertEqual( - matrix_to_string( - [[1, 2], [3, 4]], row_headers=["c", "d"], col_headers=None - ), - "c\t1\t2\n" "d\t3\t4", + assert ( + matrix_to_string([[1, 2], [3, 4]], row_headers=["c", "d"], col_headers=None) + == "c\t1\t2\n" + "d\t3\t4" ) - self.assertEqual( - matrix_to_string( - [[1, 2], [3, 4]], row_headers=None, col_headers=["a", "b"] - ), - "a\tb\n" "1\t2\n" "3\t4", + assert ( + matrix_to_string([[1, 2], [3, 4]], row_headers=None, col_headers=["a", "b"]) + == "a\tb\n" + "1\t2\n" + "3\t4" ) - self.assertEqual( + assert ( matrix_to_string( [[1, 2], [3, 4]], row_headers=["c", "d"], col_headers=["a", "b"] - ), - "\ta\tb\n" "c\t1\t2\n" "d\t3\t4", + ) + == "\ta\tb\n" + "c\t1\t2\n" + "d\t3\t4" ) def test_transpose(self): - self.assertEqual(transpose([[1, 2], [3, 4]]), [[1, 3], [2, 4]]) + assert transpose([[1, 2], [3, 4]]) == [[1, 3], [2, 4]] -class TestOtherUtils(BaseTestCase): +class TestOtherUtils: def test_iterable(self): # Test with list, string, generator, and scalar - self.assertTrue(iterable([0, 1, 2, 3])) - self.assertTrue(iterable("test")) - self.assertTrue(iterable((i for i in range(5)))) - self.assertFalse(iterable(0)) + assert iterable([0, 1, 2, 3]) + assert iterable("test") + assert iterable((i for i in range(5))) + assert not iterable(0) def test_sized(self): # Test with list, string, generator, and scalar - self.assertTrue(sized([0, 1, 2, 3])) - self.assertTrue(sized("test")) - self.assertFalse(sized((i for i in range(5)))) - self.assertFalse(sized(0)) + assert sized([0, 1, 2, 3]) + assert sized("test") + assert not sized((i for i in range(5))) + assert not sized(0) @@ -38,7 +38,11 @@ scripts = pint/pint-convert [options.extras_require] numpy = numpy >= 1.14 uncertainties = uncertainties >= 3.0 -test = pytest; pytest-mpl; pytest-cov +test = + pytest + pytest-mpl + pytest-cov + pytest-subtests [options.package_data] pint = default_en.txt; constants_en.txt |