Levino
Levino

Reputation: 103

"ModuleNotFoundError: No module named ..." when trying to make unit tests in Python

Problem

I am trying to make unit tests for my project, but I am having issues figuring out where my error is in regards to absolute importing the module to test. I am using Visual Studio Code as my IDE.

My directories look like this:

project_folder
+ code_files
- reader.py
- __init__.py
+ tests
- test_reader.py
- data.txt
- __init__.py

My "test_reader.py" file looks like this:

import unittest
from code_files.reader import Reader
                                      
class Test_LineCounter(unittest.TestCase):
   def test_empty_file_long(self):
      self.assertEqual(Reader.line_counter(self, "data.txt"), 4)
                                            
if __name__ == "__main__":
   unittest.main()

However, I keep getting the error:

ModuleNotFoundError: No module named 'code_files'

Attempted Solutions

To be completely honest, when I was going into this project I was not very strong working with directories, packages, or modules. I have read many articles online and have read many forum posts on Stack Overflow and other websites trying to figure out what may be causing this error and how I can resolve it. Through this, I feel like I have gained a pretty good understanding of how Python handles packages and modules. Yet I still can't seem to get this problem figured out.

I have tried putting the "code_files" package into a different directory to see if that would work:

project_folder
+ app
+ code_files
- reader.py
- __init__.py

And then imported by:

from app.code_files.reader import Reader

But then I got the error:

ModuleNotFoundError: No module named 'app'

The only time I managed to get "test_reader" to work was when I had my directory structed as follows:

project_folder
+ code_files
- reader.py
- __init__.py
+ test_reader.py
+ data.txt
+ __init__.py

Final Comments

Any help would be greatly appreciated! I feel like there is a very simple solution to this that I just keep overlooking. I know very similar questions have been asked on here before, but all of the determined solutions I have seen are what I have already tried or am currently doing. So I apologize if this is a repetitive question. Thanks!

Upvotes: 10

Views: 14451

Answers (2)

Steven-MSFT
Steven-MSFT

Reputation: 8431

Reason:

This is because the folder of project_folder was not in the sys.path.

A list of strings that specifies the search path for modules. Initialized from the environment variable PYTHONPATH, plus an installation-dependent default.

As initialized upon program startup, the first item of this list, path[0], is the directory containing the script that was used to invoke the Python interpreter.

This can explain the problem you have met.

When the test_reader.py is under the tests folder, tests folder will be added to the sys.path. When the test_reader.py is under the project_folder folder, project_folder folder will be added to the sys.path. Then the python interpreter can find the code_files package.

Solution:

How do you run the test? If you run the test through the Test Panel you will not run across the module problem:

enter image description here

And it will automatically add the workspace folder to the sys.path. So, it's recommended to run the test in this way.

tips:

If you want to get the sys.path, you can add the pprint(sys.path) after the self.assertEqual(Reader.line_counter(self, "data.txt"), 4). But you can only get the result in the channel of Python Test Log in the OUTPUT panel.

If you debug(F5) the test, you can add this in the launch.json file:

"env": {"PYTHONPATH":"${workspaceFolder}"},

If you run the test with the command in ter terminal. You should modify the sys.path in the test file:

sys.path.append("the path to the project_folder folder")

Upvotes: 8

stapmoshun
stapmoshun

Reputation: 134

You must add this to the beginning of test_reader.py

# test_reader.py
import sys
sys.path.append('/.../project_folder/code_files')
import reader

Replace the ... with the concrete path, so if it is in Desktop on Windows then it would be 'C:/Users/USERNAME/Desktop/project_folder' and so on...

Here is a link to further information

Upvotes: -2

Related Questions