Skip to content

Instantly share code, notes, and snippets.

@tasdikrahman
Last active October 31, 2024 10:03
Show Gist options
  • Save tasdikrahman/2bdb3fb31136a3768fac to your computer and use it in GitHub Desktop.
Save tasdikrahman/2bdb3fb31136a3768fac to your computer and use it in GitHub Desktop.
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.

@StianHanssen
Copy link

@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

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

@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?

@stephenhutch
Copy link

Why does this not find any tests with the above:

$ python -m unittest tests

----------------------------------------------------------------------
Ran 0 tests in 0.000s

OK

@samyouaret
Copy link

You need to add __init__.py to the tests directory, If you have other subdirectories in the tests directory you also need to add the __init__.py so python can know that those are modules, not just directories.

then run:

python3 -m unittest discover -p 'test_*.py'

@10cheon00
Copy link

10cheon00 commented Sep 26, 2022

Adding __init__.py into tests/APPS_NAME/ is working! 👍

my test folder structure

root
+-- config
+-- mysite
|   `-- models, views, urls...
`-- tests
    `-- mysite
        +-- __init__.py
        +-- tests_models.py
        `-- other tests...

Thanks @samyouaret

@samyouaret
Copy link

you are welcome @10cheon00 .

@mrdougwright
Copy link

This was so very helpful. Thank you. 🎉

@paulied67
Copy link

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

What if, in this example, app.py contains the following import: import view? I find that the test fails trying to import view.py:

ModuleNotFoundError: No module named 'view'

It's almost as if the directory the test is run in becomes the "current relative" directory and, because app.py is being imported from a test, ie app_test.py, that the imports are expected from the test's location and not the location of the file importing the module.

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