Repository: hgrecco/pint

Issue:
pint 0.18 does not allow to explicitly override "~" modifier in default_format
Hi, I see a change in the behavior from pint 0.17 to 0.18 which I think it might be a bug.

Consider the following code:

```python
from pint import UnitRegistry

ureg = UnitRegistry()
q = ureg.Quantity("1m")

print(f"implicit (before): {q}")
print(f"explicit (before): {q:d}")

ureg.default_format = "~"

print(f"implicit (after):  {q}")
print(f"explicit (after):  {q:d}")
```

With pint <=0.17 I get:
```
implicit (before): 1 meter
explicit (before): 1 meter
implicit (after):  1 m
explicit (after):  1 meter
```

With pint 0.18 I get:
```
implicit (before): 1 meter
explicit (before): 1 meter
implicit (after):  1 m
explicit (after):  1 m
```

IMHO, the behaviour of 0.17 is the expected one, since the default_format should not affect at all when a explicit format is used.

Discussion:

Patch:
diff --git a/CHANGES b/CHANGES
index 2de0a4e..7a2f80b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,7 @@ Pint Changelog
 0.19 (unreleased)
 -----------------
 
+- Deprecate the old format defaulting behavior and prepare for the new one (Issue #1407)
 - Fix a bug for offset units of higher dimension, e.g. gauge pressure.
   (Issue #1066, thanks dalito)
 - Fix type hints of function wrapper (Issue #1431)
@@ -16,6 +17,9 @@ Pint Changelog
 - Use default numpy `np.printoptions` available since numpy 1.15.
 - Implement `numpy.nanprod` (Issue #1369)
 - Fix default_format ignored for measurement (Issue #1456)
+- Add `pint.testing` with functions to compare pint objects in tests (Issue #1421).
+- Fix handling modulo & floordiv operator in pint_eval (Issue #1470)
+- Fix `to_compact` and `infer_base_unit` for non-float non_int_type.
 
 ### Breaking Changes
 
diff --git a/docs/contributing.rst b/docs/contributing.rst
index 46ee6d6..ad2914f 100644
--- a/docs/contributing.rst
+++ b/docs/contributing.rst
@@ -77,8 +77,12 @@ We use pytest_ for testing. If you contribute code you need to add tests:
 - 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.
+  Check out the existing fixtures before creating your own.
 - When your test does not modify the registry, use `sess_registry` fixture.
+- **Do not** create a unit registry outside a test or fixture setup.
+- If you need a specific registry, and you need to reuse it create a
+  fixture in your test module called `local_registry` or similar.
+- Checkout `helpers.py` for some convenience functions before reinventing the wheel.
 
 
 Running tests and building documentation
diff --git a/docs/developers_reference.rst b/docs/developers_reference.rst
index f2be046..02f114e 100644
--- a/docs/developers_reference.rst
+++ b/docs/developers_reference.rst
@@ -50,6 +50,9 @@ All Modules
 .. automodule:: pint.systems
     :members:
 
+.. automodule:: pint.testing
+    :members:
+
 .. automodule:: pint.unit
     :members:
 
diff --git a/docs/formatting.rst b/docs/formatting.rst
index 74fb8bd..5b4c91f 100644
--- a/docs/formatting.rst
+++ b/docs/formatting.rst
@@ -20,16 +20,45 @@ specifications <formatspec>`. The basic format is:
 
 where each part is optional and the order of these is arbitrary.
 
-In case any part (except the modifier) is omitted, the corresponding value in
-:py:attr:`Quantity.default_format` or :py:attr:`Unit.default_format` is filled in. If
-that is not set (it evaluates to ``False``), :py:attr:`UnitRegistry.default_format` is
-used.  If both are not set, the global default of ``"D"`` and the magnitude's default
+In case the format is omitted, the corresponding value in the object's
+``.default_format`` attribute (:py:attr:`Quantity.default_format` or
+:py:attr:`Unit.default_format`) is filled in. For example:
+
+.. ipython::
+
+   In [1]: ureg = pint.UnitRegistry()
+      ...: ureg.default_format = "~P"
+
+   In [2]: u = ureg.Unit("m ** 2 / s ** 2")
+      ...: f"{u}"
+
+   In [3]: u.default_format = "~C"
+      ...: f"{u}"
+
+   In [4]: u.default_format, ureg.default_format
+
+   In [5]: q = ureg.Quantity(1.25, "m ** 2 / s ** 2")
+      ...: f"{q}"
+
+   In [6]: q.default_format = ".3fP"
+      ...: f"{q}"
+
+   In [7]: q.default_format, ureg.default_format
+
+.. note::
+
+   In the future, the magnitude and unit format spec will be evaluated
+   independently, such that with a global default of
+   ``ureg.default_format = ".3f"`` and ``f"{q:P}`` the format that
+   will be used is ``".3fP"``.
+
+If both are not set, the global default of ``"D"`` and the magnitude's default
 format are used instead.
 
 .. note::
 
    Modifiers may be used without specifying any format: ``"~"`` is a valid format
-   specification.
+   specification and is equal to ``"~D"``.
 
 
 Unit Format Specifications
diff --git a/pint/formatting.py b/pint/formatting.py
index a04205d..5a458db 100644
--- a/pint/formatting.py
+++ b/pint/formatting.py
@@ -455,14 +455,20 @@ def siunitx_format_unit(units, registry):
 def extract_custom_flags(spec):
     import re
 
-    flag_re = re.compile("(" + "|".join(list(_FORMATTERS.keys()) + ["~"]) + ")")
+    if not spec:
+        return ""
+
+    # sort by length, with longer items first
+    known_flags = sorted(_FORMATTERS.keys(), key=len, reverse=True)
+
+    flag_re = re.compile("(" + "|".join(known_flags + ["~"]) + ")")
     custom_flags = flag_re.findall(spec)
 
     return "".join(custom_flags)
 
 
 def remove_custom_flags(spec):
-    for flag in list(_FORMATTERS.keys()) + ["~"]:
+    for flag in sorted(_FORMATTERS.keys(), key=len, reverse=True) + ["~"]:
         if flag:
             spec = spec.replace(flag, "")
     return spec
diff --git a/pint/pint_eval.py b/pint/pint_eval.py
index 0d16c63..77fe243 100644
--- a/pint/pint_eval.py
+++ b/pint/pint_eval.py
@@ -20,7 +20,9 @@ _OP_PRIORITY = {
     "unary": 2,
     "*": 1,
     "": 1,  # operator for implicit ops
+    "//": 1,
     "/": 1,
+    "%": 1,
     "+": 0,
     "-": 0,
 }
@@ -48,6 +50,8 @@ _BINARY_OPERATOR_MAP = {
     "/": operator.truediv,
     "+": operator.add,
     "-": operator.sub,
+    "%": operator.mod,
+    "//": operator.floordiv,
 }
 
 _UNARY_OPERATOR_MAP = {"+": lambda x: x, "-": lambda x: x * -1}
diff --git a/pint/quantity.py b/pint/quantity.py
index 1305a56..e742874 100644
--- a/pint/quantity.py
+++ b/pint/quantity.py
@@ -345,18 +345,47 @@ class Quantity(PrettyIPython, SharedRegistryObject, Generic[_MagnitudeType]):
         if self._REGISTRY.fmt_locale is not None:
             return self.format_babel(spec)
 
-        spec = spec or self.default_format
+        mspec = remove_custom_flags(spec)
+        uspec = extract_custom_flags(spec)
+
+        default_mspec = remove_custom_flags(self.default_format)
+        default_uspec = extract_custom_flags(self.default_format)
+        if spec:
+            if not uspec and default_uspec:
+                warnings.warn(
+                    (
+                        "The given format spec does not contain a unit formatter."
+                        " Falling back to the builtin defaults, but in the future"
+                        " the unit formatter specified in the `default_format`"
+                        " attribute will be used instead."
+                    ),
+                    DeprecationWarning,
+                )
+            if not mspec and default_mspec:
+                warnings.warn(
+                    (
+                        "The given format spec does not contain a magnitude formatter."
+                        " Falling back to the builtin defaults, but in the future"
+                        " the magnitude formatter specified in the `default_format`"
+                        " attribute will be used instead."
+                    ),
+                    DeprecationWarning,
+                )
+        else:
+            mspec, uspec = default_mspec, default_uspec
 
         # If Compact is selected, do it at the beginning
         if "#" in spec:
-            spec = spec.replace("#", "")
+            # TODO: don't replace '#'
+            mspec = mspec.replace("#", "")
+            uspec = uspec.replace("#", "")
             obj = self.to_compact()
         else:
             obj = self
 
-        if "L" in spec:
+        if "L" in uspec:
             allf = plain_allf = r"{}\ {}"
-        elif "H" in spec:
+        elif "H" in uspec:
             allf = plain_allf = "{} {}"
             if iterable(obj.magnitude):
                 # Use HTML table instead of plain text template for array-likes
@@ -370,20 +399,19 @@ class Quantity(PrettyIPython, SharedRegistryObject, Generic[_MagnitudeType]):
         else:
             allf = plain_allf = "{} {}"
 
-        if "Lx" in spec:
+        if "Lx" in uspec:
             # the LaTeX siunitx code
-            spec = spec.replace("Lx", "")
             # TODO: add support for extracting options
             opts = ""
             ustr = siunitx_format_unit(obj.units._units, obj._REGISTRY)
             allf = r"\SI[%s]{{{}}}{{{}}}" % opts
         else:
             # Hand off to unit formatting
-            uspec = extract_custom_flags(spec)
-            ustr = format(obj.units, uspec)
+            # TODO: only use `uspec` after completing the deprecation cycle
+            ustr = format(obj.units, mspec + uspec)
 
-        mspec = remove_custom_flags(spec)
-        if "H" in spec:
+        # mspec = remove_custom_flags(spec)
+        if "H" in uspec:
             # HTML formatting
             if hasattr(obj.magnitude, "_repr_html_"):
                 # If magnitude has an HTML repr, nest it within Pint's
@@ -417,7 +445,7 @@ class Quantity(PrettyIPython, SharedRegistryObject, Generic[_MagnitudeType]):
                         + "</pre>"
                     )
         elif isinstance(self.magnitude, ndarray):
-            if "L" in spec:
+            if "L" in uspec:
                 # Use ndarray LaTeX special formatting
                 mstr = ndarray_to_latex(obj.magnitude, mspec)
             else:
@@ -432,12 +460,12 @@ class Quantity(PrettyIPython, SharedRegistryObject, Generic[_MagnitudeType]):
         else:
             mstr = format(obj.magnitude, mspec).replace("\n", "")
 
-        if "L" in spec:
+        if "L" in uspec:
             mstr = self._exp_pattern.sub(r"\1\\times 10^{\2\3}", mstr)
-        elif "H" in spec or "P" in spec:
+        elif "H" in uspec or "P" in uspec:
             m = self._exp_pattern.match(mstr)
             _exp_formatter = (
-                _pretty_fmt_exponent if "P" in spec else lambda s: f"<sup>{s}</sup>"
+                _pretty_fmt_exponent if "P" in uspec else lambda s: f"<sup>{s}</sup>"
             )
             if m:
                 exp = int(m.group(2) + m.group(3))
@@ -635,6 +663,8 @@ class Quantity(PrettyIPython, SharedRegistryObject, Generic[_MagnitudeType]):
         -------
         bool
         """
+        from .unit import Unit
+
         if contexts or self._REGISTRY._active_ctx:
             try:
                 self.to(other, *contexts, **ctx_kwargs)
@@ -642,7 +672,7 @@ class Quantity(PrettyIPython, SharedRegistryObject, Generic[_MagnitudeType]):
             except DimensionalityError:
                 return False
 
-        if isinstance(other, (self._REGISTRY.Quantity, self._REGISTRY.Unit)):
+        if isinstance(other, (Quantity, Unit)):
             return self.dimensionality == other.dimensionality
 
         if isinstance(other, str):
@@ -851,9 +881,9 @@ class Quantity(PrettyIPython, SharedRegistryObject, Generic[_MagnitudeType]):
         SI_bases = [item[1] for item in SI_prefixes_list]
 
         if unit is None:
-            unit = infer_base_unit(self)
+            unit = infer_base_unit(self, registry=self._REGISTRY)
         else:
-            unit = infer_base_unit(self.__class__(1, unit))
+            unit = infer_base_unit(self.__class__(1, unit), registry=self._REGISTRY)
 
         q_base = self.to(unit)
 
@@ -868,9 +898,9 @@ class Quantity(PrettyIPython, SharedRegistryObject, Generic[_MagnitudeType]):
             unit_str, unit_power = units[0]
 
         if unit_power > 0:
-            power = math.floor(math.log10(abs(magnitude)) / unit_power / 3) * 3
+            power = math.floor(math.log10(abs(magnitude)) / float(unit_power) / 3) * 3
         else:
-            power = math.ceil(math.log10(abs(magnitude)) / unit_power / 3) * 3
+            power = math.ceil(math.log10(abs(magnitude)) / float(unit_power) / 3) * 3
 
         index = bisect.bisect_left(SI_powers, power)
 
diff --git a/pint/unit.py b/pint/unit.py
index 367c7fd..18a22de 100644
--- a/pint/unit.py
+++ b/pint/unit.py
@@ -80,7 +80,7 @@ class Unit(PrettyIPython, SharedRegistryObject):
         return "<Unit('{}')>".format(self._units)
 
     def __format__(self, spec) -> str:
-        spec = spec or extract_custom_flags(self.default_format)
+        spec = extract_custom_flags(spec or self.default_format)
         if "~" in spec:
             if not self._units:
                 return ""
@@ -168,6 +168,8 @@ class Unit(PrettyIPython, SharedRegistryObject):
         -------
         bool
         """
+        from .quantity import Quantity
+
         if contexts or self._REGISTRY._active_ctx:
             try:
                 (1 * self).to(other, *contexts, **ctx_kwargs)
@@ -175,7 +177,7 @@ class Unit(PrettyIPython, SharedRegistryObject):
             except DimensionalityError:
                 return False
 
-        if isinstance(other, (self._REGISTRY.Quantity, self._REGISTRY.Unit)):
+        if isinstance(other, (Quantity, Unit)):
             return self.dimensionality == other.dimensionality
 
         if isinstance(other, str):
diff --git a/pint/util.py b/pint/util.py
index 6a8c2f9..d72f15f 100644
--- a/pint/util.py
+++ b/pint/util.py
@@ -906,29 +906,50 @@ def to_units_container(
             return UnitsContainer(unit_like)
 
 
-def infer_base_unit(q):
+def infer_base_unit(
+    unit_like: Union[UnitLike, Quantity], registry: Optional[BaseRegistry] = None
+) -> UnitsContainer:
     """
+    Given a Quantity or UnitLike, give the UnitsContainer for it's base units.
 
     Parameters
     ----------
-    q :
+    unit_like : Union[UnitLike, Quantity]
+        Quantity or Unit to infer the base units from.
 
+    registry: Optional[BaseRegistry]
+        If provided, uses the registry's UnitsContainer and parse_unit_name.  If None,
+        uses the registry attached to unit_like.
 
     Returns
     -------
-    type
+    UnitsContainer
 
+    Raises
+    ------
+    ValueError
+        The unit_like did not reference a registry, and no registry was provided.
 
     """
     d = udict()
-    for unit_name, power in q._units.items():
-        candidates = q._REGISTRY.parse_unit_name(unit_name)
+
+    original_units = to_units_container(unit_like, registry)
+
+    if registry is None and hasattr(unit_like, "_REGISTRY"):
+        registry = unit_like._REGISTRY
+    if registry is None:
+        raise ValueError("No registry provided.")
+
+    for unit_name, power in original_units.items():
+        candidates = registry.parse_unit_name(unit_name)
         assert len(candidates) == 1
         _, base_unit, _ = candidates[0]
         d[base_unit] += power
 
     # remove values that resulted in a power of 0
-    return UnitsContainer({k: v for k, v in d.items() if v != 0})
+    nonzero_dict = {k: v for k, v in d.items() if v != 0}
+
+    return registry.UnitsContainer(nonzero_dict)
 
 
 def getattr_maybe_raise(self, item):


Test patch:
diff --git a/pint/testing.py b/pint/testing.py
new file mode 100644
index 0000000..3334675
--- /dev/null
+++ b/pint/testing.py
@@ -0,0 +1,90 @@
+import math
+import warnings
+from numbers import Number
+
+from .compat import ndarray
+from .quantity import Quantity
+
+try:
+    import numpy as np
+except ImportError:
+    np = None
+
+
+def _get_comparable_magnitudes(first, second, msg):
+    if isinstance(first, Quantity) and isinstance(second, Quantity):
+        ctx = first._REGISTRY._active_ctx.contexts
+        if first.is_compatible_with(second, *ctx):
+            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_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): Magnitudes are not equal" % (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_allclose(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
diff --git a/pint/testsuite/conftest.py b/pint/testsuite/conftest.py
index 529c33f..97a944c 100644
--- a/pint/testsuite/conftest.py
+++ b/pint/testsuite/conftest.py
@@ -59,6 +59,12 @@ def class_registry():
     return pint.UnitRegistry()
 
 
+@pytest.fixture(scope="module")
+def module_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."""
diff --git a/pint/testsuite/helpers.py b/pint/testsuite/helpers.py
index a0753f5..d72b5a3 100644
--- a/pint/testsuite/helpers.py
+++ b/pint/testsuite/helpers.py
@@ -1,15 +1,12 @@
 import doctest
-import math
 import pickle
 import re
-import warnings
 from distutils.version import LooseVersion
-from numbers import Number
 
 import pytest
 
-from pint import Quantity
-from pint.compat import ndarray, np
+from pint.testing import assert_allclose as assert_quantity_almost_equal  # noqa: F401
+from pint.testing import assert_equal as assert_quantity_equal  # noqa: F401
 
 from ..compat import (
     HAS_BABEL,
@@ -88,83 +85,6 @@ class PintOutputChecker(doctest.OutputChecker):
         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."
diff --git a/pint/testsuite/test_compat_downcast.py b/pint/testsuite/test_compat_downcast.py
index a47f168..3fcf871 100644
--- a/pint/testsuite/test_compat_downcast.py
+++ b/pint/testsuite/test_compat_downcast.py
@@ -7,13 +7,37 @@ np = pytest.importorskip("numpy", reason="NumPy is not available")
 sparse = pytest.importorskip("sparse", reason="sparse is not available")
 da = pytest.importorskip("dask.array", reason="Dask is not available")
 
-# Set up unit registry and sample
-ureg = UnitRegistry(force_ndarray_like=True)
-q_base = (np.arange(25).reshape(5, 5).T + 1) * ureg.kg
+
+def WR(func):
+    """Function to wrap another containing 1 argument.
+    Used to parametrize tests in which some cases depend
+    on the registry while avoiding to create it at the module level
+    """
+    return lambda ureg, x: func(x)
+
+
+def WR2(func):
+    """Function to wrap another containing 2 argument.
+    Used to parametrize tests in which some cases depend
+    on the registry while avoiding to create it at the module level
+    """
+    return lambda ureg, x, y: func(x, y)
+
+
+@pytest.fixture(scope="module")
+def local_registry():
+    # Set up unit registry and sample
+    return UnitRegistry(force_ndarray_like=True)
+
+
+@pytest.fixture(scope="module")
+def q_base(local_registry):
+    # Set up unit registry and sample
+    return (np.arange(25).reshape(5, 5).T + 1) * local_registry.kg
 
 
 # Define identity function for use in tests
-def identity(x):
+def identity(ureg, x):
     return x
 
 
@@ -40,52 +64,77 @@ def array(request):
     [
         pytest.param(identity, identity, identity, id="identity"),
         pytest.param(
-            lambda x: x + 1 * ureg.m, lambda x: x + 1, identity, id="addition"
+            lambda ureg, x: x + 1 * ureg.m,
+            lambda ureg, x: x + 1,
+            identity,
+            id="addition",
         ),
         pytest.param(
-            lambda x: x - 20 * ureg.cm, lambda x: x - 0.2, identity, id="subtraction"
+            lambda ureg, x: x - 20 * ureg.cm,
+            lambda ureg, x: x - 0.2,
+            identity,
+            id="subtraction",
         ),
         pytest.param(
-            lambda x: x * (2 * ureg.s),
-            lambda x: 2 * x,
-            lambda u: u * ureg.s,
+            lambda ureg, x: x * (2 * ureg.s),
+            lambda ureg, x: 2 * x,
+            lambda ureg, u: u * ureg.s,
             id="multiplication",
         ),
         pytest.param(
-            lambda x: x / (1 * ureg.s), identity, lambda u: u / ureg.s, id="division"
+            lambda ureg, x: x / (1 * ureg.s),
+            identity,
+            lambda ureg, u: u / ureg.s,
+            id="division",
+        ),
+        pytest.param(
+            WR(lambda x: x ** 2),
+            WR(lambda x: x ** 2),
+            WR(lambda u: u ** 2),
+            id="square",
         ),
-        pytest.param(lambda x: x ** 2, lambda x: x ** 2, lambda u: u ** 2, id="square"),
-        pytest.param(lambda x: x.T, lambda x: x.T, identity, id="transpose"),
-        pytest.param(np.mean, np.mean, identity, id="mean ufunc"),
-        pytest.param(np.sum, np.sum, identity, id="sum ufunc"),
-        pytest.param(np.sqrt, np.sqrt, lambda u: u ** 0.5, id="sqrt ufunc"),
+        pytest.param(WR(lambda x: x.T), WR(lambda x: x.T), identity, id="transpose"),
+        pytest.param(WR(np.mean), WR(np.mean), identity, id="mean ufunc"),
+        pytest.param(WR(np.sum), WR(np.sum), identity, id="sum ufunc"),
+        pytest.param(WR(np.sqrt), WR(np.sqrt), WR(lambda u: u ** 0.5), id="sqrt ufunc"),
         pytest.param(
-            lambda x: np.reshape(x, (25,)),
-            lambda x: np.reshape(x, (25,)),
+            WR(lambda x: np.reshape(x, (25,))),
+            WR(lambda x: np.reshape(x, (25,))),
             identity,
             id="reshape function",
         ),
-        pytest.param(np.amax, np.amax, identity, id="amax function"),
+        pytest.param(WR(np.amax), WR(np.amax), identity, id="amax function"),
     ],
 )
-def test_univariate_op_consistency(op, magnitude_op, unit_op, array):
-    q = ureg.Quantity(array, "meter")
-    res = op(q)
-    assert np.all(res.magnitude == magnitude_op(array))  # Magnitude check
-    assert res.units == unit_op(q.units)  # Unit check
+def test_univariate_op_consistency(
+    local_registry, q_base, op, magnitude_op, unit_op, array
+):
+
+    q = local_registry.Quantity(array, "meter")
+    res = op(local_registry, q)
+    assert np.all(
+        res.magnitude == magnitude_op(local_registry, array)
+    )  # Magnitude check
+    assert res.units == unit_op(local_registry, q.units)  # Unit check
     assert q.magnitude is array  # Immutability check
 
 
 @pytest.mark.parametrize(
     "op, unit",
     [
-        pytest.param(lambda x, y: x * y, ureg("kg m"), id="multiplication"),
-        pytest.param(lambda x, y: x / y, ureg("m / kg"), id="division"),
-        pytest.param(np.multiply, ureg("kg m"), id="multiply ufunc"),
+        pytest.param(
+            lambda x, y: x * y, lambda ureg: ureg("kg m"), id="multiplication"
+        ),
+        pytest.param(lambda x, y: x / y, lambda ureg: ureg("m / kg"), id="division"),
+        pytest.param(np.multiply, lambda ureg: ureg("kg m"), id="multiply ufunc"),
     ],
 )
-def test_bivariate_op_consistency(op, unit, array):
-    q = ureg.Quantity(array, "meter")
+def test_bivariate_op_consistency(local_registry, q_base, op, unit, array):
+
+    # This is to avoid having a ureg built at the module level.
+    unit = unit(local_registry)
+
+    q = local_registry.Quantity(array, "meter")
     res = op(q, q_base)
     assert np.all(res.magnitude == op(array, q_base.magnitude))  # Magnitude check
     assert res.units == unit  # Unit check
@@ -96,16 +145,24 @@ def test_bivariate_op_consistency(op, unit, array):
     "op",
     [
         pytest.param(
-            lambda a, u: a * u,
+            WR2(lambda a, u: a * u),
             id="array-first",
             marks=pytest.mark.xfail(reason="upstream issue numpy/numpy#15200"),
         ),
-        pytest.param(lambda a, u: u * a, id="unit-first"),
+        pytest.param(WR2(lambda a, u: u * a), id="unit-first"),
     ],
 )
 @pytest.mark.parametrize(
     "unit",
-    [pytest.param(ureg.m, id="Unit"), pytest.param(ureg("meter"), id="Quantity")],
+    [
+        pytest.param(lambda ureg: ureg.m, id="Unit"),
+        pytest.param(lambda ureg: ureg("meter"), id="Quantity"),
+    ],
 )
-def test_array_quantity_creation_by_multiplication(op, unit, array):
-    assert type(op(array, unit)) == ureg.Quantity
+def test_array_quantity_creation_by_multiplication(
+    local_registry, q_base, op, unit, array
+):
+    # This is to avoid having a ureg built at the module level.
+    unit = unit(local_registry)
+
+    assert type(op(local_registry, array, unit)) == local_registry.Quantity
diff --git a/pint/testsuite/test_compat_upcast.py b/pint/testsuite/test_compat_upcast.py
index c789a26..a1ed897 100644
--- a/pint/testsuite/test_compat_upcast.py
+++ b/pint/testsuite/test_compat_upcast.py
@@ -1,19 +1,19 @@
 import pytest
 
-from pint import UnitRegistry
-
 # Conditionally import NumPy and any upcast type libraries
 np = pytest.importorskip("numpy", reason="NumPy is not available")
 xr = pytest.importorskip("xarray", reason="xarray is not available")
 
-# Set up unit registry and sample
-ureg = UnitRegistry()
-q = [[1.0, 2.0], [3.0, 4.0]] * ureg.m
+
+@pytest.fixture(scope="module")
+def q_base(module_registry):
+    # Set up unit registry and sample
+    return [[1.0, 2.0], [3.0, 4.0]] * module_registry.m
 
 
 @pytest.fixture
-def da():
-    return xr.DataArray(q.copy())
+def da(q_base):
+    return xr.DataArray(q_base.copy())
 
 
 @pytest.fixture
@@ -31,19 +31,19 @@ def ds():
     )
 
 
-def test_xarray_quantity_creation():
+def test_xarray_quantity_creation(module_registry, q_base):
     with pytest.raises(TypeError) as exc:
-        ureg.Quantity(xr.DataArray(np.arange(4)), "m")
+        module_registry.Quantity(xr.DataArray(np.arange(4)), "m")
         assert "Quantity cannot wrap upcast type" in str(exc)
-    assert xr.DataArray(q).data is q
+    assert xr.DataArray(q_base).data is q_base
 
 
-def test_quantification(ds):
+def test_quantification(module_registry, ds):
     da = ds["a"]
-    da.data = ureg.Quantity(da.values, da.attrs.pop("units"))
+    da.data = module_registry.Quantity(da.values, da.attrs.pop("units"))
     mean = da.mean().item()
-    assert mean.units == ureg.K
-    assert np.isclose(mean, 2.5 * ureg.K)
+    assert mean.units == module_registry.K
+    assert np.isclose(mean, 2.5 * module_registry.K)
 
 
 @pytest.mark.parametrize(
@@ -58,71 +58,72 @@ def test_quantification(ds):
 @pytest.mark.parametrize(
     "pair",
     [
-        (q, xr.DataArray(q)),
+        (lambda ureg, q: q, lambda ureg, q: xr.DataArray(q)),
         (
-            xr.DataArray([1.0, 2.0] * ureg.m, dims=("y",)),
-            xr.DataArray(
+            lambda ureg, q: xr.DataArray([1.0, 2.0] * ureg.m, dims=("y",)),
+            lambda ureg, q: xr.DataArray(
                 np.arange(6, dtype="float").reshape(3, 2, 1), dims=("z", "y", "x")
             )
             * ureg.km,
         ),
-        (1 * ureg.m, xr.DataArray(q)),
+        (lambda ureg, q: 1 * ureg.m, lambda ureg, q: xr.DataArray(q)),
     ],
 )
-def test_binary_arithmetic_commutativity(op, pair):
+def test_binary_arithmetic_commutativity(module_registry, q_base, op, pair):
+    pair = tuple(p(module_registry, q_base) for p in pair)
     z0 = op(*pair)
     z1 = op(*pair[::-1])
     z1 = z1.transpose(*z0.dims)
     assert np.all(np.isclose(z0.data, z1.data.to(z0.data.units)))
 
 
-def test_eq_commutativity(da):
-    assert np.all((q.T == da) == (da.transpose() == q))
+def test_eq_commutativity(da, q_base):
+    assert np.all((q_base.T == da) == (da.transpose() == q_base))
 
 
-def test_ne_commutativity(da):
-    assert np.all((q != da.transpose()) == (da != q.T))
+def test_ne_commutativity(da, q_base):
+    assert np.all((q_base != da.transpose()) == (da != q_base.T))
 
 
-def test_dataset_operation_with_unit(ds):
-    ds0 = ureg.K * ds.isel(x=0)
-    ds1 = (ds * ureg.K).isel(x=0)
+def test_dataset_operation_with_unit(ds, module_registry):
+    ds0 = module_registry.K * ds.isel(x=0)
+    ds1 = (ds * module_registry.K).isel(x=0)
     xr.testing.assert_identical(ds0, ds1)
-    assert np.isclose(ds0["a"].mean().item(), 0.5 * ureg.K)
+    assert np.isclose(ds0["a"].mean().item(), 0.5 * module_registry.K)
 
 
-def test_dataarray_inplace_arithmetic_roundtrip(da):
+def test_dataarray_inplace_arithmetic_roundtrip(da, module_registry, q_base):
     da_original = da.copy()
-    q_to_modify = q.copy()
-    da += q
-    xr.testing.assert_identical(da, xr.DataArray([[2, 4], [6, 8]] * ureg.m))
-    da -= q
+    q_to_modify = q_base.copy()
+    da += q_base
+    xr.testing.assert_identical(da, xr.DataArray([[2, 4], [6, 8]] * module_registry.m))
+    da -= q_base
     xr.testing.assert_identical(da, da_original)
-    da *= ureg.m
-    xr.testing.assert_identical(da, xr.DataArray(q * ureg.m))
-    da /= ureg.m
+    da *= module_registry.m
+    xr.testing.assert_identical(da, xr.DataArray(q_base * module_registry.m))
+    da /= module_registry.m
     xr.testing.assert_identical(da, da_original)
     # Operating inplace with DataArray converts to DataArray
     q_to_modify += da
     q_to_modify -= da
-    assert np.all(np.isclose(q_to_modify.data, q))
+    assert np.all(np.isclose(q_to_modify.data, q_base))
 
 
-def test_dataarray_inequalities(da):
+def test_dataarray_inequalities(da, module_registry):
     xr.testing.assert_identical(
-        2 * ureg.m > da, xr.DataArray([[True, False], [False, False]])
+        2 * module_registry.m > da, xr.DataArray([[True, False], [False, False]])
     )
     xr.testing.assert_identical(
-        2 * ureg.m < da, xr.DataArray([[False, False], [True, True]])
+        2 * module_registry.m < da, xr.DataArray([[False, False], [True, True]])
     )
     with pytest.raises(ValueError) as exc:
         da > 2
         assert "Cannot compare Quantity and <class 'int'>" in str(exc)
 
 
-def test_array_function_deferral(da):
-    lower = 2 * ureg.m
-    upper = 3 * ureg.m
+def test_array_function_deferral(da, module_registry):
+    lower = 2 * module_registry.m
+    upper = 3 * module_registry.m
     args = (da, lower, upper)
     assert (
         lower.__array_function__(
@@ -132,6 +133,6 @@ def test_array_function_deferral(da):
     )
 
 
-def test_array_ufunc_deferral(da):
-    lower = 2 * ureg.m
+def test_array_ufunc_deferral(da, module_registry):
+    lower = 2 * module_registry.m
     assert lower.__array_ufunc__(np.maximum, "__call__", lower, da) is NotImplemented
diff --git a/pint/testsuite/test_contexts.py b/pint/testsuite/test_contexts.py
index 91070cf..5188edf 100644
--- a/pint/testsuite/test_contexts.py
+++ b/pint/testsuite/test_contexts.py
@@ -87,7 +87,7 @@ def add_sharedargdef_ctxs(ureg):
 
 class TestContexts:
     def test_known_context(self, func_registry):
-        ureg = UnitRegistry()
+        ureg = func_registry
         add_ctxs(ureg)
         with ureg.context("lc"):
             assert ureg._active_ctx
@@ -104,7 +104,7 @@ class TestContexts:
         assert not ureg._active_ctx.graph
 
     def test_known_context_enable(self, func_registry):
-        ureg = UnitRegistry()
+        ureg = func_registry
         add_ctxs(ureg)
         ureg.enable_contexts("lc")
         assert ureg._active_ctx
@@ -123,7 +123,7 @@ class TestContexts:
         assert not ureg._active_ctx.graph
 
     def test_graph(self, func_registry):
-        ureg = UnitRegistry()
+        ureg = func_registry
         add_ctxs(ureg)
         l = UnitsContainer({"[length]": 1.0})  # noqa: E741
         t = UnitsContainer({"[time]": -1.0})
@@ -162,7 +162,7 @@ class TestContexts:
             assert ureg._active_ctx.graph == g
 
     def test_graph_enable(self, func_registry):
-        ureg = UnitRegistry()
+        ureg = func_registry
         add_ctxs(ureg)
         l = UnitsContainer({"[length]": 1.0})  # noqa: E741
         t = UnitsContainer({"[time]": -1.0})
@@ -208,7 +208,7 @@ class TestContexts:
         ureg.disable_contexts(2)
 
     def test_known_nested_context(self, func_registry):
-        ureg = UnitRegistry()
+        ureg = func_registry
         add_ctxs(ureg)
 
         with ureg.context("lc"):
@@ -239,7 +239,7 @@ class TestContexts:
         assert not ureg._active_ctx.graph
 
     def test_unknown_nested_context(self, func_registry):
-        ureg = UnitRegistry()
+        ureg = func_registry
         add_ctxs(ureg)
 
         with ureg.context("lc"):
@@ -256,7 +256,7 @@ class TestContexts:
         assert not ureg._active_ctx.graph
 
     def test_one_context(self, func_registry):
-        ureg = UnitRegistry()
+        ureg = func_registry
 
         add_ctxs(ureg)
 
@@ -276,7 +276,7 @@ class TestContexts:
         assert ureg.get_compatible_units(q) == meter_units
 
     def test_multiple_context(self, func_registry):
-        ureg = UnitRegistry()
+        ureg = func_registry
 
         add_ctxs(ureg)
 
@@ -299,7 +299,7 @@ class TestContexts:
         assert ureg.get_compatible_units(q) == meter_units
 
     def test_nested_context(self, func_registry):
-        ureg = UnitRegistry()
+        ureg = func_registry
 
         add_ctxs(ureg)
 
@@ -324,7 +324,7 @@ class TestContexts:
 
     def test_context_with_arg(self, func_registry):
 
-        ureg = UnitRegistry()
+        ureg = func_registry
 
         add_arg_ctxs(ureg)
 
@@ -353,7 +353,7 @@ class TestContexts:
 
     def test_enable_context_with_arg(self, func_registry):
 
-        ureg = UnitRegistry()
+        ureg = func_registry
 
         add_arg_ctxs(ureg)
 
@@ -387,7 +387,7 @@ class TestContexts:
 
     def test_context_with_arg_def(self, func_registry):
 
-        ureg = UnitRegistry()
+        ureg = func_registry
 
         add_argdef_ctxs(ureg)
 
@@ -428,7 +428,7 @@ class TestContexts:
 
     def test_context_with_sharedarg_def(self, func_registry):
 
-        ureg = UnitRegistry()
+        ureg = func_registry
 
         add_sharedargdef_ctxs(ureg)
 
@@ -468,7 +468,7 @@ class TestContexts:
                 assert q.to("Hz") == s / 6
 
     def test_anonymous_context(self, func_registry):
-        ureg = UnitRegistry()
+        ureg = func_registry
         c = Context()
         c.add_transformation("[length]", "[time]", lambda ureg, x: x / ureg("5 cm/s"))
         with pytest.raises(ValueError):
@@ -498,8 +498,8 @@ class TestContexts:
         with ureg.context(c, c2):
             helpers.assert_quantity_equal(x.to("s"), ureg("1 s"))
 
-    def _test_ctx(self, ctx):
-        ureg = UnitRegistry()
+    def _test_ctx(self, ctx, ureg):
+
         q = 500 * ureg.meter
         s = (ureg.speed_of_light / q).to("Hz")
 
@@ -532,7 +532,37 @@ class TestContexts:
         with pytest.raises(DefinitionSyntaxError):
             Context.from_lines(["@context c", badrow])
 
-    def test_parse_simple(self):
+    @pytest.mark.parametrize(
+        "source, name, aliases, defaults",
+        [
+            (
+                [
+                    "@context longcontextname",
+                    "[length] -> 1 / [time]: c / value",
+                    "1 / [time] -> [length]: c / value",
+                ],
+                "longcontextname",
+                (),
+                {},
+            ),
+            (
+                ["@context longcontextname = lc", "[length] <-> 1 / [time]: c / value"],
+                "longcontextname",
+                ("lc",),
+                {},
+            ),
+            (
+                [
+                    "@context longcontextname = lc = lcn",
+                    "[length] <-> 1 / [time]: c / value",
+                ],
+                "longcontextname",
+                ("lc", "lcn"),
+                {},
+            ),
+        ],
+    )
+    def test_parse_simple(self, func_registry, source, name, aliases, defaults):
 
         a = Context.__keytransform__(
             UnitsContainer({"[time]": -1}), UnitsContainer({"[length]": 1})
@@ -541,41 +571,14 @@ class TestContexts:
             UnitsContainer({"[length]": 1}), UnitsContainer({"[time]": -1})
         )
 
-        s = [
-            "@context longcontextname",
-            "[length] -> 1 / [time]: c / value",
-            "1 / [time] -> [length]: c / value",
-        ]
-
-        c = Context.from_lines(s)
-        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)
-        assert c.name == "longcontextname"
-        assert c.aliases == ("lc",)
-        assert c.defaults == {}
-        assert c.funcs.keys() == {a, b}
-        self._test_ctx(c)
-
-        s = [
-            "@context longcontextname = lc = lcn",
-            "[length] <-> 1 / [time]: c / value",
-        ]
-
-        c = Context.from_lines(s)
-        assert c.name == "longcontextname"
-        assert c.aliases == ("lc", "lcn")
-        assert c.defaults == {}
+        c = Context.from_lines(source)
+        assert c.name == name
+        assert c.aliases == aliases
+        assert c.defaults == defaults
         assert c.funcs.keys() == {a, b}
-        self._test_ctx(c)
+        self._test_ctx(c, func_registry)
 
-    def test_parse_auto_inverse(self):
+    def test_parse_auto_inverse(self, func_registry):
 
         a = Context.__keytransform__(
             UnitsContainer({"[time]": -1.0}), UnitsContainer({"[length]": 1.0})
@@ -589,9 +592,9 @@ class TestContexts:
         c = Context.from_lines(s)
         assert c.defaults == {}
         assert c.funcs.keys() == {a, b}
-        self._test_ctx(c)
+        self._test_ctx(c, func_registry)
 
-    def test_parse_define(self):
+    def test_parse_define(self, func_registry):
         a = Context.__keytransform__(
             UnitsContainer({"[time]": -1}), UnitsContainer({"[length]": 1.0})
         )
@@ -603,9 +606,9 @@ class TestContexts:
         c = Context.from_lines(s)
         assert c.defaults == {}
         assert c.funcs.keys() == {a, b}
-        self._test_ctx(c)
+        self._test_ctx(c, func_registry)
 
-    def test_parse_parameterized(self):
+    def test_parse_parameterized(self, func_registry):
         a = Context.__keytransform__(
             UnitsContainer({"[time]": -1.0}), UnitsContainer({"[length]": 1.0})
         )
@@ -618,7 +621,7 @@ class TestContexts:
         c = Context.from_lines(s)
         assert c.defaults == {"n": 1}
         assert c.funcs.keys() == {a, b}
-        self._test_ctx(c)
+        self._test_ctx(c, func_registry)
 
         s = [
             "@context(n=1, bla=2) longcontextname",
@@ -634,9 +637,9 @@ class TestContexts:
         with pytest.raises(DefinitionSyntaxError):
             Context.from_lines(s)
 
-    def test_warnings(self, caplog):
+    def test_warnings(self, caplog, func_registry):
 
-        ureg = UnitRegistry()
+        ureg = func_registry
 
         with caplog.at_level(logging.DEBUG, "pint"):
             add_ctxs(ureg)
@@ -655,16 +658,8 @@ class TestContexts:
 
 
 class TestDefinedContexts:
-    @classmethod
-    def setup_class(cls):
-        cls.ureg = UnitRegistry()
-
-    @classmethod
-    def teardown_class(cls):
-        cls.ureg = None
-
-    def test_defined(self):
-        ureg = self.ureg
+    def test_defined(self, class_registry):
+        ureg = class_registry
         with ureg.context("sp"):
             pass
 
@@ -680,8 +675,8 @@ class TestDefinedContexts:
             assert a in ureg._active_ctx
             assert b in ureg._active_ctx
 
-    def test_spectroscopy(self):
-        ureg = self.ureg
+    def test_spectroscopy(self, class_registry):
+        ureg = class_registry
         eq = (532.0 * ureg.nm, 563.5 * ureg.terahertz, 2.33053 * ureg.eV)
         with ureg.context("sp"):
             from pint.util import find_shortest_path
@@ -703,8 +698,8 @@ class TestDefinedContexts:
         for a, b in itertools.product(eq, eq):
             helpers.assert_quantity_almost_equal(a.to(b.units, "sp"), b, rtol=0.01)
 
-    def test_textile(self):
-        ureg = self.ureg
+    def test_textile(self, class_registry):
+        ureg = class_registry
         qty_direct = 1.331 * ureg.tex
         with pytest.raises(DimensionalityError):
             qty_indirect = qty_direct.to("Nm")
@@ -736,8 +731,8 @@ class TestDefinedContexts:
                 == 0
             )
 
-    def test_decorator(self):
-        ureg = self.ureg
+    def test_decorator(self, class_registry):
+        ureg = class_registry
 
         a = 532.0 * ureg.nm
         with ureg.context("sp"):
@@ -755,8 +750,8 @@ class TestDefinedContexts:
 
         assert b == g(a)
 
-    def test_decorator_composition(self):
-        ureg = self.ureg
+    def test_decorator_composition(self, class_registry):
+        ureg = class_registry
 
         a = 532.0 * ureg.nm
         with ureg.context("sp"):
diff --git a/pint/testsuite/test_dask.py b/pint/testsuite/test_dask.py
index cb4d2c0..ef6044c 100644
--- a/pint/testsuite/test_dask.py
+++ b/pint/testsuite/test_dask.py
@@ -16,12 +16,17 @@ from distributed.utils_test import cluster, gen_cluster, loop  # isort:skip
 
 loop = loop  # flake8
 
-ureg = UnitRegistry(force_ndarray_like=True)
 units_ = "kilogram"
 
 
-def add_five(q):
-    return q + 5 * ureg(units_)
+@pytest.fixture(scope="module")
+def local_registry():
+    # Set up unit registry and sample
+    return UnitRegistry(force_ndarray_like=True)
+
+
+def add_five(local_registry, q):
+    return q + 5 * local_registry(units_)
 
 
 @pytest.fixture
@@ -34,21 +39,21 @@ def numpy_array():
     return np.arange(0, 25, dtype=float).reshape((5, 5)) + 5
 
 
-def test_is_dask_collection(dask_array):
+def test_is_dask_collection(local_registry, dask_array):
     """Test that a pint.Quantity wrapped Dask array is a Dask collection."""
-    q = ureg.Quantity(dask_array, units_)
+    q = local_registry.Quantity(dask_array, units_)
     assert dask.is_dask_collection(q)
 
 
-def test_is_not_dask_collection(numpy_array):
+def test_is_not_dask_collection(local_registry, numpy_array):
     """Test that other pint.Quantity wrapped objects are not Dask collections."""
-    q = ureg.Quantity(numpy_array, units_)
+    q = local_registry.Quantity(numpy_array, units_)
     assert not dask.is_dask_collection(q)
 
 
-def test_dask_scheduler(dask_array):
+def test_dask_scheduler(local_registry, dask_array):
     """Test that a pint.Quantity wrapped Dask array has the correct default scheduler."""
-    q = ureg.Quantity(dask_array, units_)
+    q = local_registry.Quantity(dask_array, units_)
 
     scheduler = q.__dask_scheduler__
     scheduler_name = f"{scheduler.__module__}.{scheduler.__name__}"
@@ -70,27 +75,27 @@ def test_dask_scheduler(dask_array):
         ),
     ),
 )
-def test_dask_tokenize(item):
+def test_dask_tokenize(local_registry, item):
     """Test that a pint.Quantity wrapping something has a unique token."""
     dask_token = dask.base.tokenize(item)
-    q = ureg.Quantity(item, units_)
+    q = local_registry.Quantity(item, units_)
 
     assert dask.base.tokenize(item) != dask.base.tokenize(q)
     assert dask.base.tokenize(item) == dask_token
 
 
-def test_dask_optimize(dask_array):
+def test_dask_optimize(local_registry, dask_array):
     """Test that a pint.Quantity wrapped Dask array can be optimized."""
-    q = ureg.Quantity(dask_array, units_)
+    q = local_registry.Quantity(dask_array, units_)
 
     assert q.__dask_optimize__ == dask.array.Array.__dask_optimize__
 
 
-def test_compute(dask_array, numpy_array):
+def test_compute(local_registry, dask_array, numpy_array):
     """Test the compute() method on a pint.Quantity wrapped Dask array."""
-    q = ureg.Quantity(dask_array, units_)
+    q = local_registry.Quantity(dask_array, units_)
 
-    comps = add_five(q)
+    comps = add_five(local_registry, q)
     res = comps.compute()
 
     assert np.all(res.m == numpy_array)
@@ -99,11 +104,11 @@ def test_compute(dask_array, numpy_array):
     assert q.magnitude is dask_array
 
 
-def test_persist(dask_array, numpy_array):
+def test_persist(local_registry, dask_array, numpy_array):
     """Test the persist() method on a pint.Quantity wrapped Dask array."""
-    q = ureg.Quantity(dask_array, units_)
+    q = local_registry.Quantity(dask_array, units_)
 
-    comps = add_five(q)
+    comps = add_five(local_registry, q)
     res = comps.persist()
 
     assert np.all(res.m == numpy_array)
@@ -115,11 +120,11 @@ def test_persist(dask_array, numpy_array):
 @pytest.mark.skipif(
     importlib.util.find_spec("graphviz") is None, reason="GraphViz is not available"
 )
-def test_visualize(dask_array):
+def test_visualize(local_registry, dask_array):
     """Test the visualize() method on a pint.Quantity wrapped Dask array."""
-    q = ureg.Quantity(dask_array, units_)
+    q = local_registry.Quantity(dask_array, units_)
 
-    comps = add_five(q)
+    comps = add_five(local_registry, q)
     res = comps.visualize()
 
     assert res is None
@@ -128,11 +133,11 @@ def test_visualize(dask_array):
     os.remove("mydask.png")
 
 
-def test_compute_persist_equivalent(dask_array, numpy_array):
+def test_compute_persist_equivalent(local_registry, dask_array, numpy_array):
     """Test that compute() and persist() return the same numeric results."""
-    q = ureg.Quantity(dask_array, units_)
+    q = local_registry.Quantity(dask_array, units_)
 
-    comps = add_five(q)
+    comps = add_five(local_registry, q)
     res_compute = comps.compute()
     res_persist = comps.persist()
 
@@ -141,11 +146,11 @@ def test_compute_persist_equivalent(dask_array, numpy_array):
 
 
 @pytest.mark.parametrize("method", ["compute", "persist", "visualize"])
-def test_exception_method_not_implemented(numpy_array, method):
+def test_exception_method_not_implemented(local_registry, numpy_array, method):
     """Test exception handling for convenience methods on a pint.Quantity wrapped
     object that is not a dask.array.Array object.
     """
-    q = ureg.Quantity(numpy_array, units_)
+    q = local_registry.Quantity(numpy_array, units_)
 
     exctruth = (
         f"Method {method} only implemented for objects of"
@@ -157,13 +162,13 @@ def test_exception_method_not_implemented(numpy_array, method):
         obj_method()
 
 
-def test_distributed_compute(loop, dask_array, numpy_array):
+def test_distributed_compute(local_registry, loop, dask_array, numpy_array):
     """Test compute() for distributed machines."""
-    q = ureg.Quantity(dask_array, units_)
+    q = local_registry.Quantity(dask_array, units_)
 
     with cluster() as (s, [a, b]):
         with Client(s["address"], loop=loop):
-            comps = add_five(q)
+            comps = add_five(local_registry, q)
             res = comps.compute()
 
             assert np.all(res.m == numpy_array)
@@ -173,13 +178,13 @@ def test_distributed_compute(loop, dask_array, numpy_array):
     assert q.magnitude is dask_array
 
 
-def test_distributed_persist(loop, dask_array):
+def test_distributed_persist(local_registry, loop, dask_array):
     """Test persist() for distributed machines."""
-    q = ureg.Quantity(dask_array, units_)
+    q = local_registry.Quantity(dask_array, units_)
 
     with cluster() as (s, [a, b]):
         with Client(s["address"], loop=loop):
-            comps = add_five(q)
+            comps = add_five(local_registry, q)
             persisted_q = comps.persist()
 
             comps_truth = dask_array + 5
@@ -195,10 +200,14 @@ def test_distributed_persist(loop, dask_array):
 @gen_cluster(client=True)
 async def test_async(c, s, a, b):
     """Test asynchronous operations."""
+
+    # TODO: use a fixture for this.
+    local_registry = UnitRegistry(force_ndarray_like=True)
+
     da = dask.array.arange(0, 25, chunks=5, dtype=float).reshape((5, 5))
-    q = ureg.Quantity(da, units_)
+    q = local_registry.Quantity(da, units_)
 
-    x = q + ureg.Quantity(5, units_)
+    x = q + local_registry.Quantity(5, units_)
     y = x.persist()
     assert str(y)
 
diff --git a/pint/testsuite/test_infer_base_unit.py b/pint/testsuite/test_infer_base_unit.py
index 54a4720..f2605c6 100644
--- a/pint/testsuite/test_infer_base_unit.py
+++ b/pint/testsuite/test_infer_base_unit.py
@@ -1,4 +1,10 @@
+from decimal import Decimal
+from fractions import Fraction
+
+import pytest
+
 from pint import Quantity as Q
+from pint import UnitRegistry
 from pint.testsuite import helpers
 from pint.util import infer_base_unit
 
@@ -7,7 +13,44 @@ class TestInferBaseUnit:
     def test_infer_base_unit(self):
         from pint.util import infer_base_unit
 
-        assert infer_base_unit(Q(1, "millimeter * nanometer")) == Q(1, "meter**2").units
+        test_units = Q(1, "meter**2").units
+        registry = Q(1, "meter**2")._REGISTRY
+
+        assert infer_base_unit(Q(1, "millimeter * nanometer")) == test_units
+
+        assert infer_base_unit("millimeter * nanometer", registry) == test_units
+
+        assert (
+            infer_base_unit(Q(1, "millimeter * nanometer").units, registry)
+            == test_units
+        )
+
+        with pytest.raises(ValueError, match=r"No registry provided."):
+            infer_base_unit("millimeter")
+
+    def test_infer_base_unit_decimal(self):
+        from pint.util import infer_base_unit
+
+        ureg = UnitRegistry(non_int_type=Decimal)
+        QD = ureg.Quantity
+
+        ibu_d = infer_base_unit(QD(Decimal("1"), "millimeter * nanometer"))
+
+        assert ibu_d == QD(Decimal("1"), "meter**2").units
+
+        assert all(isinstance(v, Decimal) for v in ibu_d.values())
+
+    def test_infer_base_unit_fraction(self):
+        from pint.util import infer_base_unit
+
+        ureg = UnitRegistry(non_int_type=Fraction)
+        QD = ureg.Quantity
+
+        ibu_d = infer_base_unit(QD(Fraction("1"), "millimeter * nanometer"))
+
+        assert ibu_d == QD(Fraction("1"), "meter**2").units
+
+        assert all(isinstance(v, Fraction) for v in ibu_d.values())
 
     def test_units_adding_to_zero(self):
         assert infer_base_unit(Q(1, "m * mm / m / um * s")) == Q(1, "s").units
@@ -21,6 +64,42 @@ class TestInferBaseUnit:
         r = (Q(1, "m") * Q(1, "mm") / Q(1, "m") / Q(2, "um") * Q(2, "s")).to_compact()
         helpers.assert_quantity_almost_equal(r, Q(1000, "s"))
 
+    def test_to_compact_decimal(self):
+        ureg = UnitRegistry(non_int_type=Decimal)
+        Q = ureg.Quantity
+        r = (
+            Q(Decimal("1000000000.0"), "m")
+            * Q(Decimal("1"), "mm")
+            / Q(Decimal("1"), "s")
+            / Q(Decimal("1"), "ms")
+        )
+        compact_r = r.to_compact()
+        expected = Q(Decimal("1000.0"), "kilometer**2 / second**2")
+        assert compact_r == expected
+
+        r = (
+            Q(Decimal(1), "m") * Q(1, "mm") / Q(1, "m**2") / Q(2, "um") * Q(2, "s")
+        ).to_compact()
+        assert r == Q(1000, "s/m")
+
+    def test_to_compact_fraction(self):
+        ureg = UnitRegistry(non_int_type=Fraction)
+        Q = ureg.Quantity
+        r = (
+            Q(Fraction("10000000000/10"), "m")
+            * Q(Fraction("1"), "mm")
+            / Q(Fraction("1"), "s")
+            / Q(Fraction("1"), "ms")
+        )
+        compact_r = r.to_compact()
+        expected = Q(Fraction("1000.0"), "kilometer**2 / second**2")
+        assert compact_r == expected
+
+        r = (
+            Q(Fraction(1), "m") * Q(1, "mm") / Q(1, "m**2") / Q(2, "um") * Q(2, "s")
+        ).to_compact()
+        assert r == Q(1000, "s/m")
+
     def test_volts(self):
         from pint.util import infer_base_unit
 
diff --git a/pint/testsuite/test_issues.py b/pint/testsuite/test_issues.py
index 55723c3..43fce0a 100644
--- a/pint/testsuite/test_issues.py
+++ b/pint/testsuite/test_issues.py
@@ -10,113 +10,116 @@ from pint.testsuite import QuantityTestCase, helpers
 from pint.unit import UnitsContainer
 from pint.util import ParserHelper
 
-ureg = UnitRegistry()
-
 
+# TODO: do not subclass from QuantityTestCase
 class TestIssues(QuantityTestCase):
 
     kwargs = dict(autoconvert_offset_to_baseunit=False)
 
     @pytest.mark.xfail
-    def test_issue25(self):
+    def test_issue25(self, module_registry):
         x = ParserHelper.from_string("10 %")
         assert x == ParserHelper(10, {"%": 1})
         x = ParserHelper.from_string("10 ‰")
         assert x == ParserHelper(10, {"‰": 1})
-        ureg.define("percent = [fraction]; offset: 0 = %")
-        ureg.define("permille = percent / 10 = ‰")
-        x = ureg.parse_expression("10 %")
-        assert x == ureg.Quantity(10, {"%": 1})
-        y = ureg.parse_expression("10 ‰")
-        assert y == ureg.Quantity(10, {"‰": 1})
-        assert x.to("‰") == ureg.Quantity(1, {"‰": 1})
-
-    def test_issue29(self):
-        t = 4 * ureg("mW")
+        module_registry.define("percent = [fraction]; offset: 0 = %")
+        module_registry.define("permille = percent / 10 = ‰")
+        x = module_registry.parse_expression("10 %")
+        assert x == module_registry.Quantity(10, {"%": 1})
+        y = module_registry.parse_expression("10 ‰")
+        assert y == module_registry.Quantity(10, {"‰": 1})
+        assert x.to("‰") == module_registry.Quantity(1, {"‰": 1})
+
+    def test_issue29(self, module_registry):
+        t = 4 * module_registry("mW")
         assert t.magnitude == 4
         assert t._units == UnitsContainer(milliwatt=1)
-        assert t.to("joule / second") == 4e-3 * ureg("W")
+        assert t.to("joule / second") == 4e-3 * module_registry("W")
 
     @pytest.mark.xfail
     @helpers.requires_numpy
-    def test_issue37(self):
+    def test_issue37(self, module_registry):
         x = np.ma.masked_array([1, 2, 3], mask=[True, True, False])
-        q = ureg.meter * x
-        assert isinstance(q, ureg.Quantity)
+        q = module_registry.meter * x
+        assert isinstance(q, module_registry.Quantity)
         np.testing.assert_array_equal(q.magnitude, x)
-        assert q.units == ureg.meter.units
-        q = x * ureg.meter
-        assert isinstance(q, ureg.Quantity)
+        assert q.units == module_registry.meter.units
+        q = x * module_registry.meter
+        assert isinstance(q, module_registry.Quantity)
         np.testing.assert_array_equal(q.magnitude, x)
-        assert q.units == ureg.meter.units
+        assert q.units == module_registry.meter.units
 
         m = np.ma.masked_array(2 * np.ones(3, 3))
         qq = q * m
-        assert isinstance(qq, ureg.Quantity)
+        assert isinstance(qq, module_registry.Quantity)
         np.testing.assert_array_equal(qq.magnitude, x * m)
-        assert qq.units == ureg.meter.units
+        assert qq.units == module_registry.meter.units
         qq = m * q
-        assert isinstance(qq, ureg.Quantity)
+        assert isinstance(qq, module_registry.Quantity)
         np.testing.assert_array_equal(qq.magnitude, x * m)
-        assert qq.units == ureg.meter.units
+        assert qq.units == module_registry.meter.units
 
     @pytest.mark.xfail
     @helpers.requires_numpy
-    def test_issue39(self):
+    def test_issue39(self, module_registry):
         x = np.matrix([[1, 2, 3], [1, 2, 3], [1, 2, 3]])
-        q = ureg.meter * x
-        assert isinstance(q, ureg.Quantity)
+        q = module_registry.meter * x
+        assert isinstance(q, module_registry.Quantity)
         np.testing.assert_array_equal(q.magnitude, x)
-        assert q.units == ureg.meter.units
-        q = x * ureg.meter
-        assert isinstance(q, ureg.Quantity)
+        assert q.units == module_registry.meter.units
+        q = x * module_registry.meter
+        assert isinstance(q, module_registry.Quantity)
         np.testing.assert_array_equal(q.magnitude, x)
-        assert q.units == ureg.meter.units
+        assert q.units == module_registry.meter.units
 
         m = np.matrix(2 * np.ones(3, 3))
         qq = q * m
-        assert isinstance(qq, ureg.Quantity)
+        assert isinstance(qq, module_registry.Quantity)
         np.testing.assert_array_equal(qq.magnitude, x * m)
-        assert qq.units == ureg.meter.units
+        assert qq.units == module_registry.meter.units
         qq = m * q
-        assert isinstance(qq, ureg.Quantity)
+        assert isinstance(qq, module_registry.Quantity)
         np.testing.assert_array_equal(qq.magnitude, x * m)
-        assert qq.units == ureg.meter.units
+        assert qq.units == module_registry.meter.units
 
     @helpers.requires_numpy
-    def test_issue44(self):
-        x = 4.0 * ureg.dimensionless
+    def test_issue44(self, module_registry):
+        x = 4.0 * module_registry.dimensionless
         np.sqrt(x)
         helpers.assert_quantity_almost_equal(
-            np.sqrt([4.0] * ureg.dimensionless), [2.0] * ureg.dimensionless
+            np.sqrt([4.0] * module_registry.dimensionless),
+            [2.0] * module_registry.dimensionless,
         )
         helpers.assert_quantity_almost_equal(
-            np.sqrt(4.0 * ureg.dimensionless), 2.0 * ureg.dimensionless
+            np.sqrt(4.0 * module_registry.dimensionless),
+            2.0 * module_registry.dimensionless,
         )
 
-    def test_issue45(self):
+    def test_issue45(self, module_registry):
         import math
 
         helpers.assert_quantity_almost_equal(
-            math.sqrt(4 * ureg.m / ureg.cm), math.sqrt(4 * 100)
+            math.sqrt(4 * module_registry.m / module_registry.cm), math.sqrt(4 * 100)
+        )
+        helpers.assert_quantity_almost_equal(
+            float(module_registry.V / module_registry.mV), 1000.0
         )
-        helpers.assert_quantity_almost_equal(float(ureg.V / ureg.mV), 1000.0)
 
     @helpers.requires_numpy
-    def test_issue45b(self):
+    def test_issue45b(self, module_registry):
         helpers.assert_quantity_almost_equal(
-            np.sin([np.pi / 2] * ureg.m / ureg.m),
-            np.sin([np.pi / 2] * ureg.dimensionless),
+            np.sin([np.pi / 2] * module_registry.m / module_registry.m),
+            np.sin([np.pi / 2] * module_registry.dimensionless),
         )
         helpers.assert_quantity_almost_equal(
-            np.sin([np.pi / 2] * ureg.cm / ureg.m),
-            np.sin([np.pi / 2] * ureg.dimensionless * 0.01),
+            np.sin([np.pi / 2] * module_registry.cm / module_registry.m),
+            np.sin([np.pi / 2] * module_registry.dimensionless * 0.01),
         )
 
-    def test_issue50(self):
-        Q_ = ureg.Quantity
-        assert Q_(100) == 100 * ureg.dimensionless
-        assert Q_("100") == 100 * ureg.dimensionless
+    def test_issue50(self, module_registry):
+        Q_ = module_registry.Quantity
+        assert Q_(100) == 100 * module_registry.dimensionless
+        assert Q_("100") == 100 * module_registry.dimensionless
 
     def test_issue52(self):
         u1 = UnitRegistry()
@@ -140,17 +143,17 @@ class TestIssues(QuantityTestCase):
             with pytest.raises(ValueError):
                 fun(q1, q2)
 
-    def test_issue54(self):
-        assert (1 * ureg.km / ureg.m + 1).magnitude == 1001
+    def test_issue54(self, module_registry):
+        assert (1 * module_registry.km / module_registry.m + 1).magnitude == 1001
 
-    def test_issue54_related(self):
-        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_issue54_related(self, module_registry):
+        assert module_registry.km / module_registry.m == 1000
+        assert 1000 == module_registry.km / module_registry.m
+        assert 900 < module_registry.km / module_registry.m
+        assert 1100 > module_registry.km / module_registry.m
 
-    def test_issue61(self):
-        Q_ = ureg.Quantity
+    def test_issue61(self, module_registry):
+        Q_ = module_registry.Quantity
         for value in ({}, {"a": 3}, None):
             with pytest.raises(TypeError):
                 Q_(value)
@@ -162,49 +165,49 @@ class TestIssues(QuantityTestCase):
             Q_("")
 
     @helpers.requires_not_numpy()
-    def test_issue61_notNP(self):
-        Q_ = ureg.Quantity
+    def test_issue61_notNP(self, module_registry):
+        Q_ = module_registry.Quantity
         for value in ([1, 2, 3], (1, 2, 3)):
             with pytest.raises(TypeError):
                 Q_(value)
             with pytest.raises(TypeError):
                 Q_(value, "meter")
 
-    def test_issue62(self):
-        m = ureg("m**0.5")
+    def test_issue62(self, module_registry):
+        m = module_registry("m**0.5")
         assert str(m.units) == "meter ** 0.5"
 
-    def test_issue66(self):
-        assert ureg.get_dimensionality(
+    def test_issue66(self, module_registry):
+        assert module_registry.get_dimensionality(
             UnitsContainer({"[temperature]": 1})
         ) == UnitsContainer({"[temperature]": 1})
-        assert ureg.get_dimensionality(ureg.kelvin) == UnitsContainer(
-            {"[temperature]": 1}
-        )
-        assert ureg.get_dimensionality(ureg.degC) == UnitsContainer(
-            {"[temperature]": 1}
-        )
+        assert module_registry.get_dimensionality(
+            module_registry.kelvin
+        ) == UnitsContainer({"[temperature]": 1})
+        assert module_registry.get_dimensionality(
+            module_registry.degC
+        ) == UnitsContainer({"[temperature]": 1})
 
-    def test_issue66b(self):
-        assert ureg.get_base_units(ureg.kelvin) == (
+    def test_issue66b(self, module_registry):
+        assert module_registry.get_base_units(module_registry.kelvin) == (
             1.0,
-            ureg.Unit(UnitsContainer({"kelvin": 1})),
+            module_registry.Unit(UnitsContainer({"kelvin": 1})),
         )
-        assert ureg.get_base_units(ureg.degC) == (
+        assert module_registry.get_base_units(module_registry.degC) == (
             1.0,
-            ureg.Unit(UnitsContainer({"kelvin": 1})),
+            module_registry.Unit(UnitsContainer({"kelvin": 1})),
         )
 
-    def test_issue69(self):
-        q = ureg("m").to(ureg("in"))
-        assert q == ureg("m").to("in")
+    def test_issue69(self, module_registry):
+        q = module_registry("m").to(module_registry("in"))
+        assert q == module_registry("m").to("in")
 
     @helpers.requires_numpy
-    def test_issue74(self):
+    def test_issue74(self, module_registry):
         v1 = np.asarray([1.0, 2.0, 3.0])
         v2 = np.asarray([3.0, 2.0, 1.0])
-        q1 = v1 * ureg.ms
-        q2 = v2 * ureg.ms
+        q1 = v1 * module_registry.ms
+        q2 = v2 * module_registry.ms
 
         np.testing.assert_array_equal(q1 < q2, v1 < v2)
         np.testing.assert_array_equal(q1 > q2, v1 > v2)
@@ -212,7 +215,7 @@ class TestIssues(QuantityTestCase):
         np.testing.assert_array_equal(q1 <= q2, v1 <= v2)
         np.testing.assert_array_equal(q1 >= q2, v1 >= v2)
 
-        q2s = np.asarray([0.003, 0.002, 0.001]) * ureg.s
+        q2s = np.asarray([0.003, 0.002, 0.001]) * module_registry.s
         v2s = q2s.to("ms").magnitude
 
         np.testing.assert_array_equal(q1 < q2s, v1 < v2s)
@@ -222,54 +225,54 @@ class TestIssues(QuantityTestCase):
         np.testing.assert_array_equal(q1 >= q2s, v1 >= v2s)
 
     @helpers.requires_numpy
-    def test_issue75(self):
+    def test_issue75(self, module_registry):
         v1 = np.asarray([1.0, 2.0, 3.0])
         v2 = np.asarray([3.0, 2.0, 1.0])
-        q1 = v1 * ureg.ms
-        q2 = v2 * ureg.ms
+        q1 = v1 * module_registry.ms
+        q2 = v2 * module_registry.ms
 
         np.testing.assert_array_equal(q1 == q2, v1 == v2)
         np.testing.assert_array_equal(q1 != q2, v1 != v2)
 
-        q2s = np.asarray([0.003, 0.002, 0.001]) * ureg.s
+        q2s = np.asarray([0.003, 0.002, 0.001]) * module_registry.s
         v2s = q2s.to("ms").magnitude
 
         np.testing.assert_array_equal(q1 == q2s, v1 == v2s)
         np.testing.assert_array_equal(q1 != q2s, v1 != v2s)
 
     @helpers.requires_uncertainties()
-    def test_issue77(self):
-        acc = (5.0 * ureg("m/s/s")).plus_minus(0.25)
-        tim = (37.0 * ureg("s")).plus_minus(0.16)
+    def test_issue77(self, module_registry):
+        acc = (5.0 * module_registry("m/s/s")).plus_minus(0.25)
+        tim = (37.0 * module_registry("s")).plus_minus(0.16)
         dis = acc * tim ** 2 / 2
         assert dis.value == acc.value * tim.value ** 2 / 2
 
-    def test_issue85(self):
+    def test_issue85(self, module_registry):
 
-        T = 4.0 * ureg.kelvin
-        m = 1.0 * ureg.amu
-        va = 2.0 * ureg.k * T / m
+        T = 4.0 * module_registry.kelvin
+        m = 1.0 * module_registry.amu
+        va = 2.0 * module_registry.k * T / m
 
         va.to_base_units()
 
-        boltmk = 1.380649e-23 * ureg.J / ureg.K
+        boltmk = 1.380649e-23 * module_registry.J / module_registry.K
         vb = 2.0 * boltmk * T / m
 
         helpers.assert_quantity_almost_equal(va.to_base_units(), vb.to_base_units())
 
-    def test_issue86(self):
-        ureg = self.ureg
-        ureg.autoconvert_offset_to_baseunit = True
+    def test_issue86(self, module_registry):
+
+        module_registry.autoconvert_offset_to_baseunit = True
 
         def parts(q):
             return q.magnitude, q.units
 
-        q1 = 10.0 * ureg.degC
-        q2 = 10.0 * ureg.kelvin
+        q1 = 10.0 * module_registry.degC
+        q2 = 10.0 * module_registry.kelvin
 
         k1 = q1.to_base_units()
 
-        q3 = 3.0 * ureg.meter
+        q3 = 3.0 * module_registry.meter
 
         q1m, q1u = parts(q1)
         q2m, q2u = parts(q2)
@@ -294,14 +297,13 @@ class TestIssues(QuantityTestCase):
         assert parts(q1 ** 2) == (k1m ** 2, k1u ** 2)
         assert parts(q1 ** -2) == (k1m ** -2, k1u ** -2)
 
-    def test_issues86b(self):
-        ureg = self.ureg
-
-        T1 = 200.0 * ureg.degC
-        T2 = T1.to(ureg.kelvin)
-        m = 132.9054519 * ureg.amu
-        v1 = 2 * ureg.k * T1 / m
-        v2 = 2 * ureg.k * T2 / m
+    def test_issues86b(self, module_registry):
+        T1 = module_registry.Quantity(200, module_registry.degC)
+        # T1 = 200.0 * module_registry.degC
+        T2 = T1.to(module_registry.kelvin)
+        m = 132.9054519 * module_registry.amu
+        v1 = 2 * module_registry.k * T1 / m
+        v2 = 2 * module_registry.k * T2 / m
 
         helpers.assert_quantity_almost_equal(v1, v2)
         helpers.assert_quantity_almost_equal(v1, v2.to_base_units())
@@ -309,30 +311,35 @@ class TestIssues(QuantityTestCase):
         helpers.assert_quantity_almost_equal(v1.to_base_units(), v2.to_base_units())
 
     @pytest.mark.xfail
-    def test_issue86c(self):
-        ureg = self.ureg
-        ureg.autoconvert_offset_to_baseunit = True
-        T = ureg.degC
+    def test_issue86c(self, module_registry):
+        module_registry.autoconvert_offset_to_baseunit = True
+        T = module_registry.degC
         T = 100.0 * T
-        helpers.assert_quantity_almost_equal(ureg.k * 2 * T, ureg.k * (2 * T))
+        helpers.assert_quantity_almost_equal(
+            module_registry.k * 2 * T, module_registry.k * (2 * T)
+        )
 
-    def test_issue93(self):
-        x = 5 * ureg.meter
+    def test_issue93(self, module_registry):
+        x = 5 * module_registry.meter
         assert isinstance(x.magnitude, int)
-        y = 0.1 * ureg.meter
+        y = 0.1 * module_registry.meter
         assert isinstance(y.magnitude, float)
-        z = 5 * ureg.meter
+        z = 5 * module_registry.meter
         assert isinstance(z.magnitude, int)
         z += y
         assert isinstance(z.magnitude, float)
 
-        helpers.assert_quantity_almost_equal(x + y, 5.1 * ureg.meter)
-        helpers.assert_quantity_almost_equal(z, 5.1 * ureg.meter)
+        helpers.assert_quantity_almost_equal(x + y, 5.1 * module_registry.meter)
+        helpers.assert_quantity_almost_equal(z, 5.1 * module_registry.meter)
 
-    def test_issue104(self):
+    def test_issue104(self, module_registry):
 
-        x = [ureg("1 meter"), ureg("1 meter"), ureg("1 meter")]
-        y = [ureg("1 meter")] * 3
+        x = [
+            module_registry("1 meter"),
+            module_registry("1 meter"),
+            module_registry("1 meter"),
+        ]
+        y = [module_registry("1 meter")] * 3
 
         def summer(values):
             if not values:
@@ -343,27 +350,31 @@ class TestIssues(QuantityTestCase):
 
             return total
 
-        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"))
+        helpers.assert_quantity_almost_equal(
+            summer(x), module_registry.Quantity(3, "meter")
+        )
+        helpers.assert_quantity_almost_equal(x[0], module_registry.Quantity(1, "meter"))
+        helpers.assert_quantity_almost_equal(
+            summer(y), module_registry.Quantity(3, "meter")
+        )
+        helpers.assert_quantity_almost_equal(y[0], module_registry.Quantity(1, "meter"))
 
-    def test_issue105(self):
+    def test_issue105(self, module_registry):
 
-        func = ureg.parse_unit_name
+        func = module_registry.parse_unit_name
         val = list(func("meter"))
         assert list(func("METER")) == []
         assert val == list(func("METER", False))
 
-        for func in (ureg.get_name, ureg.parse_expression):
+        for func in (module_registry.get_name, module_registry.parse_expression):
             val = func("meter")
             with pytest.raises(AttributeError):
                 func("METER")
             assert val == func("METER", False)
 
     @helpers.requires_numpy
-    def test_issue127(self):
-        q = [1.0, 2.0, 3.0, 4.0] * self.ureg.meter
+    def test_issue127(self, module_registry):
+        q = [1.0, 2.0, 3.0, 4.0] * module_registry.meter
         q[0] = np.nan
         assert q[0] != 1.0
         assert math.isnan(q[0].magnitude)
@@ -378,34 +389,34 @@ class TestIssues(QuantityTestCase):
         assert iq == 10
         assert isinstance(iq, int)
 
-    def test_angstrom_creation(self):
-        ureg.Quantity(2, "Å")
+    def test_angstrom_creation(self, module_registry):
+        module_registry.Quantity(2, "Å")
 
-    def test_alternative_angstrom_definition(self):
-        ureg.Quantity(2, "\u212B")
+    def test_alternative_angstrom_definition(self, module_registry):
+        module_registry.Quantity(2, "\u212B")
 
-    def test_micro_creation(self):
-        ureg.Quantity(2, "µm")
+    def test_micro_creation(self, module_registry):
+        module_registry.Quantity(2, "µm")
 
     @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
+    def test_issue171_real_imag(self, module_registry):
+        qr = [1.0, 2.0, 3.0, 4.0] * module_registry.meter
+        qi = [4.0, 3.0, 2.0, 1.0] * module_registry.meter
         q = qr + 1j * qi
         helpers.assert_quantity_equal(q.real, qr)
         helpers.assert_quantity_equal(q.imag, qi)
 
     @helpers.requires_numpy
-    def test_issue171_T(self):
+    def test_issue171_T(self, module_registry):
         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
+        q1 = a * module_registry.meter
+        q2 = a.T * module_registry.meter
         helpers.assert_quantity_equal(q1.T, q2)
 
     @helpers.requires_numpy
-    def test_issue250(self):
-        a = self.ureg.V
-        b = self.ureg.mV
+    def test_issue250(self, module_registry):
+        a = module_registry.V
+        b = module_registry.mV
         assert np.float16(a / b) == 1000.0
         assert np.float32(a / b) == 1000.0
         assert np.float64(a / b) == 1000.0
@@ -419,88 +430,93 @@ class TestIssues(QuantityTestCase):
         u = t.to(ur.mF)
         helpers.assert_quantity_equal(q.to(ur.mF), u)
 
-    def test_issue323(self):
+    def test_issue323(self, module_registry):
         from fractions import Fraction as F
 
         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("")
+    def test_issue339(self, module_registry):
+        q1 = module_registry("")
         assert q1.magnitude == 1
-        assert q1.units == self.ureg.dimensionless
-        q2 = self.ureg("1 dimensionless")
+        assert q1.units == module_registry.dimensionless
+        q2 = module_registry("1 dimensionless")
         assert q1 == q2
 
-    def test_issue354_356_370(self):
+    def test_issue354_356_370(self, module_registry):
         assert (
-            "{:~}".format(1 * self.ureg.second / self.ureg.millisecond) == "1.0 s / ms"
+            "{:~}".format(1 * module_registry.second / module_registry.millisecond)
+            == "1.0 s / ms"
         )
-        assert "{:~}".format(1 * self.ureg.count) == "1 count"
-        assert "{:~}".format(1 * self.ureg("MiB")) == "1 MiB"
+        assert "{:~}".format(1 * module_registry.count) == "1 count"
+        assert "{:~}".format(1 * module_registry("MiB")) == "1 MiB"
 
-    def test_issue468(self):
-        @ureg.wraps("kg", "meter")
+    def test_issue468(self, module_registry):
+        @module_registry.wraps("kg", "meter")
         def f(x):
             return x
 
-        x = ureg.Quantity(1.0, "meter")
+        x = module_registry.Quantity(1.0, "meter")
         y = f(x)
         z = x * y
-        assert z == ureg.Quantity(1.0, "meter * kilogram")
+        assert z == module_registry.Quantity(1.0, "meter * kilogram")
 
     @helpers.requires_numpy
-    def test_issue482(self):
-        q = self.ureg.Quantity(1, self.ureg.dimensionless)
+    def test_issue482(self, module_registry):
+        q = module_registry.Quantity(1, module_registry.dimensionless)
         qe = np.exp(q)
-        assert isinstance(qe, self.ureg.Quantity)
+        assert isinstance(qe, module_registry.Quantity)
 
     @helpers.requires_numpy
-    def test_issue483(self):
-        ureg = self.ureg
+    def test_issue483(self, module_registry):
+
         a = np.asarray([1, 2, 3])
-        q = [1, 2, 3] * ureg.dimensionless
+        q = [1, 2, 3] * module_registry.dimensionless
         p = (q ** q).m
         np.testing.assert_array_equal(p, a ** a)
 
-    def test_issue507(self):
+    def test_issue507(self, module_registry):
         # leading underscore in unit works with numbers
-        ureg.define("_100km = 100 * kilometer")
-        battery_ec = 16 * ureg.kWh / ureg._100km  # noqa: F841
+        module_registry.define("_100km = 100 * kilometer")
+        battery_ec = 16 * module_registry.kWh / module_registry._100km  # noqa: F841
         # ... but not with text
-        ureg.define("_home = 4700 * kWh / year")
+        module_registry.define("_home = 4700 * kWh / year")
         with pytest.raises(AttributeError):
-            home_elec_power = 1 * ureg._home  # noqa: F841
+            home_elec_power = 1 * module_registry._home  # noqa: F841
         # ... or with *only* underscores
-        ureg.define("_ = 45 * km")
+        module_registry.define("_ = 45 * km")
         with pytest.raises(AttributeError):
-            one_blank = 1 * ureg._  # noqa: F841
+            one_blank = 1 * module_registry._  # noqa: F841
 
-    def test_issue523(self):
+    def test_issue523(self, module_registry):
         src, dst = UnitsContainer({"meter": 1}), UnitsContainer({"degF": 1})
         value = 10.0
-        convert = self.ureg.convert
+        convert = module_registry.convert
         with pytest.raises(DimensionalityError):
             convert(value, src, dst)
         with pytest.raises(DimensionalityError):
             convert(value, dst, src)
 
-    def test_issue532(self):
-        ureg = self.ureg
-
-        @ureg.check(ureg(""))
+    def test_issue532(self, module_registry):
+        @module_registry.check(module_registry(""))
         def f(x):
             return 2 * x
 
-        assert f(ureg.Quantity(1, "")) == 2
+        assert f(module_registry.Quantity(1, "")) == 2
         with pytest.raises(DimensionalityError):
-            f(ureg.Quantity(1, "m"))
+            f(module_registry.Quantity(1, "m"))
 
-    def test_issue625a(self):
-        Q_ = ureg.Quantity
+    def test_issue625a(self, module_registry):
+        Q_ = module_registry.Quantity
         from math import sqrt
 
-        @ureg.wraps(ureg.second, (ureg.meters, ureg.meters / ureg.second ** 2))
+        @module_registry.wraps(
+            module_registry.second,
+            (
+                module_registry.meters,
+                module_registry.meters / module_registry.second ** 2,
+            ),
+        )
         def calculate_time_to_fall(height, gravity=Q_(9.8, "m/s^2")):
             """Calculate time to fall from a height h with a default gravity.
 
@@ -534,10 +550,10 @@ class TestIssues(QuantityTestCase):
         t2 = calculate_time_to_fall(lunar_module_height, moon_gravity)
         assert round(abs(t2 - Q_(3.508232077228117, "s")), 7) == 0
 
-    def test_issue625b(self):
-        Q_ = ureg.Quantity
+    def test_issue625b(self, module_registry):
+        Q_ = module_registry.Quantity
 
-        @ureg.wraps("=A*B", ("=A", "=B"))
+        @module_registry.wraps("=A*B", ("=A", "=B"))
         def get_displacement(time, rate=Q_(1, "m/s")):
             """Calculates displacement from a duration and default rate.
 
@@ -573,24 +589,24 @@ class TestIssues(QuantityTestCase):
         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
+    def test_issue655a(self, module_registry):
+        distance = 1 * module_registry.m
+        time = 1 * module_registry.s
         velocity = distance / time
         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
+    def test_issue655b(self, module_registry):
+        Q_ = module_registry.Quantity
 
-        @ureg.check("[length]", "[length]/[time]^2")
+        @module_registry.check("[length]", "[length]/[time]^2")
         def pendulum_period(length, G=Q_(1, "standard_gravity")):
             # print(length)
             return (2 * math.pi * (length / G) ** 0.5).to("s")
 
-        length = Q_(1, ureg.m)
+        length = Q_(1, module_registry.m)
         # Assume earth gravity
         t = pendulum_period(length)
         assert round(abs(t - Q_("2.0064092925890407 second")), 7) == 0
@@ -599,18 +615,18 @@ class TestIssues(QuantityTestCase):
         t = pendulum_period(length, moon_gravity)
         assert round(abs(t - Q_("4.928936075204336 second")), 7) == 0
 
-    def test_issue783(self):
-        assert not ureg("g") == []
+    def test_issue783(self, module_registry):
+        assert not module_registry("g") == []
 
-    def test_issue856(self):
+    def test_issue856(self, module_registry):
         ph1 = ParserHelper(scale=123)
         ph2 = copy.deepcopy(ph1)
         assert ph2.scale == ph1.scale
 
-        ureg1 = UnitRegistry()
-        ureg2 = copy.deepcopy(ureg1)
+        module_registry1 = UnitRegistry()
+        module_registry2 = copy.deepcopy(module_registry1)
         # Very basic functionality test
-        assert ureg2("1 t").to("kg").magnitude == 1000
+        assert module_registry2("1 t").to("kg").magnitude == 1000
 
     def test_issue856b(self):
         # Test that, after a deepcopy(), the two UnitRegistries are
@@ -641,13 +657,13 @@ class TestIssues(QuantityTestCase):
         assert a != c
 
     def test_issue902(self):
-        ureg = UnitRegistry(auto_reduce_dimensions=True)
-        velocity = 1 * ureg.m / ureg.s
-        cross_section = 1 * ureg.um ** 2
+        module_registry = UnitRegistry(auto_reduce_dimensions=True)
+        velocity = 1 * module_registry.m / module_registry.s
+        cross_section = 1 * module_registry.um ** 2
         result = cross_section / velocity
-        assert result == 1e-12 * ureg.m * ureg.s
+        assert result == 1e-12 * module_registry.m * module_registry.s
 
-    def test_issue912(self):
+    def test_issue912(self, module_registry):
         """pprint.pformat() invokes sorted() on large sets and frozensets and graciously
         handles TypeError, but not generic Exceptions. This test will fail if
         pint.DimensionalityError stops being a subclass of TypeError.
@@ -659,53 +675,55 @@ class TestIssues(QuantityTestCase):
         -------
 
         """
-        meter_units = ureg.get_compatible_units(ureg.meter)
-        hertz_units = ureg.get_compatible_units(ureg.hertz)
+        meter_units = module_registry.get_compatible_units(module_registry.meter)
+        hertz_units = module_registry.get_compatible_units(module_registry.hertz)
         pprint.pformat(meter_units | hertz_units)
 
-    def test_issue932(self):
-        q = ureg.Quantity("1 kg")
+    def test_issue932(self, module_registry):
+        q = module_registry.Quantity("1 kg")
         with pytest.raises(DimensionalityError):
             q.to("joule")
-        ureg.enable_contexts("energy", *(Context() for _ in range(20)))
+        module_registry.enable_contexts("energy", *(Context() for _ in range(20)))
         q.to("joule")
-        ureg.disable_contexts()
+        module_registry.disable_contexts()
         with pytest.raises(DimensionalityError):
             q.to("joule")
 
-    def test_issue960(self):
-        q = (1 * ureg.nanometer).to_compact("micrometer")
-        assert q.units == ureg.nanometer
+    def test_issue960(self, module_registry):
+        q = (1 * module_registry.nanometer).to_compact("micrometer")
+        assert q.units == module_registry.nanometer
         assert q.magnitude == 1
 
-    def test_issue1032(self):
+    def test_issue1032(self, module_registry):
         class MultiplicativeDictionary(dict):
             def __rmul__(self, other):
                 return self.__class__(
                     {key: value * other for key, value in self.items()}
                 )
 
-        q = 3 * ureg.s
+        q = 3 * module_registry.s
         d = MultiplicativeDictionary({4: 5, 6: 7})
-        assert q * d == MultiplicativeDictionary({4: 15 * ureg.s, 6: 21 * ureg.s})
+        assert q * d == MultiplicativeDictionary(
+            {4: 15 * module_registry.s, 6: 21 * module_registry.s}
+        )
         with pytest.raises(TypeError):
             d * q
 
     @helpers.requires_numpy
-    def test_issue973(self):
+    def test_issue973(self, module_registry):
         """Verify that an empty array Quantity can be created through multiplication."""
-        q0 = np.array([]) * ureg.m  # by Unit
-        q1 = np.array([]) * ureg("m")  # by Quantity
-        assert isinstance(q0, ureg.Quantity)
-        assert isinstance(q1, ureg.Quantity)
+        q0 = np.array([]) * module_registry.m  # by Unit
+        q1 = np.array([]) * module_registry("m")  # by Quantity
+        assert isinstance(q0, module_registry.Quantity)
+        assert isinstance(q1, module_registry.Quantity)
         assert len(q0) == len(q1) == 0
 
-    def test_issue1058(self):
+    def test_issue1058(self, module_registry):
         """verify that auto-reducing quantities with three or more units
         of same base type succeeds"""
-        q = 1 * ureg.mg / ureg.g / ureg.kg
+        q = 1 * module_registry.mg / module_registry.g / module_registry.kg
         q.ito_reduced_units()
-        assert isinstance(q, ureg.Quantity)
+        assert isinstance(q, module_registry.Quantity)
 
     def test_issue1062_issue1097(self):
         # Must not be used by any other tests
@@ -728,16 +746,16 @@ class TestIssues(QuantityTestCase):
         helpers.assert_quantity_equal(q_4barg_a, q_5bar)
         helpers.assert_quantity_equal(q_4barg_b, q_5bar)
 
-    def test_issue1086(self):
+    def test_issue1086(self, module_registry):
         # units with prefixes should correctly test as 'in' the registry
-        assert "bits" in ureg
-        assert "gigabits" in ureg
-        assert "meters" in ureg
-        assert "kilometers" in ureg
+        assert "bits" in module_registry
+        assert "gigabits" in module_registry
+        assert "meters" in module_registry
+        assert "kilometers" in module_registry
         # unknown or incorrect units should test as 'not in' the registry
-        assert "magicbits" not in ureg
-        assert "unknownmeters" not in ureg
-        assert "gigatrees" not in ureg
+        assert "magicbits" not in module_registry
+        assert "unknownmeters" not in module_registry
+        assert "gigatrees" not in module_registry
 
     def test_issue1112(self):
         ureg = UnitRegistry(
@@ -765,34 +783,36 @@ class TestIssues(QuantityTestCase):
         ureg.enable_contexts("c3")
 
     @helpers.requires_numpy
-    def test_issue1144_1102(self):
+    def test_issue1144_1102(self, module_registry):
         # Performing operations shouldn't modify the original objects
         # Issue 1144
         ddc = "delta_degree_Celsius"
-        q1 = ureg.Quantity([-287.78, -32.24, -1.94], ddc)
-        q2 = ureg.Quantity(70.0, "degree_Fahrenheit")
+        q1 = module_registry.Quantity([-287.78, -32.24, -1.94], ddc)
+        q2 = module_registry.Quantity(70.0, "degree_Fahrenheit")
         q1 - q2
-        assert all(q1 == ureg.Quantity([-287.78, -32.24, -1.94], ddc))
-        assert q2 == ureg.Quantity(70.0, "degree_Fahrenheit")
+        assert all(q1 == module_registry.Quantity([-287.78, -32.24, -1.94], ddc))
+        assert q2 == module_registry.Quantity(70.0, "degree_Fahrenheit")
         q2 - q1
-        assert all(q1 == ureg.Quantity([-287.78, -32.24, -1.94], ddc))
-        assert q2 == ureg.Quantity(70.0, "degree_Fahrenheit")
+        assert all(q1 == module_registry.Quantity([-287.78, -32.24, -1.94], ddc))
+        assert q2 == module_registry.Quantity(70.0, "degree_Fahrenheit")
         # Issue 1102
-        val = [30.0, 45.0, 60.0] * ureg.degree
+        val = [30.0, 45.0, 60.0] * module_registry.degree
         val == 1
         1 == val
-        assert all(val == ureg.Quantity([30.0, 45.0, 60.0], "degree"))
+        assert all(val == module_registry.Quantity([30.0, 45.0, 60.0], "degree"))
         # Test for another bug identified by searching on "_convert_magnitude"
-        q2 = ureg.Quantity(3, "degree_Kelvin")
+        q2 = module_registry.Quantity(3, "degree_Kelvin")
         q1 - q2
-        assert all(q1 == ureg.Quantity([-287.78, -32.24, -1.94], ddc))
+        assert all(q1 == module_registry.Quantity([-287.78, -32.24, -1.94], ddc))
 
     @helpers.requires_numpy
-    def test_issue_1136(self):
-        assert (2 ** ureg.Quantity([2, 3], "") == 2 ** np.array([2, 3])).all()
+    def test_issue_1136(self, module_registry):
+        assert (
+            2 ** module_registry.Quantity([2, 3], "") == 2 ** np.array([2, 3])
+        ).all()
 
         with pytest.raises(DimensionalityError):
-            2 ** ureg.Quantity([2, 3], "m")
+            2 ** module_registry.Quantity([2, 3], "m")
 
     def test_issue1175(self):
         import pickle
@@ -803,16 +823,18 @@ class TestIssues(QuantityTestCase):
         assert isinstance(foo2, foo1.__class__)
 
     @helpers.requires_numpy
-    def test_issue1174(self):
-        q = [1.0, -2.0, 3.0, -4.0] * self.ureg.meter
+    def test_issue1174(self, module_registry):
+        q = [1.0, -2.0, 3.0, -4.0] * module_registry.meter
         assert np.sign(q[0].magnitude)
         assert np.sign(q[1].magnitude)
 
     @helpers.requires_numpy()
-    def test_issue_1185(self):
+    def test_issue_1185(self, module_registry):
         # Test __pow__
-        foo = ureg.Quantity((3, 3), "mm / cm")
-        assert np.allclose(foo ** ureg.Quantity([2, 3], ""), 0.3 ** np.array([2, 3]))
+        foo = module_registry.Quantity((3, 3), "mm / cm")
+        assert np.allclose(
+            foo ** module_registry.Quantity([2, 3], ""), 0.3 ** np.array([2, 3])
+        )
         assert np.allclose(foo ** np.array([2, 3]), 0.3 ** np.array([2, 3]))
         assert np.allclose(np.array([2, 3]) ** foo, np.array([2, 3]) ** 0.3)
         # Test __ipow__
@@ -820,19 +842,21 @@ class TestIssues(QuantityTestCase):
         assert np.allclose(foo, 0.3 ** np.array([2, 3]))
         # Test __rpow__
         assert np.allclose(
-            np.array((1, 1)).__rpow__(ureg.Quantity((2, 3), "mm / cm")),
+            np.array((1, 1)).__rpow__(module_registry.Quantity((2, 3), "mm / cm")),
             np.array((0.2, 0.3)),
         )
         assert np.allclose(
-            ureg.Quantity((20, 20), "mm / cm").__rpow__(np.array((0.2, 0.3))),
+            module_registry.Quantity((20, 20), "mm / cm").__rpow__(
+                np.array((0.2, 0.3))
+            ),
             np.array((0.04, 0.09)),
         )
 
     @helpers.requires_uncertainties()
     def test_issue_1300(self):
-        ureg = UnitRegistry()
-        ureg.default_format = "~P"
-        m = ureg.Measurement(1, 0.1, "meter")
+        module_registry = UnitRegistry()
+        module_registry.default_format = "~P"
+        m = module_registry.Measurement(1, 0.1, "meter")
         assert m.default_format == "~P"
 
 
@@ -854,18 +878,25 @@ if np is not None:
         ],
     )
     @pytest.mark.parametrize(
-        "q",
+        "q_params",
         [
-            pytest.param(ureg.Quantity(1, "m"), id="python scalar int"),
-            pytest.param(ureg.Quantity([1, 2, 3, 4], "m"), id="array int"),
-            pytest.param(ureg.Quantity([1], "m")[0], id="numpy scalar int"),
-            pytest.param(ureg.Quantity(1.0, "m"), id="python scalar float"),
-            pytest.param(ureg.Quantity([1.0, 2.0, 3.0, 4.0], "m"), id="array float"),
-            pytest.param(ureg.Quantity([1.0], "m")[0], id="numpy scalar float"),
+            pytest.param((1, "m"), id="python scalar int"),
+            pytest.param(([1, 2, 3, 4], "m"), id="array int"),
+            pytest.param(([1], "m", 0), id="numpy scalar int"),
+            pytest.param((1.0, "m"), id="python scalar float"),
+            pytest.param(([1.0, 2.0, 3.0, 4.0], "m"), id="array float"),
+            pytest.param(([1.0], "m", 0), id="numpy scalar float"),
         ],
     )
-    def test_issue925(callable, q):
+    def test_issue925(module_registry, callable, q_params):
         # Test for immutability of type
+        if len(q_params) == 3:
+            q_params, el = q_params[:2], q_params[2]
+        else:
+            el = None
+        q = module_registry.Quantity(*q_params)
+        if el is not None:
+            q = q[el]
         type_before = type(q._magnitude)
         callable(q)
         assert isinstance(q._magnitude, type_before)
diff --git a/pint/testsuite/test_log_units.py b/pint/testsuite/test_log_units.py
index 77eba02..2215c2c 100644
--- a/pint/testsuite/test_log_units.py
+++ b/pint/testsuite/test_log_units.py
@@ -9,15 +9,11 @@ from pint.unit import Unit, UnitsContainer
 
 
 @pytest.fixture(scope="module")
-def auto_ureg():
+def module_registry_auto_offset():
     return UnitRegistry(autoconvert_offset_to_baseunit=True)
 
 
-@pytest.fixture(scope="module")
-def ureg():
-    return UnitRegistry()
-
-
+# TODO: do not subclass from QuantityTestCase
 class TestLogarithmicQuantity(QuantityTestCase):
     def test_log_quantity_creation(self, caplog):
 
@@ -76,7 +72,7 @@ class TestLogarithmicQuantity(QuantityTestCase):
         # 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 pytest.raises(OffsetUnitCalculusError):
-            (-10.0 * self.ureg.dB) / (1 * self.ureg.cm)
+            (-10.0 * self.ureg.dB) / (1 * self.module_registry.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:
@@ -100,36 +96,36 @@ log_unit_names = [
 
 
 @pytest.mark.parametrize("unit_name", log_unit_names)
-def test_unit_by_attribute(ureg, unit_name):
+def test_unit_by_attribute(module_registry, unit_name):
     """Can the logarithmic units be accessed by attribute lookups?"""
-    unit = getattr(ureg, unit_name)
+    unit = getattr(module_registry, unit_name)
     assert isinstance(unit, Unit)
 
 
 @pytest.mark.parametrize("unit_name", log_unit_names)
-def test_unit_parsing(ureg, unit_name):
+def test_unit_parsing(module_registry, unit_name):
     """Can the logarithmic units be understood by the parser?"""
-    unit = ureg.parse_units(unit_name)
+    unit = module_registry.parse_units(unit_name)
     assert isinstance(unit, Unit)
 
 
 @pytest.mark.parametrize("mag", [1.0, 4.2])
 @pytest.mark.parametrize("unit_name", log_unit_names)
-def test_quantity_by_constructor(ureg, unit_name, mag):
+def test_quantity_by_constructor(module_registry, unit_name, mag):
     """Can Quantity() objects be constructed using logarithmic units?"""
-    q = ureg.Quantity(mag, unit_name)
+    q = module_registry.Quantity(mag, unit_name)
     assert q.magnitude == pytest.approx(mag)
-    assert q.units == getattr(ureg, unit_name)
+    assert q.units == getattr(module_registry, unit_name)
 
 
 @pytest.mark.parametrize("mag", [1.0, 4.2])
 @pytest.mark.parametrize("unit_name", log_unit_names)
-def test_quantity_by_multiplication(auto_ureg, unit_name, mag):
+def test_quantity_by_multiplication(module_registry_auto_offset, unit_name, mag):
     """Test that logarithmic units can be defined with multiplication
 
     Requires setting `autoconvert_offset_to_baseunit` to True
     """
-    unit = getattr(auto_ureg, unit_name)
+    unit = getattr(module_registry_auto_offset, unit_name)
     q = mag * unit
     assert q.magnitude == pytest.approx(mag)
     assert q.units == unit
@@ -144,9 +140,9 @@ def test_quantity_by_multiplication(auto_ureg, unit_name, mag):
         ("octave", "oct"),
     ],
 )
-def test_unit_equivalence(ureg, unit1, unit2):
+def test_unit_equivalence(module_registry, unit1, unit2):
     """Are certain pairs of units equivalent?"""
-    assert getattr(ureg, unit1) == getattr(ureg, unit2)
+    assert getattr(module_registry, unit1) == getattr(module_registry, unit2)
 
 
 @pytest.mark.parametrize(
@@ -159,9 +155,9 @@ def test_unit_equivalence(ureg, unit1, unit2):
         (60.0, 1e6),
     ],
 )
-def test_db_conversion(ureg, db_value, scalar):
+def test_db_conversion(module_registry, db_value, scalar):
     """Test that a dB value can be converted to a scalar and back."""
-    Q_ = ureg.Quantity
+    Q_ = module_registry.Quantity
     assert Q_(db_value, "dB").to("dimensionless").magnitude == pytest.approx(scalar)
     assert Q_(scalar, "dimensionless").to("dB").magnitude == pytest.approx(db_value)
 
@@ -176,9 +172,9 @@ def test_db_conversion(ureg, db_value, scalar):
         (-2.0, 0.25),
     ],
 )
-def test_octave_conversion(ureg, octave, scalar):
+def test_octave_conversion(module_registry, octave, scalar):
     """Test that an octave can be converted to a scalar and back."""
-    Q_ = ureg.Quantity
+    Q_ = module_registry.Quantity
     assert Q_(octave, "octave").to("dimensionless").magnitude == pytest.approx(scalar)
     assert Q_(scalar, "dimensionless").to("octave").magnitude == pytest.approx(octave)
 
@@ -193,9 +189,9 @@ def test_octave_conversion(ureg, octave, scalar):
         (-2.0, 0.01),
     ],
 )
-def test_decade_conversion(ureg, decade, scalar):
+def test_decade_conversion(module_registry, decade, scalar):
     """Test that a decade can be converted to a scalar and back."""
-    Q_ = ureg.Quantity
+    Q_ = module_registry.Quantity
     assert Q_(decade, "decade").to("dimensionless").magnitude == pytest.approx(scalar)
     assert Q_(scalar, "dimensionless").to("decade").magnitude == pytest.approx(decade)
 
@@ -210,50 +206,52 @@ def test_decade_conversion(ureg, decade, scalar):
         (-20.0, 0.01),
     ],
 )
-def test_dbm_mw_conversion(ureg, dbm_value, mw_value):
+def test_dbm_mw_conversion(module_registry, dbm_value, mw_value):
     """Test dBm values can convert to mW and back."""
-    Q_ = ureg.Quantity
+    Q_ = module_registry.Quantity
     assert Q_(dbm_value, "dBm").to("mW").magnitude == pytest.approx(mw_value)
     assert Q_(mw_value, "mW").to("dBm").magnitude == pytest.approx(dbm_value)
 
 
 @pytest.mark.xfail
-def test_compound_log_unit_multiply_definition(auto_ureg):
+def test_compound_log_unit_multiply_definition(module_registry_auto_offset):
     """Check that compound log units can be defined using multiply."""
-    Q_ = auto_ureg.Quantity
-    canonical_def = Q_(-161, "dBm") / auto_ureg.Hz
-    mult_def = -161 * auto_ureg("dBm/Hz")
+    Q_ = module_registry_auto_offset.Quantity
+    canonical_def = Q_(-161, "dBm") / module_registry_auto_offset.Hz
+    mult_def = -161 * module_registry_auto_offset("dBm/Hz")
     assert mult_def == canonical_def
 
 
 @pytest.mark.xfail
-def test_compound_log_unit_quantity_definition(auto_ureg):
+def test_compound_log_unit_quantity_definition(module_registry_auto_offset):
     """Check that compound log units can be defined using ``Quantity()``."""
-    Q_ = auto_ureg.Quantity
-    canonical_def = Q_(-161, "dBm") / auto_ureg.Hz
+    Q_ = module_registry_auto_offset.Quantity
+    canonical_def = Q_(-161, "dBm") / module_registry_auto_offset.Hz
     quantity_def = Q_(-161, "dBm/Hz")
     assert quantity_def == canonical_def
 
 
-def test_compound_log_unit_parse_definition(auto_ureg):
-    Q_ = auto_ureg.Quantity
-    canonical_def = Q_(-161, "dBm") / auto_ureg.Hz
-    parse_def = auto_ureg("-161 dBm/Hz")
+def test_compound_log_unit_parse_definition(module_registry_auto_offset):
+    Q_ = module_registry_auto_offset.Quantity
+    canonical_def = Q_(-161, "dBm") / module_registry_auto_offset.Hz
+    parse_def = module_registry_auto_offset("-161 dBm/Hz")
     assert parse_def == canonical_def
 
 
-def test_compound_log_unit_parse_expr(auto_ureg):
+def test_compound_log_unit_parse_expr(module_registry_auto_offset):
     """Check that compound log units can be defined using ``parse_expression()``."""
-    Q_ = auto_ureg.Quantity
-    canonical_def = Q_(-161, "dBm") / auto_ureg.Hz
-    parse_def = auto_ureg.parse_expression("-161 dBm/Hz")
+    Q_ = module_registry_auto_offset.Quantity
+    canonical_def = Q_(-161, "dBm") / module_registry_auto_offset.Hz
+    parse_def = module_registry_auto_offset.parse_expression("-161 dBm/Hz")
     assert canonical_def == parse_def
 
 
 @pytest.mark.xfail
-def test_dbm_db_addition(auto_ureg):
+def test_dbm_db_addition(module_registry_auto_offset):
     """Test a dB value can be added to a dBm and the answer is correct."""
-    power = (5 * auto_ureg.dBm) + (10 * auto_ureg.dB)
+    power = (5 * module_registry_auto_offset.dBm) + (
+        10 * module_registry_auto_offset.dB
+    )
     assert power.to("dBm").magnitude == pytest.approx(15)
 
 
@@ -266,10 +264,10 @@ def test_dbm_db_addition(auto_ureg):
         (200, 0.0, 200),
     ],  # noqa: E231
 )
-def test_frequency_octave_addition(auto_ureg, freq1, octaves, freq2):
+def test_frequency_octave_addition(module_registry_auto_offset, freq1, octaves, freq2):
     """Test an Octave can be added to a frequency correctly"""
-    freq1 = freq1 * auto_ureg.Hz
-    shift = octaves * auto_ureg.Octave
+    freq1 = freq1 * module_registry_auto_offset.Hz
+    shift = octaves * module_registry_auto_offset.Octave
     new_freq = freq1 + shift
     assert new_freq.units == freq1.units
     assert new_freq.magnitude == pytest.approx(freq2)
diff --git a/pint/testsuite/test_matplotlib.py b/pint/testsuite/test_matplotlib.py
index 3c590ae..25f3172 100644
--- a/pint/testsuite/test_matplotlib.py
+++ b/pint/testsuite/test_matplotlib.py
@@ -6,38 +6,43 @@ from pint import UnitRegistry
 plt = pytest.importorskip("matplotlib.pyplot", reason="matplotlib is not available")
 np = pytest.importorskip("numpy", reason="NumPy is not available")
 
-# Set up unit registry for matplotlib
-ureg = UnitRegistry()
-ureg.setup_matplotlib(True)
+
+@pytest.fixture(scope="module")
+def local_registry():
+    # Set up unit registry for matplotlib
+    ureg = UnitRegistry()
+    ureg.setup_matplotlib(True)
+    return ureg
+
 
 # Set up matplotlib
 plt.switch_backend("agg")
 
 
 @pytest.mark.mpl_image_compare(tolerance=0, remove_text=True)
-def test_basic_plot():
-    y = np.linspace(0, 30) * ureg.miles
-    x = np.linspace(0, 5) * ureg.hours
+def test_basic_plot(local_registry):
+    y = np.linspace(0, 30) * local_registry.miles
+    x = np.linspace(0, 5) * local_registry.hours
 
     fig, ax = plt.subplots()
     ax.plot(x, y, "tab:blue")
-    ax.axhline(26400 * ureg.feet, color="tab:red")
-    ax.axvline(120 * ureg.minutes, color="tab:green")
+    ax.axhline(26400 * local_registry.feet, color="tab:red")
+    ax.axvline(120 * local_registry.minutes, color="tab:green")
 
     return fig
 
 
 @pytest.mark.mpl_image_compare(tolerance=0, remove_text=True)
-def test_plot_with_set_units():
-    y = np.linspace(0, 30) * ureg.miles
-    x = np.linspace(0, 5) * ureg.hours
+def test_plot_with_set_units(local_registry):
+    y = np.linspace(0, 30) * local_registry.miles
+    x = np.linspace(0, 5) * local_registry.hours
 
     fig, ax = plt.subplots()
-    ax.yaxis.set_units(ureg.inches)
-    ax.xaxis.set_units(ureg.seconds)
+    ax.yaxis.set_units(local_registry.inches)
+    ax.xaxis.set_units(local_registry.seconds)
 
     ax.plot(x, y, "tab:blue")
-    ax.axhline(26400 * ureg.feet, color="tab:red")
-    ax.axvline(120 * ureg.minutes, color="tab:green")
+    ax.axhline(26400 * local_registry.feet, color="tab:red")
+    ax.axvline(120 * local_registry.minutes, color="tab:green")
 
     return fig
diff --git a/pint/testsuite/test_measurement.py b/pint/testsuite/test_measurement.py
index 61427cd..fcc98a0 100644
--- a/pint/testsuite/test_measurement.py
+++ b/pint/testsuite/test_measurement.py
@@ -4,6 +4,7 @@ from pint import DimensionalityError
 from pint.testsuite import QuantityTestCase, helpers
 
 
+# TODO: do not subclass from QuantityTestCase
 @helpers.requires_not_uncertainties()
 class TestNotMeasurement(QuantityTestCase):
     def test_instantiate(self):
@@ -12,6 +13,7 @@ class TestNotMeasurement(QuantityTestCase):
             M_(4.0, 0.1, "s")
 
 
+# TODO: do not subclass from QuantityTestCase
 @helpers.requires_uncertainties()
 class TestMeasurement(QuantityTestCase):
     def test_simple(self):
diff --git a/pint/testsuite/test_non_int.py b/pint/testsuite/test_non_int.py
index 620a12a..f55afef 100644
--- a/pint/testsuite/test_non_int.py
+++ b/pint/testsuite/test_non_int.py
@@ -18,6 +18,7 @@ class FakeWrapper:
         self.q = q
 
 
+# TODO: do not subclass from QuantityTestCase
 class NonIntTypeQuantityTestCase(QuantityTestCase):
     def assert_quantity_almost_equal(
         self, first, second, rtol="1e-07", atol="0", msg=None
diff --git a/pint/testsuite/test_pint_eval.py b/pint/testsuite/test_pint_eval.py
index 2372933..bed8105 100644
--- a/pint/testsuite/test_pint_eval.py
+++ b/pint/testsuite/test_pint_eval.py
@@ -1,3 +1,5 @@
+import pytest
+
 from pint.compat import tokenizer
 from pint.pint_eval import build_eval_tree
 
@@ -6,61 +8,67 @@ class TestPintEval:
     def _test_one(self, input_text, parsed):
         assert build_eval_tree(tokenizer(input_text)).to_string() == parsed
 
-    def test_build_eval_tree(self):
-        self._test_one("3", "3")
-        self._test_one("1 + 2", "(1 + 2)")
-        # order of operations
-        self._test_one("2 * 3 + 4", "((2 * 3) + 4)")
-        # parentheses
-        self._test_one("2 * (3 + 4)", "(2 * (3 + 4))")
-        # more order of operations
-        self._test_one("1 + 2 * 3 ** (4 + 3 / 5)", "(1 + (2 * (3 ** (4 + (3 / 5)))))")
-        # nested parentheses at beginning
-        self._test_one("1 * ((3 + 4) * 5)", "(1 * ((3 + 4) * 5))")
-        # nested parentheses at end
-        self._test_one("1 * (5 * (3 + 4))", "(1 * (5 * (3 + 4)))")
-        # nested parentheses in middle
-        self._test_one("1 * (5 * (3 + 4) / 6)", "(1 * ((5 * (3 + 4)) / 6))")
-        # unary
-        self._test_one("-1", "(- 1)")
-        # unary
-        self._test_one("3 * -1", "(3 * (- 1))")
-        # double unary
-        self._test_one("3 * --1", "(3 * (- (- 1)))")
-        # parenthetical unary
-        self._test_one("3 * -(2 + 4)", "(3 * (- (2 + 4)))")
-        # parenthetical unary
-        self._test_one("3 * -((2 + 4))", "(3 * (- (2 + 4)))")
-        # implicit op
-        self._test_one("3 4", "(3 4)")
-        # implicit op, then parentheses
-        self._test_one("3 (2 + 4)", "(3 (2 + 4))")
-        # parentheses, then implicit
-        self._test_one("(3 ** 4 ) 5", "((3 ** 4) 5)")
-        # implicit op, then exponentiation
-        self._test_one("3 4 ** 5", "(3 (4 ** 5))")
-        # implicit op, then addition
-        self._test_one("3 4 + 5", "((3 4) + 5)")
-        # power followed by implicit
-        self._test_one("3 ** 4 5", "((3 ** 4) 5)")
-        # implicit with parentheses
-        self._test_one("3 (4 ** 5)", "(3 (4 ** 5))")
-        # exponent with e
-        self._test_one("3e-1", "3e-1")
-        # multiple units with exponents
-        self._test_one("kg ** 1 * s ** 2", "((kg ** 1) * (s ** 2))")
-        # multiple units with neg exponents
-        self._test_one("kg ** -1 * s ** -2", "((kg ** (- 1)) * (s ** (- 2)))")
-        # multiple units with neg exponents
-        self._test_one("kg^-1 * s^-2", "((kg ^ (- 1)) * (s ^ (- 2)))")
-        # multiple units with neg exponents, implicit op
-        self._test_one("kg^-1 s^-2", "((kg ^ (- 1)) (s ^ (- 2)))")
-        # nested power
-        self._test_one("2 ^ 3 ^ 2", "(2 ^ (3 ^ 2))")
-        # nested power
-        self._test_one("gram * second / meter ** 2", "((gram * second) / (meter ** 2))")
-        # nested power
-        self._test_one("gram / meter ** 2 / second", "((gram / (meter ** 2)) / second)")
-        # units should behave like numbers, so we don't need a bunch of extra tests for them
-        # implicit op, then addition
-        self._test_one("3 kg + 5", "((3 kg) + 5)")
+    @pytest.mark.parametrize(
+        ("input_text", "parsed"),
+        (
+            ("3", "3"),
+            ("1 + 2", "(1 + 2)"),
+            ("2 * 3 + 4", "((2 * 3) + 4)"),  # order of operations
+            ("2 * (3 + 4)", "(2 * (3 + 4))"),  # parentheses
+            (
+                "1 + 2 * 3 ** (4 + 3 / 5)",
+                "(1 + (2 * (3 ** (4 + (3 / 5)))))",
+            ),  # more order of operations
+            (
+                "1 * ((3 + 4) * 5)",
+                "(1 * ((3 + 4) * 5))",
+            ),  # nested parentheses at beginning
+            ("1 * (5 * (3 + 4))", "(1 * (5 * (3 + 4)))"),  # nested parentheses at end
+            (
+                "1 * (5 * (3 + 4) / 6)",
+                "(1 * ((5 * (3 + 4)) / 6))",
+            ),  # nested parentheses in middle
+            ("-1", "(- 1)"),  # unary
+            ("3 * -1", "(3 * (- 1))"),  # unary
+            ("3 * --1", "(3 * (- (- 1)))"),  # double unary
+            ("3 * -(2 + 4)", "(3 * (- (2 + 4)))"),  # parenthetical unary
+            ("3 * -((2 + 4))", "(3 * (- (2 + 4)))"),  # parenthetical unary
+            # implicit op
+            ("3 4", "(3 4)"),
+            # implicit op, then parentheses
+            ("3 (2 + 4)", "(3 (2 + 4))"),
+            # parentheses, then implicit
+            ("(3 ** 4 ) 5", "((3 ** 4) 5)"),
+            # implicit op, then exponentiation
+            ("3 4 ** 5", "(3 (4 ** 5))"),
+            # implicit op, then addition
+            ("3 4 + 5", "((3 4) + 5)"),
+            # power followed by implicit
+            ("3 ** 4 5", "((3 ** 4) 5)"),
+            # implicit with parentheses
+            ("3 (4 ** 5)", "(3 (4 ** 5))"),
+            # exponent with e
+            ("3e-1", "3e-1"),
+            # multiple units with exponents
+            ("kg ** 1 * s ** 2", "((kg ** 1) * (s ** 2))"),
+            # multiple units with neg exponents
+            ("kg ** -1 * s ** -2", "((kg ** (- 1)) * (s ** (- 2)))"),
+            # multiple units with neg exponents
+            ("kg^-1 * s^-2", "((kg ^ (- 1)) * (s ^ (- 2)))"),
+            # multiple units with neg exponents, implicit op
+            ("kg^-1 s^-2", "((kg ^ (- 1)) (s ^ (- 2)))"),
+            # nested power
+            ("2 ^ 3 ^ 2", "(2 ^ (3 ^ 2))"),
+            # nested power
+            ("gram * second / meter ** 2", "((gram * second) / (meter ** 2))"),
+            # nested power
+            ("gram / meter ** 2 / second", "((gram / (meter ** 2)) / second)"),
+            # units should behave like numbers, so we don't need a bunch of extra tests for them
+            # implicit op, then addition
+            ("3 kg + 5", "((3 kg) + 5)"),
+            ("(5 % 2) m", "((5 % 2) m)"),  # mod operator
+            ("(5 // 2) m", "((5 // 2) m)"),  # floordiv operator
+        ),
+    )
+    def test_build_eval_tree(self, input_text, parsed):
+        self._test_one(input_text, parsed)
diff --git a/pint/testsuite/test_pitheorem.py b/pint/testsuite/test_pitheorem.py
index 1a49962..a495882 100644
--- a/pint/testsuite/test_pitheorem.py
+++ b/pint/testsuite/test_pitheorem.py
@@ -5,6 +5,7 @@ from pint import pi_theorem
 from pint.testsuite import QuantityTestCase
 
 
+# TODO: do not subclass from QuantityTestCase
 class TestPiTheorem(QuantityTestCase):
     def test_simple(self, caplog):
 
diff --git a/pint/testsuite/test_quantity.py b/pint/testsuite/test_quantity.py
index 998a53d..c29fd19 100644
--- a/pint/testsuite/test_quantity.py
+++ b/pint/testsuite/test_quantity.py
@@ -27,6 +27,7 @@ class FakeWrapper:
         self.q = q
 
 
+# TODO: do not subclass from QuantityTestCase
 class TestQuantity(QuantityTestCase):
 
     kwargs = dict(autoconvert_offset_to_baseunit=False)
@@ -261,6 +262,24 @@ class TestQuantity(QuantityTestCase):
                 ureg.default_format = spec
                 assert f"{x}" == result
 
+    def test_formatting_override_default_units(self):
+        ureg = UnitRegistry()
+        ureg.default_format = "~"
+        x = ureg.Quantity(4, "m ** 2")
+
+        assert f"{x:dP}" == "4 meter²"
+        with pytest.warns(DeprecationWarning):
+            assert f"{x:d}" == "4 meter ** 2"
+
+    def test_formatting_override_default_magnitude(self):
+        ureg = UnitRegistry()
+        ureg.default_format = ".2f"
+        x = ureg.Quantity(4, "m ** 2")
+
+        assert f"{x:dP}" == "4 meter²"
+        with pytest.warns(DeprecationWarning):
+            assert f"{x:D}" == "4 meter ** 2"
+
     def test_exponent_formatting(self):
         ureg = UnitRegistry()
         x = ureg.Quantity(1e20, "meter")
@@ -646,6 +665,7 @@ class TestQuantity(QuantityTestCase):
         helpers.assert_quantity_equal(q.to_reduced_units(), self.Q_(0.5, "kg"))
 
 
+# TODO: do not subclass from QuantityTestCase
 class TestQuantityToCompact(QuantityTestCase):
     def assertQuantityAlmostIdentical(self, q1, q2):
         assert q1.units == q2.units
@@ -716,6 +736,7 @@ class TestQuantityToCompact(QuantityTestCase):
         )
 
 
+# TODO: do not subclass from QuantityTestCase
 class TestQuantityBasicMath(QuantityTestCase):
     def _test_inplace(self, operator, value1, value2, expected_result, unit=None):
         if isinstance(value1, str):
@@ -975,6 +996,7 @@ class TestQuantityBasicMath(QuantityTestCase):
                 fun(z)
 
 
+# TODO: do not subclass from QuantityTestCase
 class TestQuantityNeutralAdd(QuantityTestCase):
     """Addition to zero or NaN is allowed between a Quantity and a non-Quantity"""
 
@@ -1072,6 +1094,7 @@ class TestQuantityNeutralAdd(QuantityTestCase):
         helpers.assert_quantity_equal(z, -e)
 
 
+# TODO: do not subclass from QuantityTestCase
 class TestDimensions(QuantityTestCase):
     def test_get_dimensionality(self):
         get = self.ureg.get_dimensionality
@@ -1128,6 +1151,7 @@ class TestDimensionsWithDefaultRegistry(TestDimensions):
         cls.Q_ = cls.ureg.Quantity
 
 
+# TODO: do not subclass from QuantityTestCase
 class TestOffsetUnitMath(QuantityTestCase):
     @classmethod
     def setup_class(cls):
@@ -1722,6 +1746,7 @@ class TestDimensionReduction:
         assert x.units == ureg.foot
 
 
+# TODO: do not subclass from QuantityTestCase
 class TestTimedelta(QuantityTestCase):
     def test_add_sub(self):
         d = datetime.datetime(year=1968, month=1, day=10, hour=3, minute=42, second=24)
@@ -1750,6 +1775,7 @@ class TestTimedelta(QuantityTestCase):
             after -= d
 
 
+# TODO: do not subclass from QuantityTestCase
 class TestCompareNeutral(QuantityTestCase):
     """Test comparisons against non-Quantity zero or NaN values for for
     non-dimensionless quantities
diff --git a/pint/testsuite/test_systems.py b/pint/testsuite/test_systems.py
index 8c54d8f..fa7aff1 100644
--- a/pint/testsuite/test_systems.py
+++ b/pint/testsuite/test_systems.py
@@ -163,6 +163,7 @@ class TestGroup:
         assert c == frozenset([ureg.inch, ureg.yard])
 
 
+# TODO: do not subclass from QuantityTestCase
 class TestSystem(QuantityTestCase):
     def _build_empty_reg_root(self):
         ureg = UnitRegistry(None)
diff --git a/pint/testsuite/test_testing.py b/pint/testsuite/test_testing.py
new file mode 100644
index 0000000..666f3e1
--- /dev/null
+++ b/pint/testsuite/test_testing.py
@@ -0,0 +1,95 @@
+import pytest
+
+from .. import testing
+from ..quantity import Quantity
+
+np = pytest.importorskip("numpy")
+
+
+@pytest.mark.parametrize(
+    ["first", "second", "error", "message"],
+    (
+        pytest.param(
+            np.array([0, 1]), np.array([0, 1]), False, "", id="ndarray-None-None-equal"
+        ),
+        pytest.param(
+            Quantity(1, "m"),
+            1,
+            True,
+            "The first is not dimensionless",
+            id="mixed1-int-not equal-equal",
+        ),
+        pytest.param(
+            1,
+            Quantity(1, "m"),
+            True,
+            "The second is not dimensionless",
+            id="mixed2-int-not equal-equal",
+        ),
+        pytest.param(
+            Quantity(1, "m"), Quantity(1, "m"), False, "", id="Quantity-int-equal-equal"
+        ),
+        pytest.param(
+            Quantity(1, "m"),
+            Quantity(1, "s"),
+            True,
+            "Units are not equal",
+            id="Quantity-int-equal-not equal",
+        ),
+        pytest.param(
+            Quantity(1, "m"),
+            Quantity(2, "m"),
+            True,
+            "Magnitudes are not equal",
+            id="Quantity-int-not equal-equal",
+        ),
+        pytest.param(
+            Quantity(1, "m"),
+            Quantity(2, "s"),
+            True,
+            "Units are not equal",
+            id="Quantity-int-not equal-not equal",
+        ),
+        pytest.param(
+            Quantity(1, "m"),
+            Quantity(float("nan"), "m"),
+            True,
+            "Magnitudes are not equal",
+            id="Quantity-float-not equal-equal",
+        ),
+        pytest.param(
+            Quantity([1, 2], "m"),
+            Quantity([1, 2], "m"),
+            False,
+            "",
+            id="Quantity-ndarray-equal-equal",
+        ),
+        pytest.param(
+            Quantity([1, 2], "m"),
+            Quantity([1, 2], "s"),
+            True,
+            "Units are not equal",
+            id="Quantity-ndarray-equal-not equal",
+        ),
+        pytest.param(
+            Quantity([1, 2], "m"),
+            Quantity([2, 2], "m"),
+            True,
+            "Magnitudes are not equal",
+            id="Quantity-ndarray-not equal-equal",
+        ),
+        pytest.param(
+            Quantity([1, 2], "m"),
+            Quantity([2, 2], "s"),
+            True,
+            "Units are not equal",
+            id="Quantity-ndarray-not equal-not equal",
+        ),
+    ),
+)
+def test_assert_equal(first, second, error, message):
+    if error:
+        with pytest.raises(AssertionError, match=message):
+            testing.assert_equal(first, second)
+    else:
+        testing.assert_equal(first, second)
diff --git a/pint/testsuite/test_unit.py b/pint/testsuite/test_unit.py
index 5b8ea5a..bd4888e 100644
--- a/pint/testsuite/test_unit.py
+++ b/pint/testsuite/test_unit.py
@@ -18,6 +18,7 @@ from pint.testsuite import QuantityTestCase, helpers
 from pint.util import ParserHelper, UnitsContainer
 
 
+# TODO: do not subclass from QuantityTestCase
 class TestUnit(QuantityTestCase):
     def test_creation(self):
         for arg in ("meter", UnitsContainer(meter=1), self.U_("m")):
@@ -758,6 +759,7 @@ class TestCaseInsensitiveRegistry(QuantityTestCase):
         assert ureg.parse_units("j", case_sensitive=False) == UnitsContainer(joule=1)
 
 
+# TODO: do not subclass from QuantityTestCase
 class TestCompatibleUnits(QuantityTestCase):
     def _test(self, input_units):
         gd = self.ureg.get_dimensionality
@@ -852,6 +854,7 @@ class TestRegistryWithDefaultRegistry(TestRegistry):
             d("myk- = 1000 = kilo-")
 
 
+# TODO: remove QuantityTestCase
 class TestConvertWithOffset(QuantityTestCase):
 
     # The dicts in convert_with_offset are used to create a UnitsContainer.