pytest-dev/pytest · error · AssertionError

approx() is not supported in a boolean context. Did you…

Error message

approx() is not supported in a boolean context.
Did you mean: `assert a == approx(b)`?

What it means

pytest.approx() returns an Approx object whose only meaningful operation is equality comparison (e.g. `a == approx(b)`). The class deliberately defines __bool__ to raise AssertionError so that misuses like `assert approx(x)` or `if approx(x):` fail loudly instead of silently passing or failing. pytest throws this because a bare truthiness check on an Approx value has no sensible meaning and would otherwise evaluate to True/False unpredictably.

Solutions

  1. Always write approx() on the right-hand side of ==: `assert actual == approx(expected)`.
  2. If you stored approx in a variable, compare it explicitly: `assert actual == expected_approx`.
  3. Search the failing test file for `assert approx(` (regex) and add the missing `actual ==` operand.

Example fix

# before
assert approx(0.3)
# after
assert 0.1 + 0.2 == approx(0.3)
Defensive patterns

Strategy: validation

Validate before calling

# Before using an approx value, ensure it is always compared, never evaluated as bool.
# Static check (regex in pre-commit / lint): reject `assert approx(` without `==`.
import re
def assert_uses_comparison(line: str) -> bool:
    # flag bare `assert approx(...)` or `assert <name> ` where name holds an Approx
    return bool(re.search(r'\bassert\s+approx\(', line)) and '==' not in line

Type guard

from pytest import Approx
def is_approx(obj) -> bool:
    return isinstance(obj, Approx)

Prevention

When it happens

Trigger: Calling bool(approx(x)), using approx(x) in an if/while/and/or expression, writing `assert approx(x)` without a comparison operand, passing approx(x) to a function that evaluates its argument's truthiness, or storing the result and later using it in a conditional. Triggered at Approx.__bool__ (src/_pytest/approx.py:110-114).

Common situations: Copy-pasting a test skeleton and forgetting the left-hand operand (assert approx(expected) instead of assert actual == approx(expected)); refactoring a comparison into a helper that returns the approx object; using approx() with pytest.warns/raises which evaluate truthiness of the returned context.

Related errors


AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11). Data as JSON: /api/errors/05b56d3b2fda749a. Report an issue: GitHub.

Appendix: source

Thrown at src/_pytest/approx.py:112

    @abc.abstractmethod
    def __repr__(self) -> str:
        raise NotImplementedError

    def _repr_compare(self, other_side) -> list[str]:
        return [
            "comparison failed",
            f"Obtained: {other_side}",
            f"Expected: {self}",
        ]

    def __eq__(self, actual) -> bool:
        return all(
            a == self._approx_scalar(x) for a, x in self._yield_comparisons(actual)
        )

    def __bool__(self):
        __tracebackhide__ = True
        raise AssertionError(
            "approx() is not supported in a boolean context.\nDid you mean: `assert a == approx(b)`?"
        )

    # Ignore type because of https://github.com/python/mypy/issues/4266.
    __hash__ = None  # type: ignore

    def _approx_scalar(self, x) -> ApproxScalar[Any] | ApproxTimedelta:
        if isinstance(x, Decimal):
            return ApproxDecimal(x, rel=self.rel, abs=self.abs, nan_ok=self.nan_ok)
        if isinstance(x, (datetime, timedelta)):
            return ApproxTimedelta(x, rel=self.rel, abs=self.abs, nan_ok=self.nan_ok)
        return ApproxScalar(x, rel=self.rel, abs=self.abs, nan_ok=self.nan_ok)

    def _yield_comparisons(self, actual: object):
        """Yield all the pairs of numbers to be compared.

        This is used to implement the `__eq__` method.
        """

View on GitHub (pinned to 0d6fbdeffa)