diff --git a/changelog/9061.breaking.rst b/changelog/9061.breaking.rst new file mode 100644 index 00000000000..bf639e13214 --- /dev/null +++ b/changelog/9061.breaking.rst @@ -0,0 +1,15 @@ +Using :func:`pytest.approx` in a boolean context now raises an error hinting at the proper usage. + +It is apparently common for users to mistakenly use ``pytest.approx`` like this: + +.. code-block:: python + + assert pytest.approx(actual, expected) + +While the correct usage is: + +.. code-block:: python + + assert actual == pytest.approx(expected) + +The new error message helps catch those mistakes. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 847991a3708..8332bbe0a7b 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -100,6 +100,11 @@ def __eq__(self, actual) -> bool: a == self._approx_scalar(x) for a, x in self._yield_comparisons(actual) ) + def __bool__(self): + 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 diff --git a/testing/python/approx.py b/testing/python/approx.py index d4a152f3ea4..0d411d8a6da 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -319,6 +319,12 @@ def test_repr_nd_array(self, value, expected_repr_string): np_array = np.array(value) assert repr(approx(np_array)) == expected_repr_string + def test_bool(self): + with pytest.raises(AssertionError) as err: + assert approx(1) + + assert err.match(r"approx\(\) is not supported in a boolean context") + def test_operator_overloading(self): assert 1 == approx(1, rel=1e-6, abs=1e-12) assert not (1 != approx(1, rel=1e-6, abs=1e-12))