Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Typical Directory structure for python tests

A Typical directory structure for running tests using unittest

Ref : stackoverflow

The best solution in my opinion is to use the unittest command line interface which will add the directory to the sys.path so you don't have to (done in the TestLoader class).

For example for a directory structure like this:

new_project
├── antigravity.py
└── test_antigravity.py

You can just run:

$ cd new_project
$ python -m unittest test_antigravity

For a directory structure like yours:

new_project
├── antigravity
│   ├── __init__.py         # make it a package
│   └── antigravity.py
└── test
    ├── __init__.py         # also make test a package
    └── test_antigravity.py

And in the test modules inside the test package, you can import the antigravity package and its modules as usual:

# import the package
import antigravity

# import the antigravity module
from antigravity import antigravity

# or an object inside the antigravity module
from antigravity.antigravity import my_object

Running a single test module:

To run a single test module, in this case test_antigravity.py:

$ cd new_project
$ python -m unittest test.test_antigravity

Just reference the test module the same way you import it.

Running a single test case or test method:

Also you can run a single TestCase or a single test method:

$ python -m unittest test.test_antigravity.GravityTestCase
$ python -m unittest test.test_antigravity.GravityTestCase.test_method

Running all tests:

You can also use test discovery which will discover and run all the tests for you, they must be modules or packages named test*.py (can be changed with the -p, --pattern flag):

$ cd new_project
$ python -m unittest discover

This will run all the test*.py modules inside the test package.

@Ayushverma8
Copy link

Ayushverma8 commented Mar 21, 2018

Was struggling for this. Thanks. Saved my Day. 👍

@magarage
Copy link

magarage commented Jun 4, 2018

Thanks. I also received help by this 😄 👍

@KevinMendietaP
Copy link

KevinMendietaP commented Jun 15, 2018

This works also for python3.x ???

@sathiyarajanm
Copy link

sathiyarajanm commented Jun 28, 2018

great Article btw.

@nosahama
Copy link

nosahama commented Oct 24, 2018

It's not generally ideal to have your tests folder named test so as to prevent any clashes with python inbuilt test, you can also name the project tests folder tests.

Also since the folder would be holding/storing multiple tests, hence the plural naming convention.

@eronekogin
Copy link

eronekogin commented Apr 13, 2019

Thank you very much for sharing this best practice, I was struggling in the past three hoursT T

@flow2k
Copy link

flow2k commented Apr 25, 2019

@nosahama Are there documentation/links that also recommend your convention? In Java, for example, the test directory is named test, not tests.

@StianHanssen
Copy link

StianHanssen commented Jun 21, 2019

I don't think this is a proper solution.. Sure it works for running the tests, but how do you import modules in the same directory, then?
If I call python antigravity\some_other_file.py or do cd antigravity and then python some_other_file.py and this file imports using any of the methods mentioned, I get ModuleNotFoundError: No module named 'antigravity'.

The only way I found that I could run that file normally would be to do a normal import: import antigravity...But then the tests can't import modules properly.

@felix-hilden
Copy link

felix-hilden commented Jul 3, 2019

@KevinMendietaP - Yes, this does work for Python 3! At least for my particular 3.6.5.
@flow2k - path/to/python/lib/test contains Python's own tests, which is importable as import test. So to avoid clashes one probably should use some other name for a folder containing tests. Or it might not be a problem for you.

@StianHanssen

I don't think this is a proper solution. -- How do you import modules in the same directory, then?

I think that's not really an issue with this particular approach to test discovery as it is one with imports in general. Some time ago I had the pleasure of receiving a rather comprehensive answer on a question on relative imports I posted on Stack Overflow. Building on that, my current approach is to always use absolute imports. That is, even though a shorter import might exist, I always import all the way from the top within a package. Combined with an install via pip install -e ./ this allows for easy development of a package.

Thanks for the Gist by the way! Useful and very much a proper solution in my opinion.

@StianHanssen
Copy link

StianHanssen commented Jul 5, 2019

@felix-hilden Yes, you are correct, I actually found that I was wrong, but forgot to edit my answer.
If you simply run as module instead of as a script it works perfectly fine for both running test and the program it self. To reference to my example, this way would run the program without any problems (calling command from project directory):
python -m antigravity.some_other_file

I was used to running my programs as scripts and so I didn't really consider simply running them as modules. Might be a nice thing to know for others as well!

@eric-burel
Copy link

eric-burel commented Nov 7, 2019

Edit (question had already been posed):
@StianHanssen your question is very interesting. Is there another alternative to running the code as module?
This feels a bit confusing coming from JS for example where you just import files using realtive path + an index.js...

@StianHanssen
Copy link

StianHanssen commented Nov 8, 2019

@eric-burel
I personally find running code as modules the best alternative because it seems the most consistent :)
Use the import convention shown in this thread and run the program using: python -m antigravity.some_other_file rather than python antigravity\some_other_file.py.
I think a part of the confusion is that your location in the file system when calling the command in terminal affects how things are imported. I always make it a rule to stay in the root directory of the project when running a python file (and run it as a module). That way, it stays consistent and I do not run into troubles with tests and other external modules.

@jpswain
Copy link

jpswain commented Apr 12, 2020

🙏

@clarencedesmarais
Copy link

clarencedesmarais commented Nov 27, 2020

This is great,

Question, do you have an example such that given this directory structure :

image

I want to know how to import src > mypkg > app.py into tests > unit> app_test.py

@kalvelukas
Copy link

kalvelukas commented Nov 30, 2020

@clarencedesmarais : I've got the same problem actually. Could you solve this, or does someone else got a hint for it?

@galak75
Copy link

galak75 commented Jan 8, 2021

@clarencedesmarais, @kalvelukas : you have to configure your setup.py :

setup(
    ...,
    packages=find_packages(where='src'),
    package_dir={
        '': 'src',
    },
    ...
)

Then, you should be able to import mypkg.app

For additional details, take a look at this Stackoverflow question.

@frosk1
Copy link

frosk1 commented Feb 3, 2021

It is really important to mention, that the enduser has to be in the project root directory to perform the unittest method:

cd new_project

refer to this question:
https://stackoverflow.com/questions/49849475/python-unittest-works-from-pycharm-but-not-from-ternimal

@mar-ses
Copy link

mar-ses commented Jul 16, 2021

I've got a follow up question. I named the directory containing the test modules tests as seems to be the convention. However, IPython seems to have its own tests module, which it places into one of the usualy sys.path paths. i.e. for a virtual environment main, created with virtualenv, when I download IPython, the following module clashes:

.../main/lib/python3.6/site-packages/IPython/extensions/tests.py

Since I assume most people install IPython, this sounds incompatible with the convention of calling your testing dir tests. So who is breaking convention here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment