Skip to content

Commit

Permalink
Merge pull request #3696 from abrammer/approx_numpy_tolerance_bugfix
Browse files Browse the repository at this point in the history
bugfix in ApproxNumpy initialisation, use keywords for arguments to fix
  • Loading branch information
nicoddemus authored Jul 30, 2018
2 parents f1ec02c + 535fd1f commit 150535b
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 1 deletion.
2 changes: 2 additions & 0 deletions changelog/3695.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix ``ApproxNumpy`` initialisation argument mixup, ``abs`` and ``rel`` tolerances were flipped causing strange comparsion results.
Add tests to check ``abs`` and ``rel`` tolerances for ``np.array`` and test for expecting ``nan`` with ``np.array()``
2 changes: 1 addition & 1 deletion src/_pytest/python_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ def __eq__(self, actual):
the pre-specified tolerance.
"""
if _is_numpy_array(actual):
return ApproxNumpy(actual, self.abs, self.rel, self.nan_ok) == self.expected
return all(a == self for a in actual.flat)

# Short-circuit exact equality.
if actual == self.expected:
Expand Down
62 changes: 62 additions & 0 deletions testing/python/approx.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,68 @@ def test_numpy_array(self):
assert actual == approx(list(expected), rel=5e-7, abs=0)
assert actual != approx(list(expected), rel=5e-8, abs=0)

def test_numpy_tolerance_args(self):
"""
Check that numpy rel/abs args are handled correctly
for comparison against an np.array
Check both sides of the operator, hopefully it doesn't impact things.
Test all permutations of where the approx and np.array() can show up
"""
np = pytest.importorskip("numpy")
expected = 100.
actual = 99.
abs_diff = expected - actual
rel_diff = (expected - actual) / expected

tests = [
(eq, abs_diff, 0),
(eq, 0, rel_diff),
(ne, 0, rel_diff / 2.), # rel diff fail
(ne, abs_diff / 2., 0), # abs diff fail
]

for op, _abs, _rel in tests:
assert op(np.array(actual), approx(expected, abs=_abs, rel=_rel)) # a, b
assert op(approx(expected, abs=_abs, rel=_rel), np.array(actual)) # b, a

assert op(actual, approx(np.array(expected), abs=_abs, rel=_rel)) # a, b
assert op(approx(np.array(expected), abs=_abs, rel=_rel), actual) # b, a

assert op(np.array(actual), approx(np.array(expected), abs=_abs, rel=_rel))
assert op(approx(np.array(expected), abs=_abs, rel=_rel), np.array(actual))

def test_numpy_expecting_nan(self):
np = pytest.importorskip("numpy")
examples = [
(eq, nan, nan),
(eq, -nan, -nan),
(eq, nan, -nan),
(ne, 0.0, nan),
(ne, inf, nan),
]
for op, a, x in examples:
# Nothing is equal to NaN by default.
assert np.array(a) != approx(x)
assert a != approx(np.array(x))

# If ``nan_ok=True``, then NaN is equal to NaN.
assert op(np.array(a), approx(x, nan_ok=True))
assert op(a, approx(np.array(x), nan_ok=True))

def test_numpy_expecting_inf(self):
np = pytest.importorskip("numpy")
examples = [
(eq, inf, inf),
(eq, -inf, -inf),
(ne, inf, -inf),
(ne, 0.0, inf),
(ne, nan, inf),
]
for op, a, x in examples:
assert op(np.array(a), approx(x))
assert op(a, approx(np.array(x)))
assert op(np.array(a), approx(np.array(x)))

def test_numpy_array_wrong_shape(self):
np = pytest.importorskip("numpy")

Expand Down

0 comments on commit 150535b

Please sign in to comment.