2

I'm new to python and trying to get a unittest working, but the imports in the test files don't work. Folder structure:

toyProjects
└── pythonProj
    ├── mainpack
    │   ├── __init__.py         
    │   ├── MyClass.py  
    │   └── setup.py
    └── tests
        ├── __init__.py        
        └── test_MyClass.py

MyClass.py:

class MyClass:
    def __init__(self, x):
        self.x = x

    def someMethod(self):
        print("Called MyClass.someMethod");

setup.py:

def myFunction():
    print("Called setup.myFunction");

test_MyClass.py:

import unittest

import setup
from MyClass import MyClass

class TestMyClass(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.my = MyClass(4);

    def test_something(self):
        self.my.someMethod();
        setup.myFunction();    

Incase it matters: there is a mainfile.py in pythonProj (not shown in the diagram above cause I assume it's not relevant) which runs fine and finds all the files. Its contents are:

from mainpack import setup
from mainpack.MyClass import MyClass

print("Program start");

setup.myFunction()

myInst = MyClass(4);
myInst.someMethod();

I run the test with

cd toyProjects\pythonProj\tests
python -m unittest test_MyClass.py

I tried pretty much all the solutions from here. And this page says "Many resources on the web will have you fiddling with your sys.path but in most cases, this is a code smell that indicates you are not properly using modules and/or packages.", so hopefully I can learn the proper way to do it (but I'll use sys.path if there's no other solution. Only so far, all the versions I've tried of that haven't worked either.)

More specifically, different types of imports I tried in the test_MyClass file:

import setup                               -->ModuleNotFoundError: No module named 'setup'
from MyClass import MyClass                -->ModuleNotFoundError: No module named 'MyClass'
from mainpack import setup                 -->ModuleNotFoundError: No module named 'mainpack'
from ..mainpack import setup               -->Unresolved reference mainpack
import mainpack                            -->ModuleNotFoundError: No module named 'mainpack'
from mainpack.setup import someFunction    -->Unresolved reference mainpack
from .. import mainpack                    -->ImportError: attempted relative import with no known parent package
MJL
  • 352
  • 3
  • 11
  • Put an empty `__init__.py` in `pythonProj`, then things like `from ..mainpack import setup` and `from .. import mainpack` *should* work. – MattDMo Jan 22 '23 at 20:26
  • @MattDMo : Didn't work. Both still give "ImportError: attempted relative import with no known parent package" – MJL Jan 23 '23 at 20:46

1 Answers1

4

For a package to be importable, it has to be located in one of the directories specified by your PATH environment variable. Since you don't have the pythonProj directory in your PATH, you can instead run the script from that directory because python automatically adds the current working directory to PATH when running a script.

Because the setup and MyClass modules are not reachable from PATH, they cannot be imported using implicit relative imports. Instead, you can use absolute imports in test_MyClass.py:
import setup -> from mainpack import setup
from MyClass import MyClass -> from mainpack.MyClass import MyClass

Then you can run your tests:

cd toyProjects/pythonProj
python -m unittest tests/test_MyClass.py
Fractalism
  • 1,231
  • 3
  • 12
  • Awesome, that worked, thanks! Is this the common practice though, for people who have lots of projects? – MJL Jan 23 '23 at 20:49
  • I can't say if it's common or not, but this should be easier than having to tweak PATH for every project. – Fractalism Jan 23 '23 at 21:02