1

Given the directory structure:

/home/user/python/mypacakge/src/foo.py
/home/user/python/mypacakge/tests
/home/user/python/mypacakge/tests/fixtures
/home/user/python/mypacakge/tests/fixtures/config.json.sample
/home/user/python/mypacakge/tests/foo_tests.py
/home/user/python/mypacakge/README.md

Where src contains the source code, and test contains the unit tests, how do I setup a "package" so that my relative imports that are used in the unit tests located in test/ can load classes in src/?

Similar questions: Python Relative Imports and Packages and Python: relative imports without packages or modules, but the first doesn't really answer my question (or I don't understand it) and the second relies on symlinks to hack it together (respectively).

4
  • You mean simply import a file like this: from .. import src.module ? Any class in module is then loaded.. Commented Mar 8, 2017 at 18:26
  • Can also do from ..src import module.class btw Commented Mar 8, 2017 at 18:27
  • a) it appears to not be a best practice to use relative imports, b) I get this: ValueError: Attempted relative import beyond toplevel package Commented Mar 8, 2017 at 18:36
  • If you set a structure where you try to import from repo_root/test something in repo_root/src, from .. import will work. If you got a warning about a top level package that probably means that's not the structure of your repo. Regardless of that, Python imports packages that are part of the main package stated in setup.py. If you don't install the package, it's not available. I don't see how relative imports in tests are bad practice. Moreover, I don't even know of another way to do that that isn't ugly. Commented Mar 8, 2017 at 18:42

1 Answer 1

1

I figured it out.

You have to have __init__.py in each of the folders like so:

/home/user/python/mypackage/src/__init__.py
/home/user/python/mypackage/src/Foo.py
/home/user/python/mypackage/tests
/home/user/python/mypackage/tests/fixtures
/home/user/python/mypackage/tests/fixtures/config.json.sample
/home/user/python/mypackage/tests/foo_test.py
/home/user/python/mypackage/tests/__init__.py
/home/user/python/mypackage/README.md
/home/user/python/mypackage/__init__.py

This tells python that we have "a package" in each of the directories including the top level directory. So, at this point, I have the following packages:

mypackage
mypackage.test
mypackage.src

So, because python will only go "down into" directories, we have to execute the unit tests from the root of the top-most package, which in this case is:

/home/user/python/mypackage/

So, from here, I can execute python and tell it to execute the unittest module and then specify which tests I want it to perform by specifying the module using the command line options

python -m unittest tests.foo_test.TestFoo

This tells python:

  1. Execute python and load the module unittest
  2. Tell unit test to run the tests contained in the class TestFoo, which is in the file foo_test.py, which is in the test directory.

Python is able to find it because __init__.py in each of these directories promotes them to a package that python and unittest can work with.

Lastly, foo_test.py must contain an import statement like:

from src import Foo

Because we are executing from the top level directory, AND we have packages setup for each of the subdirectories, the src package is available in the namespace, and can be loaded by a test.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.