Repository navigation
TST: follow numpy/pytest traceback conventions in simple assert_* test helper functions - #16080
Conversation
|
Thank you for your contribution to Astropy! 🌌 This checklist is meant to remind the package maintainers who will review this pull request of some common things to look for.
|
|
|
||
|
|
||
| def assert_objects_equal(obj1, obj2, attrs, compare_class=True): | ||
| __tracebackhide__ = True |
There was a problem hiding this comment.
Not sure to understand the benefit. If a test fail I will want to know why and hence dive into this function to find which attribute and examine the value, so why hiding it ?
There was a problem hiding this comment.
I tried to explain the expected gain in #16071
I could furthermore add that:
- in a sense, this satisfies the principle of least surprise (as a user of
numpy.testing.assert_*functions, I grew to expect the internals of such functions to be hidden in tracebacks) - you can still opt-in the current behaviour using
--full-trace, while the behaviour this is enabling is not achievable currently
There was a problem hiding this comment.
I personally would be more surprised by not being able to know why I had a failure. The traceback would still go through the failure within the unit test. Often I end up having to bisect issues by examining these helper functions and making temporary modifications to them.
If we do go through with this change I suggest we carefully consider the error messages being raised so that they are more indicative of what has caused the failure.
There was a problem hiding this comment.
Yes but being useful for numpy.testing.assert_ doesn't mean it's always better. Here the code is specific to what is being tested and used by a few tests only, and there is a good chance that I will want to see the full traceback is there a problem.
Also the problem is that I don't know what to expect with __tracebackhide__ activated, what will pytest print ?
There was a problem hiding this comment.
As you'll have seen from my comment above, I agree with @saimn here - I can see representations as being a single object where one wants to hide the traceback, since their content is uniform, but not a more complicated object where one also compares attributes.
There was a problem hiding this comment.
If we do go through with this change I suggest we carefully consider the error messages being raised so that they are more indicative of what has caused the failure.
Also the problem is that I don't know what to expect with tracebackhide activated, what will pytest print ?
In short: pytest prints the exact same message as it would without __tracebackhide__, the difference is in the line that is associated with that message.
To illustrate let's take my t.py test module from #16071 (copied here in a dropdown for convenience)
t.py
# t.py
import numpy as np
def assert_equal_len_v1(x, y):
assert len(x) == len(y)
def assert_equal_len_v2(x, y):
__tracebackhide__ = True
assert len(x) == len(y)
def test_v1():
a = np.arange(2)
b = np.arange(3)
assert_equal_len_v1(a, b)
def test_v2():
a = np.arange(2)
b = np.arange(3)
assert_equal_len_v2(a, b)Here's the output
$ pytest t.py
====================== test session starts ======================
platform darwin -- Python 3.12.0, pytest-8.0.0, pluggy-1.4.0
...
t.py FF [100%]
=========================== FAILURES ============================
____________________________ test_v1 ____________________________
def test_v1():
a = np.arange(2)
b = np.arange(3)
> assert_equal_len_v1(a, b)
t.py:14:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
x = array([0, 1]), y = array([0, 1, 2])
def assert_equal_len_v1(x, y):
> assert len(x) == len(y)
E assert 2 == 3
E + where 2 = len(array([0, 1]))
E + and 3 = len(array([0, 1, 2]))
t.py:5: AssertionError
____________________________ test_v2 ____________________________
def test_v2():
a = np.arange(2)
b = np.arange(3)
> assert_equal_len_v2(a, b)
E assert 2 == 3
E + where 2 = len(array([0, 1]))
E + and 3 = len(array([0, 1, 2]))
t.py:19: AssertionError
==================== short test summary info ====================
FAILED t.py::test_v1 - assert 2 == 3
FAILED t.py::test_v2 - assert 2 == 3
======================= 2 failed in 0.06s =======================
mhvk
left a comment
There was a problem hiding this comment.
While I like the general idea, I think this goes too far. Note that the numpy assert_array_equal, etc., actually tell you about the mismatched elements; they don't just fail. I think in such a case there is indeed no reason to keep the full trace. However, absent that, one should have the trace for any function which does not have such a message - so I think we should not change any of the more complicated functions, where a lot of different things can go wrong.
Anyway, bottom line, I'd only do the simple ones that use assert_array_equal etc under the hood.
| @@ -26,12 +26,15 @@ def teardown_function(function): | |||
|
|
|||
| # Compatibility functions to convert from nose to pytest | |||
There was a problem hiding this comment.
Hmm, really these should just be replaced! But can be for follow-up...
There was a problem hiding this comment.
Right. I can do that as a follow up ! Meanwhile, I'll avoid touching them here
There was a problem hiding this comment.
These are being removed already in #15839, but in most instances the corresponding numpy.testing functions would be used; so if I understood you correctly, the numpy versions would already take care of setting __tracebackhide__? A couple uses of assert_equal would be changed to simple asserts though.
There was a problem hiding this comment.
thanks @eerovaher , I wasn't aware of this issue. Since it's mark with "good first issue" I should leave it to new contributors, right ?
if I understood you correctly, the numpy versions would already take care of setting
__tracebackhide__?
Correct ! For instance, see the first line in numpy.testing.assert_equal's definition https://github.com/numpy/numpy/blob/e920ca42d98c4911c2294784f8809b38735923a4/numpy/testing/_private/utils.py#L313
There was a problem hiding this comment.
Simple and non-critical tasks such as removing these functions are indeed best left for new contributors.
There was a problem hiding this comment.
thanks @eerovaher , I wasn't aware of this issue. Since it's mark with "good first issue" I should leave it to new contributors, right ?
It is all but done in #15839 already, but your comments would be very welcome there. Pretty much all that remains to be done is settling on where to best use numpy.testing.assert_equal() vs. assert a == b. And if this PR is being merged first, might be worth looking if the new asserts in #15839 should get their __tracebackhide__ as well.
There was a problem hiding this comment.
Thank you, I'll make sure to review this one tomorrow !
|
|
||
|
|
||
| def assert_objects_equal(obj1, obj2, attrs, compare_class=True): | ||
| __tracebackhide__ = True |
There was a problem hiding this comment.
As you'll have seen from my comment above, I agree with @saimn here - I can see representations as being a single object where one wants to hide the traceback, since their content is uniform, but not a more complicated object where one also compares attributes.
f578c44 to
356eccb
Compare
|
I'm not sure all labels are still appropriate, they were added by the bot based on my initial commit, which had a larger scope. |
|
Updated the labels. FYI. Yes, the bot does not re-label every commit (and I think doing that would be a little excessive). |
|
@saimn , how do you feel about |
eerovaher
left a comment
There was a problem hiding this comment.
Setting __tracebackhide__ = True is a good idea if the test helper function is written to produce good output in case of failure (like the numpy.testing functions are) or if it is a thin wrapper around such a function. It looks like in coordinates the only function that should have __tracebackhide__ = True is assert_representation_allclose() in test_representation_arithmetic.py.
c05a670 to
5d8430b
Compare
|
@eerovaher thank you, I've reverted everything else in |
5d8430b to
d1d3496
Compare
|
(squashed) |
d1d3496 to
4e6e1f7
Compare
|
rebased to fix a trivial conflict. I also added a checklist to keep track of reviews, if we absolutely require every package maintainer to approve. |
4e6e1f7 to
aa168f9
Compare
…t helper functions
aa168f9 to
b6e8317
Compare
mhvk
left a comment
There was a problem hiding this comment.
utils.masked and uncertainties are OK; thanks for pushing this forward!
|
I think this is really all fine - and a nice addition - so let's get it in. Thanks, @neutrinoceros! |
Description
Fixes #16071 and replaces #16069
Reviews:
io.misc