6

I'm unable to integrate my project's unit tests into VSCode. Test discovery fails because source files are not recognized by pytest.

(Just for clarification, this is a question about VSCode, not about pytest. I'm here because VSCode links its question section to SOF. Tests work fine if I run them manually.)

Tooling: pyenv, pipenv, pytest.

Project layout:

/src -> source code
/tests/unit -> test code

.vscode/settings.json:

{
    "python.envFile": "${workspaceFolder}/.env",
    "python.testing.pytestEnabled": true,
    "python.testing.pytestArgs": [
        "tests"
    ],
    "python.testing.unittestEnabled": false,
    "python.testing.nosetestsEnabled": false
    [...]
}

.env:

PYTHONPATH=./src

(Note: I don't think .env matters here, as per this comment, under Use of the PYTHONPATH variable)

Test discovery fails with:

tests/unit/test_revoke_default_sg.py:7: in <module>
    from revokedefaultsg.app import RevokeDefaultSg, UnknownEventException
E   ModuleNotFoundError: No module named 'revokedefaultsg'
=========================== short test summary info ============================
ERROR tests/unit/test_revoke_default_sg.py
!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
=============================== 1 error in 0.08s ===============================

This is caused by ./src not being part of the python path, so tests cannot import source code.

I can fix this on CLI/makefile level by adding to PYTHONPATH:

PYTHONPATH=./src pytest

This works as expected.

What's the correct setup for VSCode?

Am I supposed to create a launch configuration for testing? I've started to look into this, but couldn't get it to work nicely with pipenv.

Jan Groth
  • 14,039
  • 5
  • 40
  • 55
  • 2
    Several issues coming together here, pytest itself should have a [configuration file](https://docs.pytest.org/en/latest/customize.html#config-file-formats) with `pytest.ini` being the simplest option. Then, there's configuration of the `src` layout, `setup.py` with `package_dir` is [the simplest option](https://stackoverflow.com/questions/14417236). From your description it's a good question if you [activated your venv](https://stackoverflow.com/questions/62498127). Your PYTHONPATH will be relative to OS and/or venv depending how you separated things. Should be mostly independent of the IDE... – bad_coder Aug 12 '20 at 22:44
  • I'm a PyCharm user, I don't know if VSCode comes with testing functionalities builtin. What I just said are the steps to get the tools working on a console/shell independently of IDE integration features. For the IDE I use the standard integration tools that provide a GUI for a part of what I just described (but most of it has to be configured by hand all the same). – bad_coder Aug 12 '20 at 22:50
  • it's been awhile since I've done this, and my layout is different, but what I ended up doing on at least one project is in the .vscode/settings.json file: 1. set the python.pythonPath and 2. set python.testing.pytestEnabled: true (I have other test frameworks disabled). Then, run via `pipenv run python -m pytest src` – Hikash Aug 12 '20 at 22:56
  • This seems very specific to [JSON](https://stackoverflow.com/tags/json/info) and [PYTHONPATH](https://stackoverflow.com/tags/pythonpath/info) you may consider adding those tags. – bad_coder Aug 12 '20 at 23:22
  • I have been using pytest with Visual Code for quite some time. What I usually do is that I put the tests within the src. I would try that first to see if there is something else wrong with the configuration. Then I would try and fiddle around with the user json. – NMech Aug 13 '20 at 04:42

1 Answers1

6

(OP here)

I think the key to integrate into VSCode creating a specific launch configuration for pytest (before, I only had the default launch configuration that's been created with the Python extension).

I now have two configurations (.vscode/launch.json):

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Run Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal",
            "env": {
                "PYTHONPATH": "./src"
            }
        },
        {
            "name": "Python: pytest",
            "type": "python",
            "request": "launch",
            "module": "pytest",
            "cwd": "${workspaceRoot}",
            "env": {
                "PYTHONPATH": "./src"
            },
            "envFile": "${workspaceRoot}/.env",
            "console": "integratedTerminal",
        }
    ]
}

(project on GitHub)

Running this configuration after launching VSCode discovers tests correctly, without raising errors. However, I have not tried it out in different projects yet.

Also, maybe I didn't find the right section of the VSCode documentation, but this feels heavily under-documented. I ended up searching GitHub for gists with launch configs and copied together whatever seemed vaguely helpful...

Jan Groth
  • 14,039
  • 5
  • 40
  • 55
  • Brilliant answer! This is the only way I found I could discover all tests and debug them for flasgger... – Louis Go Nov 09 '21 at 07:57