Skip to content

Breakpointing with python unittest #550

Closed

Description

Environment data

  • VS Code version: 1.53.2
  • Extension version (available under the Extensions sidebar): v2021.2.582707922
  • OS and version: MacOS 11.2.1 (Big Sur)
  • Python version (& distribution if applicable, e.g. Anaconda): 3.8.5 (Conda)
  • Type of virtual environment used (N/A | venv | virtualenv | conda | ...): N/A
  • Value of the python.languageServer setting: Pylance

Expected behaviour

I am running some tests using python's unittest. When an exception is raised, I'd like VS Code to breakpoint at the point the error is thrown. I have "Uncaught Exceptions" enabled and "Raised Exceptions" disabled, and I see the desired behaviour when running the code normally (not with unittest). In the minimum working example below, I'd like the code to breakpoint at line 4 when the exception is raised.

Actual behaviour

Instead of the desried/expected behaviour, the breakpoint is on the final line with an empty stack call and no way of getting back to line 4 or the variables present at that time. This makes debugging useless. I imagine this occurs because unittest catches all uncaught exceptions, so I'd like a way for VSCode to breakpoint if the except was not written by the user (as is the case with unittest). I've seen a suggested solution here (microsoft/vscode-python#14056 (comment)) and also thought that setting justMyCode might help, too, but neither did.

Caveat 1: I know I could enable "Raised Exceptions" but the code I'm working on has lots of intentional raises which are caught. So enabling "Raised Exceptions" would take too long to sift through all the intentional raises.

Caveat 2: I know there is the "Test" tab. When I click to debug the test it says "No Tests Ran". This is strange because I simply run the test from inside the "Test" tab, it successfully runs (it still raises the error, and there is no breakpointing, but it runs at least).

Steps to reproduce:

In the example below, I'd like the breakpoint at line 4 (raise RuntimeError()), but I'm getting it instead at line 11 (unittest.main()), which has an empty stack call and no way to get back to line 4 or any of the variables that were present at that time.

import unittest

def something():
    raise RuntimeError()

class TestClass(unittest.TestCase):
    def test_method(self):
        something()

if __name__ == "__main__":
    unittest.main()

Activity

  1. int19h commented on Feb 22, 2021

    @int19h
    Contributor

    To clarify - did you try locally patching your debugpy to enable user-unhandled exceptions, but it still didn't work as expected when you enabled the corresponding filter in UI?

  2. rijobro commented on Feb 22, 2021

    @rijobro
    Author

    Sorry that wasn't clear. I followed the advice given in the linked comment, but found that my settings already matched the suggested changes:

    {"filter": "userUnhandled", "label": "User Uncaught Exceptions", "default": True},
  3. int19h commented on Feb 22, 2021

    @int19h
    Contributor

    The code in question was changed slightly since that comment was written: it's now conditional on environment variable DEBUGPY_EXCEPTION_FILTER_USER_UNHANDLED, which must be set to 1.

    If you have enabled it successfully, the exception filter should show up "User Uncaught" in addition to "Uncaught" and "Raised". Are you seeing it?

  4. rijobro commented on Feb 23, 2021

    @rijobro
    Author

    As in, in my .bashrc I put:

    export DEBUGPY_EXCEPTION_FILTER_USER_UNHANDLED=1

    and then restart VSCode?

  5. int19h commented on Feb 23, 2021

    @int19h
    Contributor

    That should work, although I'd check it manually in the terminal first (i.e. export in some shell, then launch VSCode from that same shell).

  6. rijobro commented on Feb 25, 2021

    @rijobro
    Author

    I've tried a few combinations including:

    • export DEBUGPY_EXCEPTION_FILTER_USER_UNHANDLED=1 && /Applications/Visual\ Studio\ Code.app/Contents/MacOS/Electron
    • export DEBUGPY_EXCEPTION_FILTER_USER_UNHANDLED=1 && code
    • add export DEBUGPY_EXCEPTION_FILTER_USER_UNHANDLED=1 to ~/.zprofile and then launch from icon

    Unfortunately none give me the extra breakpoint button. Any further ideas?

  7. rijobro commented on Feb 25, 2021

    @rijobro
    Author

    I even hardcoded clients.py to be:

            exception_breakpoint_filters = [
                {"filter": "raised", "label": "Raised Exceptions", "default": False},
                {"filter": "uncaught", "label": "Uncaught Exceptions", "default": True},
            ]
            exception_breakpoint_filters += [
                {
                    "filter": "userUnhandled",
                    "label": "User Uncaught Exceptions",
                    "default": True,
                },
            ]
            # if int(os.getenv("DEBUGPY_EXCEPTION_FILTER_USER_UNHANDLED", "0")) != 0:

    But this still didn't add the button.

  8. fabioz commented on Feb 25, 2021

    @fabioz
    Collaborator

    It seemed to work for me (maybe you're editing a clients.py but also have debugpy installed elsewhere and it is picking a different version?)...

    As a note, after changing the environment variable, you need to run it once for the button to appear (as the VSCode UI will be updated based on what the debugger gives at runtime).

    i.e.: it should show:

    image

    After that, you need to enable it.

    If you still can't get it to work, please provide the logging (maybe it can give some hint on what's not correct).

    i.e.:

    • Open VS Code
    • Select the command Extensions: Open Extensions Folder
    • Locate the Python extension directory, typically of the form ms-python.python-2020..***
    • In that directory ensure you do not have any debug*.log files, if you do, please delete them
    • Go back into VS Code and modify your launch.json to add the setting "logToFile": true, see below:
    {
        "name": "Python: Current File (Integrated Terminal)",
        "type": "python",
        "request": "launch",
        "program": "${file}",
        "console": "integratedTerminal",
        "logToFile": true
    }
    
    • Start debugging
    • When done, go back into the extension directory and upload the debug*.log files into this GitHub issue.
  9. rijobro commented on Feb 25, 2021

    @rijobro
    Author

    The trick I was missing was to run it once to get it to refresh! Thanks!

  10. fabioz commented on Feb 25, 2021

    @fabioz
    Collaborator

    Great that it's working now ;)

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

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions