How do I debug individual Django tests in vscode?

Viewed 5508

I added a launch configuration that allows me to run all tests in Django and another that allows me to run the server, both of these work fine.

I am looking for a way to debug an individual file, but using ${file} in the arguments gives a normal path which django doesn't like.

I want a way to change ${file} into a python path so that I can debug my tests on a single file.

python manage.py test --noinput --keepdb python.path.to.my.file

works in the command line.

The following configuration seems to be almost right:

      {   "name": "Test File",
            "type": "python",
            "request": "launch",
            "program": "${workspaceFolder}/manage.py",
            "args": [
                "test",
                "--noinput",
                "--keepdb",
                "${file}"
            ],
            "django": true
        }

However, when I run this configuration I get an error, which I think is because ${file} turns into

path/to/my/file instead of path.to.my.file.

5 Answers

If you're on a Mac or Linux, the following launch config should work for a single unit test executed by Django:

    {
        "name": "Python: Django Debug Single Test",
        "type": "python",
        "request": "launch",
        "program": "${workspaceFolder}/manage.py",
        "args": [
            "test",
            "`echo -n ${relativeFileDirname} | tr \/ .`.${fileBasenameNoExtension}"
        ],
        "django": true
    },

This uses the tr command to translate / into . in the relative path.

If you're using Windows and the git bash, the launch config with tr will also work, but you'll need to quote the variable substitution and quote the double backslashes.

    {
        "name": "Python: Django Debug Single Test",
        "type": "python",
        "request": "launch",
        "program": "${workspaceFolder}/manage.py",
        "args": [
            "test",
            "`echo -n \"${relativeFileDirname}\" | tr \\\\ .`.${fileBasenameNoExtension}"
        ],
        "django": true
    },

There is no translation of file path to dotted name, so you will need to hard-code that in your launch.json.

this works for me in windows under wsl ubuntu with your tests.py as the open file :

{
    "name": "Test Django",
    "type": "python",
    "request": "launch",
    "python": "${workspaceFolder}/../.venv/bin/python",
    "program": "${workspaceFolder}/manage.py",
    "args": [
        "test",
        "${relativeFileDirname}"
    ],
        "django": true
},

I don't think you need any echo | tr ... fileBasenameNoExtension etc.

With newer versions of vscode, as mentioned in one of the comments, vscode stopped evaluating the command that is used to send into the args (`echo...`).

As a different workaround for now, I used the following, which was a bit easier for me because of how I use manage.py.

My configuration looks like this:

    {
        "name": "Python: Django Debug Single Test",
        "type": "python",
        "request": "launch",
        "program": "${workspaceFolder}/manage.py",
        "args": [
            "dtf",
            "${relativeFile}"
        ],
        "django": true
    },

Then, in my case, I added some shortcuts to my manage.py to do things like "manage.py run" (instead of runserver), or "manage.py tap" (instead of --test --parallel 3 --keepdb --settings=settings_tests), etc. So I added another shortcut called "dtf" (debug test file) which then takes the relative file and replacing the value in the argv before actually running the command. It looks like this:

if 'dtf' in sys.argv:
    logging.disable(logging.CRITICAL)

    sys.argv.remove('dtf')
    sys.argv.insert(1, 'test')
    f = sys.argv[2].replace('.py', '')
    f = '.'.join(f.split('/')[1:])
    sys.argv[2] = f

    sys.argv.append('--keepdb')
    sys.argv.append('--settings=my_project.settings_tests')
    print(sys.argv)

You can look at some of the shortcuts I use in my manage.py file here: https://gist.github.com/kalsky/0cba3618452238f3b00354a90d2a51e5

Related