diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 07794abea95..ad62306cfea 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -530,6 +530,17 @@ class ApproxDecimal(ApproxScalar): DEFAULT_ABSOLUTE_TOLERANCE = Decimal("1e-12") DEFAULT_RELATIVE_TOLERANCE = Decimal("1e-6") + def __repr__(self): + rel = Decimal(str(self.rel)) if isinstance(self.rel, float) else self.rel + abs_ = Decimal(str(self.abs)) if isinstance(self.abs, float) else self.abs + if rel is not None and Decimal("1e-3") <= rel <= Decimal("1e3"): + tol_str = f"{rel:.1e}" + elif abs_ is not None: + tol_str = f"{abs_:.1e}" + else: + tol_str = "???" + return f"{self.expected} ± {tol_str}" + def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase: """Assert that two numbers (or two ordered sequences of numbers) are equal to each other diff --git a/testing/test_decimal_approx.py b/testing/test_decimal_approx.py new file mode 100644 index 00000000000..6cd07399f36 --- /dev/null +++ b/testing/test_decimal_approx.py @@ -0,0 +1,16 @@ +from __future__ import annotations + +import decimal + +import pytest + + +def test_decimal_approx_repr_issue() -> None: + trap = decimal.getcontext().traps[decimal.FloatOperation] + decimal.getcontext().traps[decimal.FloatOperation] = False + + approx_obj = pytest.approx(decimal.Decimal("2.60")) + print(f"Attempting to represent pytest.approx(Decimal): {approx_obj}") + assert decimal.Decimal("2.600001") == approx_obj + + decimal.getcontext().traps[decimal.FloatOperation] = trap