0
votes

I'm coding my first project in Python and what I found frustrating about Python and PyTest is that it's complicated to make the directory structure and importing modules working.

I have a directory structure like this:

Football
  football
    __init__.py
    file1.py
    file2.py
    file3.py
    main.py
  tests
    context.py
    test_file1.py
    test_file2.py
    test_file3.py

Obviously, the names of the files are different than in the above example.

When I want to import a class File2 from file2.py in file1.py or main.py, then in file1.py or main.py I write:

from file2 import File2

The content of my context.py file is:

import os
import sys

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import football

This is how the content of one of the tests files (for example 'test_file1.py') look like more or less:

from context import football
from football.file1 import File1

And when I run football/main.py, it works.

But when I run pytest, I get the error more or less like that:

football/file1.py:2: in <module>
from file2 import File2
E   ImportError: No module named 'file2'

So it imports correctly the 'file1.py' file but when that file imports 'file2.py' it raises the error that it can't import (although this import works when I run football/main.py without tests).

So how should all those imports be to make it all work and have no errors during tests?

1
Where is your __init__.py?Mike Müller
Sorry, I forgot about __init__.py. It's there, I just forgot to add this in the post. I will edit my post.Damian
Add an empty conftest.py (not "context.py") in Football (project root directory). It will resolve the imports in tests.hoefling

1 Answers

1
votes

You will need to add __init__.py to your Football/football directory for python package discovery. Then, one thing you could do is add a setup.py at your project's root level and within that use find_packages() to recursively find packages to add to the python path. You'll then have to pip install your project into the virtual environment before running your tests. Tools like tox make accomplishing these steps easier by automatically setting up the virtual environment before calling your test commands.

Another option is to use the monkeypatch fixture (a pytest builtin) and modify the PYTHONPATH for your tests. You could put this in your tests/conftest.py. Still you would need to create an __init__.py in your Football/football directory.

@pytest.fixture(autouse=True)  # run this automatically before tests
def pythonpath(monkeypatch):
    path_to_project = "<path to your project root>"
    monkeypatch.setenv('PYTHONPATH', path_to_project)