Skip to content

TST: should we adopt __tracebackhide__=True in assert_* test helper functions ? #16071

Closed

Description

@neutrinoceros

numpy.testing.assert_* functions set __traceback__ = True, which changes pytest's behavior so that the internals of these functions is not shown in errors. This is particularly useful when invoking pytest with --pdb, which opens a debugger when (and where) an exception is raised: because the internals of assert_* functions are excluded from the traceback, the location associated with the error is that of the callsite, which is usually the body of a test function.
Let me illustrate what I mean with a simplified example

# 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)

run with pytest --pdb t.py and see where the debugger is opened: test_v1 will open in within assert_equal_v1's body, while test_v2 opens it in its own body, which is arguably more useful since we can inspect the whole local scope, instead of just the couple variables that were passed (under different names !) to a test helper.

I propose leveraging this mechanism in all assert_* helper functions (none of which are public API as they live in test code). Any counter arguments ?

Activity

  1. neutrinoceros commented on Feb 19, 2024

    @neutrinoceros
    ContributorAuthor

    I forgot to mention that pytest also has a flag to ignore these markers when needed: --full-trace

  2. pllim commented on Feb 19, 2024

    @pllim
    Member

    That would touch a lot of code. I am not sure if the cost outweighs the benefit here. Over 10 years without this and we still managed to debug.

  3. eerovaher commented on Feb 20, 2024

    @eerovaher
    Member

    Just adding one line to some of our test helper functions would provide a lot of useful functionality, and not just to us but to everybody that might be using those functions in their development work. I don't know what the remark about touching a lot of code in #16071 (comment) is referring to.

  4. pllim commented on Feb 20, 2024

    @pllim
    Member

    I don't know what the remark about touching a lot of code

    Maybe I am not completely understanding the ask. I thought you want to insert that line wherever there is a bare assert check.

    xref #16069 (comment)

  5. eerovaher commented on Feb 20, 2024

    @eerovaher
    Member

    We would only modify test helper functions like #16069 edited astropy.tests.helper.assert_quantity_allclose(). There's no need to touch any of the tests (i.e. test_*()).

  6. neutrinoceros commented on Feb 20, 2024

    @neutrinoceros
    ContributorAuthor

    Indeed, I'm only proposing to add this line to every function named assert_<something>, which according to this simple command would require only 34 lines.

    $ git grep "def assert_" | wc
          34     135    3049

    (but the whole idea is to make their call site behave as bare assert statements do in pytest !)

  7. pllim commented on Feb 20, 2024

    @pllim
    Member

    If it is only 34 lines, then doesn't hurt to just open a PR and see. Then, I don't understand about the comment in #16069 (comment) that said this would touch too many lines.

  8. neutrinoceros commented on Feb 20, 2024

    @neutrinoceros
    ContributorAuthor

    It's just that I naively opened my PR thinking there would only be one function to touch, so >10 seemed like "much" in comparison 😅

    I'll open a new one with the +34 patch !

  9. neutrinoceros commented on Feb 20, 2024

    @neutrinoceros
    ContributorAuthor

    While doing this I found there actually is a precedent for using this !

    __tracebackhide__ = True

    from #10373

  10. mhvk commented on Feb 20, 2024

    @mhvk
    Contributor

    Yes, a very good idea! I am always annoyed that in the debugger I first have to go up a few steps before getting to the point where I can see what actually went wrong.

  11. jdavies-st commented on Mar 13, 2024

    @jdavies-st
    Contributor

    This is a very good idea. We already do this over in jwst for all our diff and assertion helpers. It filters out the garbage internals of the assertion helper and gives you the real traceback of what is failing in the test. This gets a big 👍 from me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions