diff options
author | Hernan Grecco <hernan.grecco@gmail.com> | 2021-01-20 19:32:42 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-20 19:32:42 -0300 |
commit | b36d0a63ee24e7dada0cbf8b0499695ff57d17a8 (patch) | |
tree | 93dd3ec4249f278ca239828b6ea5a89a153de2ec | |
parent | 354839d7aa84eb6ba961b63f9a6c0d450555c368 (diff) | |
parent | 5efb97f11f0b47e98d70f5c4a3fdac13ca22d1c6 (diff) | |
download | pint-b36d0a63ee24e7dada0cbf8b0499695ff57d17a8.tar.gz |
Merge pull request #1235 from hgrecco/_pytest_migration
Pytest migration
29 files changed, 3236 insertions, 3191 deletions
diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3238d6f..0000000 --- a/.travis.yml +++ /dev/null @@ -1,83 +0,0 @@ -language: python - -branches: - # prevent bors temporary branches to be built - except: - - staging.tmp - - trying.tmp - -env: - # This project adheres to NEP-29 - # https://numpy.org/neps/nep-0029-deprecation_policy.html - - # Refer to https://docs.scipy.org/doc/numpy/release.html for - # min/max Python version supported by numpy - # Refer to history of https://github.com/lebigot/uncertainties/blob/master/setup.py - # for min/max Python versions supported by uncertainties - - - PKGS="python=3.8 pre-commit" - # Pinned packages to match readthedocs CI https://readthedocs.org/projects/pint/ - - PKGS="python=3.7 ipython matplotlib nbsphinx numpy pandas==1.1.3 jupyter_client ipykernel python-graphviz graphviz xarray sparse dask[complete] sphinx Pygments==2.3.1 docutils==0.14 alabaster commonmark==0.8.1 recommonmark==0.5.0 babel==2.8" - - PKGS="python=3.6" - - PKGS="python=3.7" - - PKGS="python=3.8" - - PKGS="python=3.6 uncertainties=3.0" - - PKGS="python=3.7 uncertainties=3.0" - - PKGS="python=3.6 numpy=1.14 matplotlib" - - PKGS="python=3.7 numpy=1.14 matplotlib" - - PKGS="python=3.8 numpy=1.17 matplotlib" - - PKGS="python=3.6 numpy=1.14 uncertainties=3.0" - - PKGS="python=3.7 numpy=1.14 uncertainties=3.0" - - PKGS="python=3.6 numpy uncertainties" - - PKGS="python=3.7 numpy uncertainties" - - PKGS="python=3.8 numpy uncertainties" - - PKGS="python=3.8 numpy uncertainties sparse xarray netCDF4" - - # TODO: pandas tests - # - PKGS="python=3.7 numpy pandas uncertainties pandas" - -before_install: - - sudo apt-get update - - wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh - - bash miniconda.sh -b -p $HOME/miniconda - - export PATH="$HOME/miniconda/bin:$PATH" - - hash -r - - conda config --set always_yes yes --set changeps1 no - - conda config --add channels conda-forge - - conda update -q conda - # Useful for debugging any issues with conda - - conda info -a - - # The next couple lines fix a crash with multiprocessing on Travis and are not specific to using Miniconda - # But broke travis 2019-08 - # - sudo rm -rf /dev/shm - # - sudo ln -s /run/shm /dev/shm - - export TEST_OPTS="-rfsxEX -s --cov=pint --cov-config=.coveragerc" - -install: - - conda create -n travis $PKGS pytest pytest-cov coveralls - - source activate travis - - if [[ $PKGS =~ pandas ]]; then PANDAS=1; else PANDAS=0; fi - - if [[ $PKGS =~ pre-commit ]]; then LINT=1; else LINT=0; fi - - if [[ $PKGS =~ sphinx ]]; then DOCS=1; else DOCS=0; fi - - if [[ $PKGS =~ matplotlib && $DOCS == 0 ]]; then pip install pytest-mpl; export TEST_OPTS="$TEST_OPTS --mpl"; fi - - if [[ $DOCS == 1 ]]; then pip install pint-pandas; fi - # this is superslow but suck it up until updates to pandas are made - # - if [[ $PANDAS == '1' ]]; then pip install numpy cython pytest pytest-cov nbval; pip install git+https://github.com/pandas-dev/pandas.git@bdb7a1603f1e0948ca0cab011987f616e7296167; python -c 'import pandas; print(pandas.__version__)'; fi - - conda list - - pip install . - -script: - # if we're doing the pandas tests and hence have pytest available, we can - # simply use it to run all the tests - # - if [[ $PANDAS == '1' ]]; then python -bb -m coverage run -p --source=pint --omit="*test*","*compat*" -m py.test -rfsxEX; fi - # test notebooks too if pandas available - # - if [[ $PANDAS == '1' ]]; then pip install -e .; pytest --nbval notebooks/*; fi - - if [[ $PANDAS == 0 && $LINT == 0 && $DOCS == 0 ]]; then python -bb -m pytest $TEST_OPTS; fi - - if [[ $LINT == 1 ]]; then pre-commit run --all-files; fi - - if [[ $DOCS == 1 ]]; then PYTHONPATH=$PWD sphinx-build -n -j auto -b html -d build/doctrees docs build/html; fi - - if [[ $DOCS == 1 ]]; then PYTHONPATH=$PWD sphinx-build -a -j auto -b doctest -d build/doctrees docs build/doctest; fi - - if [[ $LINT == 0 && $DOCS == 0 ]]; then coverage report -m; fi - -after_success: - - coveralls --verbose diff --git a/docs/contributing.rst b/docs/contributing.rst index 19157f1..841de0b 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -3,8 +3,17 @@ Contributing to Pint ==================== -You can contribute in different ways: +Pint uses (and thanks): +- github_ to host the code +- travis_ to test all commits and PRs. +- coveralls_ to monitor coverage test coverage +- readthedocs_ to host the documentation. +- `bors-ng`_ as a merge bot and therefore every PR is tested before merging. +- black_, isort_ and flake8_ as code linters and pre-commit_ to enforce them. +- pytest_ to write tests +- sphinx_ to write docs. +You can contribute in different ways: Report issues ------------- @@ -19,18 +28,23 @@ Contribute code To contribute fixes, code or documentation to Pint, fork Pint in github_ and submit the changes using a pull request against the **master** branch. -- If you are fixing a bug, add a test to test_issues.py, or amend/enrich the general - test suite to cover the use case. -- If you are submitting new code, add tests and documentation. +- If you are submitting new code, add tests (see below) and documentation. - Write "Closes #<bug number>" in the PR description or a comment, as described in the `github docs`_. - Log the change in the CHANGES file. -- Execute ``black -t py36 . && isort -rc . && flake8`` and resolve any issues. - -Pint uses `bors-ng` as a merge bot and therefore every PR is tested before merging. +- Execute ``pre-commit run --all-files`` and resolve any issues. In any case, feel free to use the `issue tracker`_ to discuss ideas for new features or improvements. +Notice that we will not merge a PR if tests are failing. In certain cases tests pass in your +machine but not in travis. There might be multiple reasons for this but these are some of +the most common + +- Your new code does not work for other Python or Numpy versions. +- The documentation is not being built properly or the examples in the docs are + not working. +- linters are reporting that the code does no adhere to the standards. + Setting up your environment --------------------------- @@ -44,6 +58,27 @@ environment on Linux or OSX with the following commands:: $ source venv/bin/activate $ pip install -e . $ pip install -r requirements_docs.txt + $ pip install pre-commit # This step and the next are optional but recommended. + $ pre-commit install + + +Writing tests +------------- + +We use pytest_ for testing. If you contribute code you need to add tests: + +- If you are fixing a bug, add a test to `test_issues.py`, or amend/enrich the general + test suite to cover the use case. +- If you are adding a new feature, add a test in the appropiate place. There is usually + a `test_X.py` for each `X.py` file. There are some other test files that deal with + individual/specific features. If in doubt, ask. +- Prefer functions to classes. +- When using classes, derive from `QuantityTestCase`. +- Use `parametrize` as much as possible. +- Use `fixtures` (see conftest.py) instead of instantiating the registry yourself. +- Checkout `helpers.py` for some convenience functions before reinventing the wheel. +- When your test does not modify the registry, use `sess_registry` fixture. + Running tests and building documentation ---------------------------------------- @@ -94,3 +129,12 @@ features that work best as an extension pacakage versus direct inclusion in Pint .. _`issue tracker`: https://github.com/hgrecco/pint/issues .. _`bors-ng`: https://github.com/bors-ng/bors-ng .. _`github docs`: https://help.github.com/articles/closing-issues-via-commit-messages/ +.. _travis: https://travis-ci.com/ +.. _coveralls: https://coveralls.io/ +.. _readthedocs: https://readthedocs.org/ +.. _pre-commit: https://pre-commit.com/ +.. _black: https://black.readthedocs.io/en/stable/ +.. _isort: https://pycqa.github.io/isort/ +.. _flake8: https://flake8.pycqa.org/en/latest/ +.. _pytest: https://docs.pytest.org/en/stable/ +.. _sphinx: https://www.sphinx-doc.org/en/master/
\ No newline at end of file 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 383914c..a0753f5 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 +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( - LooseVersion(NUMPY_VER) < LooseVersion(version), - "Requires NumPy < %s" % version, - ) - - -def requires_numpy_at_least(version): - if not HAS_NUMPY: - return unittest.skip("Requires NumPy") - return unittest.skipUnless( - LooseVersion(NUMPY_VER) >= LooseVersion(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,144 @@ 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 + + +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." +) + + +def requires_array_function_protocol(): + if not HAS_NUMPY: + return pytest.mark.skip("Requires NumPy") + return pytest.mark.skipif( + not HAS_NUMPY_ARRAY_FUNCTION, + reason="Requires __array_function__ protocol to be enabled", + ) + + +def requires_not_array_function_protocol(): + if not HAS_NUMPY: + return pytest.mark.skip("Requires NumPy") + return pytest.mark.skipif( + HAS_NUMPY_ARRAY_FUNCTION, + reason="Requires __array_function__ protocol to be unavailable or disabled", + ) + + +def requires_numpy_previous_than(version): + if not HAS_NUMPY: + return pytest.mark.skip("Requires NumPy") + return pytest.mark.skipif( + not LooseVersion(NUMPY_VER) < LooseVersion(version), + reason="Requires NumPy < %s" % version, + ) + + +def requires_numpy_at_least(version): + if not HAS_NUMPY: + return pytest.mark.skip("Requires NumPy") + return pytest.mark.skipif( + 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 df14b72..91070cf 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,265 @@ class TestDefinedContexts(QuantityTestCase): def g(wl): return wl.to("terahertz") - self.assertEqual(b, f(a)) - self.assertEqual(b, g(a)) + 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 math.isclose(q.to("USD", "c").magnitude, 10 * 1.18 * 1.11) + + +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"): + helpers.assert_quantity_almost_equal( + k.to("fahrenheit").magnitude, (100 - 255) * 9 / 5 + ) + helpers.assert_quantity_almost_equal(k.to("bogodegrees").magnitude, 100 / 9) + with subtests.test("nonmult_to_nonmult"): + with ureg.context("nonmult_to_nonmult"): + helpers.assert_quantity_almost_equal( + k.to("fahrenheit").magnitude, (100 - 123) / 7 + ) -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 + with subtests.test("nonmult_to_mult"): + with ureg.context("nonmult_to_mult"): + helpers.assert_quantity_almost_equal( + k.to("fahrenheit").magnitude, 100 / 123 + ) - @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() - ) + with subtests.test("mult_to_nonmult"): + with ureg.context("mult_to_nonmult"): + helpers.assert_quantity_almost_equal( + k.to("bogodegrees").magnitude, (100 - 123) / 5 + ) - q = ureg.Quantity("10 GBP") - self.assertEqual(q.magnitude, 10) - self.assertEqual(q.units.dimensionality, {"[currency]": 1}) - self.assertEqual(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.assertEqual(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() - ) - with self.assertRaises(ValueError) as e: - ureg.enable_contexts("c") - self.assertEqual( - str(e.exception), "Can't redefine a base unit to a derived one" - ) +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_change_base_unit(): + ureg = UnitRegistry( + """ + foo = [d1] + bar = [d2] + + @context c + bar = foo + @end + """.splitlines() + ) - 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.assertEqual( - str(e.exception), - "Can't change dimensionality of baz from [d1] to [d2] in a context", - ) + expected = "Can't redefine a base unit to a derived one" + with pytest.raises(ValueError, match=expected): + ureg.enable_contexts("c") - def test_err_cyclic_dependency(self): - 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. +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_dimensionality(): + ureg = UnitRegistry( + """ + foo = [d1] + bar = [d2] + baz = 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") - 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.assertEqual( - 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.assertEqual( - 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.assertEqual( - 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.assertEqual( - str(e.exception), "Can't redefine a unit with a prefix: kilopound" - ) +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") - 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.assertEqual(str(e.exception), "'bar' is not defined in the unit registry") + +def test_err_new_unit(): + ureg = UnitRegistry( + """ + foo = [d] + @context c + bar = foo + @end + """.splitlines() + ) + 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 ac2ccca..52309f2 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(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 410e576..620a12a 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 = [ # results 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..beea69d 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,8 +48,8 @@ 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): @@ -63,12 +66,12 @@ class TestNumpyArrayCreation(TestNumpyMethods): @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() 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,52 +88,58 @@ 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() 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() 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() 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() 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() 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() 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 ) @@ -141,8 +150,8 @@ class TestNumpyArrayManipulation(TestNumpyMethods): 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() def test_atleast_2d(self): @@ -152,8 +161,8 @@ 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() def test_atleast_3d(self): @@ -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() 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() 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() 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): + 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): + 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() 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,11 +265,11 @@ 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): @@ -268,10 +277,10 @@ class TestNumpyMathematicalFunctions(TestNumpyMethods): # Trigonometric functions @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 ) @@ -279,9 +288,9 @@ class TestNumpyMathematicalFunctions(TestNumpyMethods): @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, ) @@ -293,90 +302,106 @@ class TestNumpyMathematicalFunctions(TestNumpyMethods): 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() 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() 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() 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() 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() 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() 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() 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() 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 ) @@ -384,26 +409,26 @@ class TestNumpyMathematicalFunctions(TestNumpyMethods): 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() 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() 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() 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, ) @@ -412,19 +437,19 @@ class TestNumpyMathematicalFunctions(TestNumpyMethods): 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() 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,71 +516,72 @@ 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() 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 @@ -562,24 +593,24 @@ class TestNumpyUnclassified(TestNumpyMethods): 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() 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() 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,7 +618,8 @@ 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() def test_searchsorted_numpy_func(self): @@ -607,43 +639,45 @@ class TestNumpyUnclassified(TestNumpyMethods): @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() 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() 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() 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() 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() 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() def test_argmax_numpy_func(self): @@ -654,34 +688,34 @@ class TestNumpyUnclassified(TestNumpyMethods): 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() 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() 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() 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() 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() def test_argmin_numpy_func(self): @@ -692,85 +726,87 @@ class TestNumpyUnclassified(TestNumpyMethods): 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() 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() 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() 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() 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() 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() 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() 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() 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, @@ -778,86 +814,95 @@ class TestNumpyUnclassified(TestNumpyMethods): @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() 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() 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() 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() 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() 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,38 +964,38 @@ 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() 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() def test_alen_numpy_func(self): - self.assertEqual(np.alen(self.q), 2) + assert np.alen(self.q) == 2 @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() 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() 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() 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() 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, ) @@ -960,8 +1005,8 @@ class TestNumpyUnclassified(TestNumpyMethods): 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() def test_isclose_numpy_func(self): @@ -979,7 +1024,7 @@ class TestNumpyUnclassified(TestNumpyMethods): 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( @@ -1002,45 +1049,44 @@ class TestNumpyUnclassified(TestNumpyMethods): @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() 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") ) @@ -1065,70 +1111,76 @@ 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() 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() 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() 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() 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() 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() 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() 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() 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() 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 ) @@ -1138,43 +1190,42 @@ class TestNumpyUnclassified(TestNumpyMethods): 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_( [ @@ -1242,22 +1293,20 @@ class TestNumpyUnclassified(TestNumpyMethods): @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() 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 c1db505..0e2da2d 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,33 +534,33 @@ 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() @@ -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 9b36442..8c54d8f 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_programmatically(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 |