-
-
Notifications
You must be signed in to change notification settings - Fork 35.3k
gh-71385: add relative delta parameter for assertAlmostEqual and assertNotAlmostEqual #96881
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
base: main
Are you sure you want to change the base?
Changes from all commits
b8e619a
6eeb2b9
0797a24
6151d7e
fc545ec
ca09f2e
1b01829
640ba3b
2d115d1
835bea7
e319648
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -958,24 +958,33 @@ def assertNotEqual(self, first, second, msg=None): | |
| raise self.failureException(msg) | ||
|
|
||
| def assertAlmostEqual(self, first, second, places=None, msg=None, | ||
| delta=None): | ||
| delta=None, rel_delta=None): | ||
| """Fail if the two objects are unequal as determined by their | ||
| difference rounded to the given number of decimal places | ||
| (default 7) and comparing to zero, or by comparing that the | ||
| difference between the two objects is more than the given | ||
| delta. | ||
| difference by one of the following methods: | ||
|
|
||
| Note that decimal places (from zero) are usually not the same | ||
| as significant digits (measured from the most significant digit). | ||
| 1) Given number of decimal places. This is the default method | ||
| (default value 7 digits). Note that decimal places (from | ||
| zero) are usually not the same as significant digits | ||
| (measured from the most significant digit). | ||
|
|
||
| 2) Comparing that the absolute difference between the two | ||
| objects is more than the given delta. | ||
|
|
||
| 3) Comparing that the relative difference between the two | ||
| objects is more than the given rel_delta, using the same | ||
| algorithm as :meth:`math.isclose`. | ||
|
|
||
| If the two objects compare equal then they will automatically | ||
| compare almost equal. | ||
| compare almost equal. Comparison of floating point numbers | ||
| (espaicially inf, -inf, and NaN) is applied in the same way as | ||
| in :meth:`math.isclose` according to IEEE standard 754. | ||
| """ | ||
| if first == second: | ||
| # shortcut | ||
| return | ||
| if delta is not None and places is not None: | ||
| raise TypeError("specify delta or places not both") | ||
| if int(delta is not None) + int(places is not None) + \ | ||
| int(rel_delta is not None) > 1: | ||
| raise TypeError("specify maximally one: delta, places or rel_delta") | ||
|
|
||
| diff = abs(first - second) | ||
| if delta is not None: | ||
|
|
@@ -987,6 +996,15 @@ def assertAlmostEqual(self, first, second, places=None, msg=None, | |
| safe_repr(second), | ||
| safe_repr(delta), | ||
| safe_repr(diff)) | ||
| elif rel_delta is not None: | ||
| if (diff < rel_delta*abs(first)) or (diff < rel_delta*abs(second)): | ||
| return | ||
|
Comment on lines
+999
to
+1001
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As per Mark's commentary, I think that behavior should match math.isclose(). Namely, in the given case (when But for |
||
|
|
||
| standardMsg = '%s != %s within relatively %s (%s rel. difference)' % ( | ||
| safe_repr(first), | ||
| safe_repr(second), | ||
| safe_repr(rel_delta), | ||
| safe_repr(diff/abs(first))) | ||
| else: | ||
| if places is None: | ||
| places = 7 | ||
|
|
@@ -1003,28 +1021,38 @@ def assertAlmostEqual(self, first, second, places=None, msg=None, | |
| raise self.failureException(msg) | ||
|
|
||
| def assertNotAlmostEqual(self, first, second, places=None, msg=None, | ||
| delta=None): | ||
| delta=None, rel_delta=None): | ||
| """Fail if the two objects are equal as determined by their | ||
| difference rounded to the given number of decimal places | ||
| (default 7) and comparing to zero, or by comparing that the | ||
| difference between the two objects is less than the given delta. | ||
|
|
||
| Note that decimal places (from zero) are usually not the same | ||
| as significant digits (measured from the most significant digit). | ||
| difference by one of the methods analougsly described for | ||
| assertAlmostEqual(). | ||
|
|
||
| Objects that are equal automatically fail. | ||
| """ | ||
| if delta is not None and places is not None: | ||
| raise TypeError("specify delta or places not both") | ||
| if int(delta is not None) + int(places is not None) + \ | ||
| int(rel_delta is not None) > 1: | ||
| raise TypeError("specify maximally one: delta, places or rel_delta") | ||
|
|
||
| diff = abs(first - second) | ||
|
|
||
| if delta is not None: | ||
| if not (first == second) and diff > delta: | ||
| if not (first == second) and ((diff > delta) or diff != diff): | ||
| return | ||
| standardMsg = '%s == %s within %s delta (%s difference)' % ( | ||
| safe_repr(first), | ||
| safe_repr(second), | ||
| safe_repr(delta), | ||
| safe_repr(diff)) | ||
| elif rel_delta is not None: | ||
| if not (first == second) and \ | ||
| (((diff > rel_delta*abs(first)) and (diff > rel_delta*abs(second))) | ||
| or (diff != diff) or (diff/2 == diff)): | ||
| return | ||
|
|
||
| standardMsg = '%s == %s within relatively %s (%s rel. difference)' % ( | ||
| safe_repr(first), | ||
| safe_repr(second), | ||
| safe_repr(rel_delta), | ||
| safe_repr(diff/abs(first))) | ||
| else: | ||
| if places is None: | ||
| places = 7 | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| A new parameter ``rel_delta`` was added to the :meth:`unittest.TestCase.assertAlmostEqual` and :meth:`unittest.TestCase.assertNotAlmostEqual`. It allows comparing two objects with a maximum relative difference to each other. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add two
datetimeobjects together withtimedeltaasrel_deltaThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my point of view this seems not well defined. The clearest method to see are the units: Within the calculation, we multiply the relative delta with one of the objects: timedelta * datetime would have a unit of square seconds ...