2

I am trying to set up a workspace in VS Code and I want to be able to run it in venv.

root
- app
-/- modules
-/-/- __init__.py
-/-/- myModule.py
-/-/- myModule2.py
-/- __init__.py
-/- myApp.py
- test
-/- myTest.py
- venv

myApp.py

import random
import numpy as np

import modules.myModule as mm

x = mm.main()

myModule.py

from app.modules import myModule2

def main():
    x = myModule2()
    return x

myTest.py

import unittest
from app.modules.myModule import main

class Test_Foo(unittest.TestCase):
    def test_bar(self):
        x = main()
        assertEqual(x, 'foobar', 'not equal')


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

The issue I'm having is that my own modules can either be run in debug or in test (as unit test) but the same set up can not run for both. When I have from app.modules import myModule2 I can run test but not debug and when I have from modules import myModule2 I can run debug but not test.

my launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal"
        }
    ]
}

my setting.json

{
    "python.testing.unittestArgs": [
        "-v",
        "-s",
        "./test",
        "-p",
        "*test.py"
    ],
    "python.testing.pytestEnabled": false,
    "python.testing.unittestEnabled": true,
    "python.analysis.extraPaths": [
        "./app"
    ]
}

How do I set up my workspace to be able to run both?

I run debug on the file myApp.py, and I run the test from test explorer.

The error I get when running debug is:

Exception has occurred: ModuleNotFoundError
No module named 'app'

The exception is caught in the file myModule.py in line from app.modules import myModule2.

aaron
  • 39,695
  • 6
  • 46
  • 102
AtesTen
  • 59
  • 1
  • 12

2 Answers2

2

The problem with running the test by executing python test/myTest.py is, that the app folder is not on the python path. The unittest module, if launched via its CLI takes care of this automatically if the folder structure is setup accordingly. Detailed information can be found in this post

Long story short:

  1. Add an empty __init__.py file to your /test folder
  2. Run python -m unittest test/myTest.py

To run all tests that are contained in multiple files named test/*test.py, use the discover option of the unittest package with matching arguments:

python -m unittest discover -s "test/" -p "*test.py"

I set up a VSC project matching the files you described, added the file test/__init__.py and created a virtual environment python venv.

The above option of running tests, I can achieve by adding following configurations to the launch.json file:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: run single test",
            "type": "python",
            "request": "launch",
            "module": "unittest",
            "args": [
                "test/my_test.py"
            ]
        },
        {
            "name": "Python: run all tests",
            "type": "python",
            "request": "launch",
            "module": "unittest",
            "args": [
                "discover",
                "-s",
                "./test",
                "-p",
                "*test.py"
            ]
        }
    ]
}

which worked with debug enabled. I didn't create a setting.json file, so the python.unittest settings were set to default values.

Jonathan Weine
  • 655
  • 3
  • 11
0

Change "program": "${file}" to "module": "app.myApp".

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
//          "program": "${file}",  // Change this
            "module": "app.myApp", // to this
            "console": "integratedTerminal"
        }
    ]
}

Basically, the difference is that:

  • With "program", Python adds the final directory in ${file} (i.e. /path/to/root/app/) to sys.path (so you can only import modules).
  • With "module" or -m, Python adds the current directory (i.e. /path/to/root/) to sys.path (so you can import app) and imports the containing package of app.myApp (i.e. app).

For detailed comparisons, see What is the purpose of the -m switch? (Ctrl+F "Detailed Comparisons").

References:

aaron
  • 39,695
  • 6
  • 46
  • 102