Skip to content

bpo-30190: improved error msg for assertAlmostEqual(delta=...) #1331

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 21 additions & 14 deletions Lib/unittest/case.py
Original file line number Diff line number Diff line change
Expand Up @@ -856,23 +856,28 @@ def assertAlmostEqual(self, first, second, places=None, msg=None,
if delta is not None and places is not None:
raise TypeError("specify delta or places not both")

diff = abs(first - second)
if delta is not None:
if abs(first - second) <= delta:
if diff <= delta:
return

standardMsg = '%s != %s within %s delta' % (safe_repr(first),
safe_repr(second),
safe_repr(delta))
standardMsg = '%s != %s within %s delta (%s difference)' % (
safe_repr(first),
safe_repr(second),
safe_repr(delta),
safe_repr(diff))
else:
if places is None:
places = 7

if round(abs(second-first), places) == 0:
if round(diff, places) == 0:
return

standardMsg = '%s != %s within %r places' % (safe_repr(first),
safe_repr(second),
places)
standardMsg = '%s != %s within %r places (%s difference)' % (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about assertNotAlmostEqual()?

Copy link
Contributor Author

@giampaolo giampaolo Apr 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I'm understanding the code wrong but assertNotAlmostEqual fails if the two numbers are almost equal and just "off" by a little. So in case of:

assertNotAlmostEqual(1.00000001, 1.0, places=7)

The failure will look like this:

AssertionError 1.00000001 == 1.0 within 7 places

...which is already enough. Makes sense?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How this differs from the case when delta is specified?

Actually I don't know what is the use case for assertNotAlmostEqual(). It is not used in Python tests (except testing assertNotAlmostEqual() itself). I suggest to not change it at all.

Copy link
Contributor Author

@giampaolo giampaolo Apr 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To my understanding delta is entirely about acceptable difference (hence it makes sense to show the absolute diff) whereas places is about decimal precision.
I'm also not sure what's the use case for assertNotAlmostEqual() but whoever uses it will find this:

self.assertNotAlmostEqual(5, 10, delta=15)

...produces:

AssertionError: 5 == 10 within 15 delta (5 difference)

...more readable than the current message
So in summary, for assertNotAlmostEqual, I'd be for showing the difference if delta is specified but not if places is specified.

safe_repr(first),
safe_repr(second),
places,
safe_repr(diff))
msg = self._formatMessage(msg, standardMsg)
raise self.failureException(msg)

Expand All @@ -890,16 +895,19 @@ def assertNotAlmostEqual(self, first, second, places=None, msg=None,
"""
if delta is not None and places is not None:
raise TypeError("specify delta or places not both")
diff = abs(first - second)
if delta is not None:
if not (first == second) and abs(first - second) > delta:
if not (first == second) and diff > delta:
return
standardMsg = '%s == %s within %s delta' % (safe_repr(first),
safe_repr(second),
safe_repr(delta))
standardMsg = '%s == %s within %s delta (%s difference)' % (
safe_repr(first),
safe_repr(second),
safe_repr(delta),
safe_repr(diff))
else:
if places is None:
places = 7
if not (first == second) and round(abs(second-first), places) != 0:
if not (first == second) and round(diff, places) != 0:
return
standardMsg = '%s == %s within %r places' % (safe_repr(first),
safe_repr(second),
Expand All @@ -908,7 +916,6 @@ def assertNotAlmostEqual(self, first, second, places=None, msg=None,
msg = self._formatMessage(msg, standardMsg)
raise self.failureException(msg)


def assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None):
"""An equality assertion for ordered sequences (like lists and tuples).

Expand Down
8 changes: 5 additions & 3 deletions Lib/unittest/test/test_assertions.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,11 @@ def testNotEqual(self):
"^1 == 1 : oops$"])

def testAlmostEqual(self):
self.assertMessages('assertAlmostEqual', (1, 2),
["^1 != 2 within 7 places$", "^oops$",
"^1 != 2 within 7 places$", "^1 != 2 within 7 places : oops$"])
self.assertMessages(
'assertAlmostEqual', (1, 2),
["^1 != 2 within 7 places \(1 difference\)$", "^oops$",
"^1 != 2 within 7 places \(1 difference\)$",
"^1 != 2 within 7 places \(1 difference\) : oops$"])

def testNotAlmostEqual(self):
self.assertMessages('assertNotAlmostEqual', (1, 1),
Expand Down
6 changes: 5 additions & 1 deletion Misc/NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ What's New in Python 3.7.0 alpha 1?
Core and Builtins
-----------------

- bpo-12414: sys.getsizeof() on a code object now returns the sizes
- bpo-12414: sys.getsizeof() on a code object now returns the sizes
which includes the code struct and sizes of objects which it references.
Patch by Dong-hee Na.

Expand Down Expand Up @@ -317,6 +317,10 @@ Extension Modules
Library
-------

- bpo-30190: unittest's assertAlmostEqual and assertNotAlmostEqual provide a
better message in case of failure which includes the difference between
left and right arguments. (patch by Giampaolo Rodola')

- bpo-30101: Add support for curses.A_ITALIC.

- bpo-29822: inspect.isabstract() now works during __init_subclass__. Patch
Expand Down