0

I have a folder structure like below

.
├── src
│   ├── __init__.py
│   ├── b.py
│   └── main.py
└── test
    ├── __init__.py
    └── test_main.py

main.py imports a function from b.py which is causing me all sorts of problems.

main.py

from b import sub_m

def add_m(a, b):
    return a + b

def add_sub(a, b):
    return add_m(a, b) + sub_m(a, b)


if __name__ == '__main__':
    print(add_m(5, 5))
    print(add_sub(5,5))

b.py

def sub_m(a, b):
    return a - b

test_main.py

import unittest

from src.main import add_m, add_sub

class TestFile1(unittest.TestCase):
    def test_add_m(self):
        self.assertEqual(add_m(1, 2), 3)
    
    def test_add_sub(self):
        self.assertEqual(add_sub(5, 5), 10)

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

If I run python src/main.py, it works. But when i run the tests by running pytest test I get an error ModuleNotFoundError: No module named 'b'

I searched in StackOverflow and found different ways to get it working like running python -m pytest, python -m pytest test. But everything is giving me the same error.

The only way I could make the test work is by changing the main.py by updating the first line as

from src.b import sub_m

Instead of,

from b import sub_m

This change gets the tests working, but execution of main.py fails with this change python src/main.py fails saying ModuleNotFoundError: No module named 'src'.

What is the best way to get both the test and main.py working? I know this won't be the first time someone is facing this issue. But I tried my best to look for existing answers but nothing worked for me.

Ashok KS
  • 659
  • 5
  • 21
  • 1
    One option is to manually add `src/` to the `sys.path` using `conftest.py` when running tests. That way you dont have to import `from src`. https://stackoverflow.com/questions/70172116/modulenotfounderror-no-module-named/70172229#70172229 – Tzane May 17 '23 at 06:52

1 Answers1

0

When running python, you need to specify in which path(s) it should look for modules. That is done by putting the path(s) in PYTHONPATH environment variable.

If you don't, it assumes you want the paths where the main script is, which is fine, but does not work when running a different every point, like tests. In that case, specify it manually, e.g.

> PYTHONPATH=src pytest test
zvone
  • 18,045
  • 3
  • 49
  • 77
  • I couldn't use this solution because the command which runs pytest is part of the project's Github actions. I cannot modify that since it is at the project level. I added the conftest.py as suggested by @Tzane and added the path. – Ashok KS May 17 '23 at 23:03
  • Github action is exactly the place where this should be configured. If you cannot do it, there is probably someone who could. Modifying sys.path from within the code is a hack which makes it more difficult for others to understand what is going on. – zvone May 18 '23 at 14:51