pytest icon indicating copy to clipboard operation
pytest copied to clipboard

`pytest.approx` does not raise in mixed data type nested structures

Open jkittner opened this issue 3 years ago • 3 comments

description

when using pytest.approx on nested data structures I'd expect it to raise an exception also for mixed data type containers like a tuple in a list. So far it only works for the same data types e.g. lists in lists, tuples in tuples. For mixed data structures it incorrectly returns False, even though they should match which is a little misleading (also see below).

output of pip list

(venv) kittnjdr@ububox:~/workspace/pytest$ pip list
Package    Version                 Editable project location
---------- ----------------------- -------------------------------
attrs      22.1.0
iniconfig  1.1.1
packaging  21.3
pip        22.1.2
pluggy     1.0.0
py         1.11.0
pyparsing  3.0.9
pytest     7.2.0.dev232+gcc0092b9d /home/kittnjdr/workspace/pytest
setuptools 63.2.0
tomli      2.0.1
wheel      0.37.1

versions

  • pytest: main branch
  • OS: ubuntu 22.04

minimal reproduction

>>> import pytest
>>> [(1.0001,)] == pytest.approx([(1,)], rel=1e-2)
False
>>> ({1.0001},) == pytest.approx(({1},), rel=1e-2)
False
>>> ({"key": 1.0001},) == pytest.approx(({"key": 1},), rel=1e-2)
False
>>> (1.0001,) == pytest.approx((1,), rel=1e-2)
True
>>> ((1.0001,),) == pytest.approx(((1,),), rel=1e-2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/kittnjdr/workspace/pytest/src/_pytest/python_api.py", line 744, in approx
    return cls(expected, rel, abs, nan_ok)
  File "/home/kittnjdr/workspace/pytest/src/_pytest/python_api.py", line 86, in __init__
    self._check_type()
  File "/home/kittnjdr/workspace/pytest/src/_pytest/python_api.py", line 381, in _check_type
    raise TypeError(msg.format(x, index, pprint.pformat(self.expected)))
TypeError: pytest.approx() does not support nested data structures: (1,) at index 0
  full sequence: ((1,),)

however, it works fine if both are exactly the same, but here I'd also expect an exception instead of a result (which is correct, but maybe unintentional)

>>> [(1.0,)] == pytest.approx([(1.0,)])
True

test cases

These test cases fail, but should pass with the potential bug fixed.

diff --git a/testing/python/approx.py b/testing/python/approx.py
index 6acb466ff..31dd4638b 100644
--- a/testing/python/approx.py
+++ b/testing/python/approx.py
@@ -781,6 +781,10 @@ class TestApprox:
         "x, name",
         [
             pytest.param([[1]], "data structures", id="nested-list"),
+            pytest.param([(1,)], "data structures", id="nested-list-tuple"),
+            pytest.param([{1}], "data structures", id="nested-list-set"),
+            pytest.param([{"key": 1}], "data structures", id="nested-list-dict"),
             pytest.param({"key": {"key": 1}}, "dictionaries", id="nested-dict"),
         ],
     )

jkittner avatar Aug 12 '22 20:08 jkittner

I'm gonna try taking a look at this one, will update if I get stuck(this is my first issue in this project).

ptkenny avatar Aug 14 '22 00:08 ptkenny

This might be a tricky one, since some fundamental changes might be necessary. Ronny wrote:

I agree, feature creep happened, problem is that with a surround for the collection, the errors can't be done sanely

We just finished some early design discussions about that last month and it will take a while to manifest

jkittner avatar Aug 14 '22 01:08 jkittner

I released the PR anyway, if anything it might be a decent temporary fix.

ptkenny avatar Aug 14 '22 02:08 ptkenny

Hey guys! Not sure what is the state of this issue, but the bug is still there:

>>> pytest.approx([{"a": 0.1}], rel=1e-1) == [{"a": 0.11}]
False
>>> pytest.approx(0.1, rel=1e-1) == 0.11
True

Pytest version is 7.2.0

danielgafni avatar Dec 27 '22 17:12 danielgafni