0

Previously I was working without unittests and I had this structure for my project:

-main.py
   -folderFunctions:
       -functionA.py

Just using init file in folderFunctions, and importing

 from folderFunctions import functionA

everything was working good.

Now I have also unittests wihch I organized in this way:

-main.py
-folderFunctions:
    -functionA.py
    -folderTest:
       -testFunctionA.py

So I had to add (in order to run testFunctionA.py) in both functionA.py and testFunctionA.py these 2 lines to import the path:

 myPath = os.path.dirname(os.path.abspath(__file__))
 sys.path.insert(0, myPath + '../..') 

In this way the test works properly. But it is ugly to me and I guess also not very pythonic. Is there a way to make it more elegant?

Joe
  • 12,057
  • 5
  • 39
  • 55
  • Create a folder called `tests` on the same level where `main.py` is and put all your tests in there. – orangeInk Aug 11 '17 at 06:59
  • @orangelnk I read that usually the testfolder is at the same level of the functions one or on a deeper lever. Is on main level still pythonic? – Joe Aug 11 '17 at 07:02
  • I have to admit that I'm far from an expert when it comes to packaging but 99% of the time when I look at a package I see a `tests` folder at the same level where `setup.py` is located (meaning 1 level above all of the actual code). – orangeInk Aug 11 '17 at 07:08

2 Answers2

1

If you want your library/application to become bigger and easy to package I hardly recommend to separate source code from test code, because test code shouldn't be packaged in binary distributions (egg or wheel).

You can follow this tree structure:

+-- src/
|    +-- main.py
|    \-- folder_functions/  # <- Python package
|        +-- __init__.py
|        \-- function_a.py
\-- tests/
    \-- folder_functions/
        +-- __init__.py
        \-- test_function_a.py

Note: according to the PEP8, Python packages and modules names should be in "snake case" (lowercase + underscore).

The src directory could be avoided if you have (and you should) a main package.

As explained in other comments, the setup.py file should stand next to the src and tests folders (root level).

Read the Python Packaging User Guide

edit

The next step is to create a setup.py, for instance:

from setuptools import find_packages
from setuptools import setup

setup(
    name='Your-App',
    version='0.1.0',
    author='Your Name',
    author_email='your@email',
    url='URL of your project home page',
    description="one line description",
    long_description='long description ',
    classifiers=[
        'Development Status :: 4 - Beta',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: Python Software Foundation License',
        'Operating System :: MacOS :: MacOS X',
        'Operating System :: Microsoft :: Windows',
        'Operating System :: POSIX',
        'Programming Language :: Python',
        'Topic :: Software Development',
    ],
    platforms=["Linux", "Windows", "OS X"],
    license="MIT License",
    keywords="keywords",
    packages=find_packages("src"),
    package_dir={'': 'src'},
    entry_points={
        'console_scripts': [
            'cmd_name = main:main',
        ],
    })

Once your project is configured, you can create a virtualenv and install your application inside:

virtualenv your-app
source your-app/bin/activate
pip install -e .

You can run your tests with unitests standard module.

To import your module in your test_function_a.py, just proceed as usual:

from folder_functions import function_a
Laurent LAPORTE
  • 21,958
  • 6
  • 58
  • 103
  • Thanks for the help! so with this tree structure, how could I import in test_function_a.py function_a.py? – Joe Aug 11 '17 at 08:33
0

The more elegant way is from folderFunctions.folderTest import testFunctionA and make sure that you have an __init__.py file in the folderTest directory. You may also look at this question

otayeby
  • 312
  • 8
  • 17