Skip to content

Commit ed9fda8

Browse files
committed
Add tolerance to complex numbers
1 parent d1bc260 commit ed9fda8

File tree

3 files changed

+23
-8
lines changed

3 files changed

+23
-8
lines changed

changelog/6057.feature.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Add tolerances to complex values when printing ``pytest.approx``.
2+
3+
For example, ``repr(pytest.approx(3+4j))`` returns ``(3+4j) ± 5e-06 ∠ ±180°``. This is polar notation indicating a circle around the expected value, with a radius of 5e-06. For ``approx`` comparisons to return ``True``, the actual value should fall within this circle.

src/_pytest/python_api.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -223,26 +223,24 @@ class ApproxScalar(ApproxBase):
223223
def __repr__(self):
224224
"""
225225
Return a string communicating both the expected value and the tolerance
226-
for the comparison being made, e.g. '1.0 +- 1e-6'. Use the unicode
227-
plus/minus symbol if this is python3 (it's too hard to get right for
228-
python2).
226+
for the comparison being made, e.g. '1.0 ± 1e-6', '(3+4j) ± 5e-6 ∠ ±180°'.
229227
"""
230-
if isinstance(self.expected, complex):
231-
return str(self.expected)
232228

233229
# Infinities aren't compared using tolerances, so don't show a
234230
# tolerance.
235-
if math.isinf(self.expected):
231+
if math.isinf(abs(self.expected)):
236232
return str(self.expected)
237233

238234
# If a sensible tolerance can't be calculated, self.tolerance will
239235
# raise a ValueError. In this case, display '???'.
240236
try:
241237
vetted_tolerance = "{:.1e}".format(self.tolerance)
238+
if isinstance(self.expected, complex) and not math.isinf(self.tolerance):
239+
vetted_tolerance += " ∠ ±180°"
242240
except ValueError:
243241
vetted_tolerance = "???"
244242

245-
return "{} \u00b1 {}".format(self.expected, vetted_tolerance)
243+
return "{} ± {}".format(self.expected, vetted_tolerance)
246244

247245
def __eq__(self, actual):
248246
"""

testing/python/approx.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ def test_repr_string(self, plus_minus):
4646
assert repr(approx(1.0, rel=inf)) == "1.0 {pm} {infr}".format(
4747
pm=plus_minus, infr=infr
4848
)
49-
assert repr(approx(1.0j, rel=inf)) == "1j"
5049

5150
# Dictionaries aren't ordered, so we need to check both orders.
5251
assert repr(approx({"a": 1.0, "b": 2.0})) in (
@@ -58,6 +57,21 @@ def test_repr_string(self, plus_minus):
5857
),
5958
)
6059

60+
def test_repr_complex_numbers(self):
61+
assert repr(approx(inf + 1j)) == "(inf+1j)"
62+
assert repr(approx(1.0j, rel=inf)) == "1j ± inf"
63+
64+
# can't compute a sensible tolerance
65+
assert repr(approx(nan + 1j)) == "(nan+1j) ± ???"
66+
67+
assert repr(approx(1.0j)) == "1j ± 1.0e-06 ∠ ±180°"
68+
69+
# relative tolerance is scaled to |3+4j| = 5
70+
assert repr(approx(3 + 4 * 1j)) == "(3+4j) ± 5.0e-06 ∠ ±180°"
71+
72+
# absolute tolerance is not scaled
73+
assert repr(approx(3.3 + 4.4 * 1j, abs=0.02)) == "(3.3+4.4j) ± 2.0e-02 ∠ ±180°"
74+
6175
@pytest.mark.parametrize(
6276
"value, repr_string",
6377
[

0 commit comments

Comments
 (0)