'Python unittest directory: correct way to setup unit-test only dependencies?

I have a python package with the following directory structure:

ProjectName
  > setup.py
  > README.txt
  > PackageName
     >> ...<various .py files>...
  > tests
     >> settings
        >>> __init__.py
        >>> unit_test_utils1.py
        >>> unit_test_utils2.py
     >> __init__.py
     >> test1.py
     >> test2.py

I have some utility functions inside settings/unit_test_utils*.py only useful for setting up environment in my unit tests. What is the correct way to structure my project / imports so that these functions are useable in my unit test?

Inside test1.py I have the following:

import unittest

import sys
sys.path.append("..")
import PackageName

## option 1
from .settings import unit_test_utils1
from .settings import unit_test_utils2

## option 2
from settings import unit_test_utils1
from settings import unit_test_utils2


## is there a better way to handle this?

I use sys.path.append("..") which is kind of a hacky way for my unit tests to import PackageName and then I have two different options for importing the utilities into my tests.

If I opt for option 1, if my current directory is ProjectName/ I can run my unit tests using python -m unittest tests.test1 but if my working directory is ProjectName/tests then doing python -m unittest test1 will give me a ImportError: attempted relative import with no known parent package

Similarly if I opt for option 2, if my current directory is ProjectName/test then running python -m unittest test1 works fine but if my current directory is ProjectName/ using python -m unittest tests.test1 will give an error ModuleNotFoundError: No module named 'settings'.

What's a better way to setup my directory and import structure to allow importing helper utilities into my unit tests? Having unit tests error out because of running them from a different directory seems like a bad solution overall and I'm already using other hacks to be able to import the package.



Solution 1:[1]

One way and the way I would use:

  • remove the sys.path.append line.
  • Keep your cwd as ~/ProjectName/
  • change the imports in test1.py to:
import unittest
import PackageName
from tests.settings import unit_test_utils1
from tests.settings import unit_test_utils2

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1