Imports break VSCode testing with pytest
Asked Answered
G

3

15

I have a project where I want to VS Code's discover tests and other testing features to make testing easier. I have a problem that imports in test files break when I try to discover tests.

I have a file structure like so:

project\
  __init__.py
  package1\
    module1.py
    __init__.py
  tests\
    test.py
    __init__.py

In test.py I have a line:

import project.package1.module1 as module1

I run my project by calling python -m project in the root folder, and I am able to run tests successfully by calling python -m pytest project from the root folder.

When I run VS Code's "discover tests" feature or try to step through a file with the debugger, I receive an error 'ModuleNotFoundError: No module named project'.

Does anyone know how to solve this problem?

Galactopoietic answered 30/7, 2019 at 14:22 Comment(12)
It should work if it works from the debug pane: do you have "name": "Python: Module", configuration set in your launch.json (the gear icon in Debug pane)? Did you set the correct interpreter?Coastguardsman
I do have an entry ``` { "name": "Python: Module", "type": "python", "request": "launch", "module": "enter-your-module-name-here", "console": "integratedTerminal" }, ``` in launch.json and I'm sure the interpreter is correct. I'm using a venv virtual environment.Galactopoietic
Well, that launch.json setup implies that you can't debug/run by pressing F5 key or that green play button. Change that enter-your-module-name-here to project, save the json and you're good to go.Coastguardsman
Did you open the project/ directory in VS Code or the parent directory of project/? P.S.: you can simplify that import statement as from project.package1 import module1.Heracles
Replacing enter-your-module-name-here did not work. I have opened the parent directory of project/ in vscode as this is where the venv and other files live.Galactopoietic
That's exactly what I have set and configured, but also I have __main__.py file next to package's __init__.py with if __name__ == "__main__": in it. When you say you run your program with python -m project, what function is been called that way?Coastguardsman
I also have a __main__.py in and app.py in package`. In __main__.py` is from project import app and if __name__ == "__main__": app.run().Galactopoietic
@Dan At this point you will need to print out sys.path to see where Python is looking for modules to help understand why Python can't find project.Heracles
@BrettCannon The thing is, I can run the project fine with python -m project and I can test fine with python -m pytest project or even python -m pytest project\tests\test.py. When I do python and then import sys, sys.path I get ['', '/usr/lib/python37.zip', '/usr/lib/python3.7', '/usr/lib/python3.7/lib-dynload', '/home/dan/Documents/.../Project/venv/lib/python3.7/site-packages'] where Project is the parent folder of projectGalactopoietic
I think it's to do with the way I am importing. I am using absolute imports and this makes the working stuff work nicely. The thing is I wanted to avoid hacky methods like editing sys.path. I am not a Python expert and the import system is very complicatedGalactopoietic
@Dan and I'm going to assume import os; print(os.getcwd()) print out '/home/dan/Documents/.../Project' for ''. You don't have an __init__.py in Project/ do you? That has been known to mess things up before. We also have a fix for some test discovery in the next release you can test by installing the development build of the extension. Otherwise we are at the point that you will need to open an issue at github.com/microsoft/vscode-python.Heracles
@BrettCannon I indeed get /home/.../Project' from getcwd()` and there is no __init__.py in Project. Thank you for the help.Galactopoietic
T
11

I had the same issue. The solution that worked for me was to introduce a .envfile that holds my PYTHONPATH entries, relative to my workspace folder.

PYTHONPATH="path1:path2:pathN"

Then I added a line to my workspace settings that specifies the location of my .env file.

// ...
"python.envFile": "${workspaceFolder}/.env",
// ...
Toad answered 22/4, 2020 at 13:29 Comment(2)
.env is the default, so you probably don't need to explicitly define it.Friend
This is definitely the solution. python -m pytest works for me on the cmd. I was looking for a solution that didn't involve hacks and did not need to be commited to git. Great answerEndarch
E
4

I had the same issue where I was able to run pytest and python -m pytest successfully in the terminal within VSCode but the discovery was failing. My solution was to implement the failing import in the following way

import sys
sys.path.insert(0, '/full/path/to/package1/')
from package1.module1 import module1

Note that VSCode was opened with the project folder being the root.

Etiology answered 1/11, 2019 at 0:49 Comment(1)
I added these lines in the init.py file of the test folder. This way, the path to the package1 is added to sys.path when the tests are being discovered. Not the best solution but fixed the problem for meRipley
C
1

Next solution works for Linux and Windows,

import sys
from pathlib import Path
sys.path.insert(0, str(Path('package1/').resolve()))

It's based on @Chufolon answer. My StackOverflow reputation doesn't allow me to just comment on his answer. I prefer his solution because in the .env there could be sensitive information (passwords, ...) that shouldn't be shared (omit it in .gitignore file) for security reasons; and also because __init__.py is shared by default through Git.

Camire answered 5/3, 2022 at 14:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.