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
$ # Also works without discover for Python 3
$ # as suggested by @Burrito in the comments
$ python -m unittest

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

Here you can find the updated official documentation of discovery.

Answer from Pierre on Stack Overflow
Top answer
1 of 16
949

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
$ # Also works without discover for Python 3
$ # as suggested by @Burrito in the comments
$ python -m unittest

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

Here you can find the updated official documentation of discovery.

2 of 16
76

I've had the same problem for a long time. What I recently chose is the following directory structure:

project_path
β”œβ”€β”€ Makefile
β”œβ”€β”€ src
β”‚   β”œβ”€β”€ script_1.py
β”‚   β”œβ”€β”€ script_2.py
β”‚   └── script_3.py
└── tests
    β”œβ”€β”€ __init__.py
    β”œβ”€β”€ test_script_1.py
    β”œβ”€β”€ test_script_2.py
    └── test_script_3.py

and in the __init__.py script of the test folder, I write the following:

import os
import sys
PROJECT_PATH = os.getcwd()
SOURCE_PATH = os.path.join(
    PROJECT_PATH,"src"
)
sys.path.append(SOURCE_PATH)

Super important for sharing the project is the Makefile, because it enforces running the scripts properly. Here is the command that I put in the Makefile:

run_tests:
    python -m unittest discover .

The Makefile is important not just because of the command it runs but also because of where it runs it from. If you would cd in tests and do python -m unittest discover ., it wouldn't work because the init script in unit_tests calls os.getcwd(), which would then point to the incorrect absolute path (that would be appended to sys.path and you would be missing your source folder). The scripts would run since discover finds all the tests, but they wouldn't run properly. So the Makefile is there to avoid having to remember this issue.

I really like this approach because I don't have to touch my src folder, my unit tests or my environment variables and everything runs smoothly.

🌐
GitHub
gist.github.com β€Ί tasdikrahman β€Ί 2bdb3fb31136a3768fac
Typical Directory structure for python tests Β· GitHub
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.
Discussions

Arguments against separating `test` from `src` in a python package?
I'm more familiar with Node rather than Python but I separate my test directory from my source directory because I can easily exclude the test directory when publishing the package. So when it is used in another project it has a smaller footprint. It just makes more sense if you are going to exclude it, leave it out of the src directory. If I had to guess, that is why Python recommends it. If I'm wrong I'd love to know why. Hope this helps! More on reddit.com
🌐 r/Python
67
174
March 23, 2023
How to structure a very simply Python project with pytest tests
my_project/ β”œβ”€β”€ .vscode/ β”‚ └── settings.json β”œβ”€β”€ src/ β”‚ └── main.py β”œβ”€β”€ tests/ β”‚ └── test_utils.py └── utils/ └── utils.py Whether or not IDE/editor-specific files should be included in version control (e.g. Git) is a somewhat hot topic, and I know your question had nothing to do with that, but I just thought I'd mention that in most cases it's best to .gitignore them. I'll get back to this specific case later. If following a flat project structure, src should be a package and named after the project. If not, src should only contain packages (usually only one), and you should have a pyproject.toml file in the repository root containing the necessary metadata and possibly other configuration options. By using packages you simplify your imports and paths a lot, making your code far easier to test. main.py is the script to be run with imports from the utils file/module utils should not be in the repository root if it relies on other code in the project. Similarly, main.py shouldn't depend on anything higher up the directory tree. For self-contained scripts (for example, something used to simplify build processes in CI pipelines) the convention I've used is a scripts directory with independent script files. Side note; utils is a fairly generic name, and often there's a better way to structure your program where you wouldn't need that. settings.json contains: { "python.testing.pytestArgs": [ "tests" ], "python.testing.unittestEnabled": false, "python.testing.pytestEnabled": true } Instead of configuring pytest in an IDE-specific file, I'd very much recommend doing at least most of it in pyproject.toml or pytest's own configuration file, as then it'd behave the same no matter how you run it. For example, in this case I'd move at least the test file location to them. If you need an example, you could consider this: https://github.com/Diapolo10/python-ms More on reddit.com
🌐 r/learnpython
18
1
May 24, 2026
How to structure a Python project to work with py.test?
This question is best in r/learnpython Pytest specifically For pytest specifically, you should update your pytest.ini file and/or setup.cfg at the top of your repo and simply run py.test within your python virtual environment at the top of the repo. Hopefully you're using virtualenv or (better) vex. Ideally, you've also setup tox and potentially detox (ues a tox.ini or setup.cfg) so you can do more CI-like matrix testing against multiple environments. Tox also lets you build out environments for other things (like documentation). py.test (and tox or detox) will find your test files matched against test_* by default regardless of where the test files live. So you can structure your package with a top level tests folder or not -- whatever makes the most sense to you (and hopefully to whomever uses your code). By adding a __init__.py (not recommended) to your tests folder, it will get pulled into your package when its built. And in that scenario you can run tests on your target environment with a -m option, but I suspect you should really only run tests on your dev and qa environments (if you have both of those) and explicitly use pytest or tox. Command-lines generally I have two answers. I'm not sure which one you're actually looking for. Setup the script properly with a shebang. Add a console script to your setup.py First answer You might be looking to add this at the top of your file: #!/usr/bin/env python That will tell your bash shell to look for the default python in your environment and run it. Within a script, you'll want to add a few things, though: # !/usr/bin/env python # -*- coding: utf-8 -*- # file: hello.py def hello(): print('Hello!') if __name__ == '__main__': hello() This will tell the script to run hello only if it's in the 'main' environment within python...which is what the top level environment is when you start up the interpreter. You can check that with: $ python >>> print(__name__) __main__ Anything that falls under that __name__ == '__main__' line will only be executed from a top level python interpreter. The line will not be run during an import. Second answer The other option you may be looking for is a __main__.py and then adding a console script like so: entry_points = { 'console_scripts': [ 'command_line_name=package.__main__:function' ], } so if you did something like this: # file: hello_package/__main__.py def hello(): print('Hello!') and # file: setup.py from setuptools import setup ... setup( ... entry_points = { 'console_scripts': [ 'hello=hello_package.__main__:hello' ], } ... ) You could then run from your standard linux command-line: $ hello Hello! Command-line parsers Also, you'll want to think about how you write your command-line parser. Python comes with argparse but it's terribly obsolete at this point. Some later versions have integrated optparse, but while it's a better library than argparse the interface still leaves much room for improvement. Your best bet is to look at docopt and click. They're not really intended to be used together. The former provides a great way of specifying all of your command-line options at the top of your file within a docstring for that module. This makes it extremely easy to find the options for anyone looking at it later. And since you're using the docstring in the actual execution of the code, that also means that it will be kept up-to-date. click is the other option and provides a great decorator system. It's also modular enough that it can be used to produce more complex command-lines than docopt. But it's harder to know what the options are for the command-line at first glance, so learning/maintenance can be more difficult. I recommend this for smaller command-lines or command-lines that require multiple layers of commands (e.g. git). More on reddit.com
🌐 r/Python
9
2
August 16, 2016
Typical folder structure for a python project with unit and integration tests? - Stack Overflow
Similar to what you have shown, the typical python project structure is as follows. β”œβ”€β”€ app_name β”‚ β”œβ”€β”€ app_name β”‚ β”œβ”€β”€ __init__.py β”‚ β”œβ”€β”€ folder_name β”‚ └── etc... β”œβ”€β”€ tests β”‚ β”œβ”€β”€ unit β”‚ └── integration β”œβ”€β”€ README.md β”œβ”€β”€ setup.py ... More on stackoverflow.com
🌐 stackoverflow.com
🌐
The Hitchhiker's Guide to Python
docs.python-guide.org β€Ί writing β€Ί structure
Structuring Your Project β€” The Hitchhiker's Guide to Python
Of course, you are also free to publish code without a license, but this would prevent many people from potentially using or contributing to your code. If your module package is at the root of your repository, this should obviously be at the root as well. A pip requirements file should be placed at the root of the repository. It should specify the dependencies required to contribute to the project: testing, building, and generating documentation.
🌐
GeeksforGeeks
geeksforgeeks.org β€Ί python β€Ί typical-directory-structure-for-running-tests-using-unittest-in-python
Typical directory structure for running tests using unittest in Python - GeeksforGeeks
July 23, 2025 - The __init__.py file is a special ... code that can be used by other parts of your project. tests/ is a subdirectory that contains test code for your project....
🌐
Amazon S3
s3.amazonaws.com β€Ί assets.datacamp.com β€Ί production β€Ί course_15974 β€Ί slides β€Ί chapter3.pdf pdf
How to organize a growing set of tests?
Project structure Β· src/ # All application code lives here Β· |-- data/ # Package for data preprocessing Β· | |-- __init__.py Β· | |-- preprocessing_helpers.py # Contains row_to_list(), convert_to_int() |-- features/ # Package for feature generation from preprocessed data Β· |-- __init__.py Β· UNIT TESTING FOR DATA SCIENCE IN PYTHON Β·
🌐
YouTube
youtube.com β€Ί watch
🐍 Python Project Directory Structures & Unit Test πŸ§ͺ - YouTube
🐍 Python Project Directory Structures & Unit Test πŸ§ͺWelcome to this informative episode, where we dive into the essential aspects of Python project director...
Published: July 23, 2023
Find elsewhere
🌐
Medium
medium.com β€Ί @sreeku.ralla β€Ί organizing-unit-tests-in-python-as-packages-ff5f9271d049
Organizing Unit Tests in Python as packages | by Srikari Rallabandi | Medium
August 26, 2022 - I faced a few issues in writing unit tests, especially while organizing test code I wanted to share how I overcome the same. I had the following sample class in the OOPS folder as a python package.
🌐
Reddit
reddit.com β€Ί r/python β€Ί arguments against separating `test` from `src` in a python package?
r/Python on Reddit: Arguments against separating `test` from `src` in a python package?
March 23, 2023 -

The Python Packaging Authority recommends separating the test directory from the src (source code) directory in a Python application:

https://packaging.python.org/en/latest/tutorials/packaging-projects/#creating-the-package-files

Personally, I have always preferred this approach of keeping tests outside the package rather than mixing them with the source code (tests in package).

However, in the interest of expanding my perspective and learning something new, I am open to exploring alternative viewpoints. What are the main arguments for including tests within the package itself?

Image taken from https://blog.ionelmc.ro/2014/05/25/python-packaging/
🌐
Reddit
reddit.com β€Ί r/learnpython β€Ί how to structure a very simply python project with pytest tests
r/learnpython on Reddit: How to structure a very simply Python project with pytest tests
May 24, 2026 -

I am struggling to get what is a very simple Python project (for my own use) set up correctly with respect to module name resolution for script execution and for running tests via pytest.

While this project could certainly be done with a flat structure, I am trying to understand how to structure things *properly* for a larger project. I know that *properly* is up for debate, so I am just looking for advice. Should I have __init__.py files in any of these folders (empty or otherwise)? Should I have a pytest.ini and/or pyproject.toml file? All recommendations are welcome. Thanks.

settings.json contains:

my_project/
β”œβ”€β”€ .vscode/
β”‚   └── settings.json
β”œβ”€β”€ src/
β”‚   └── main.py
β”œβ”€β”€ tests/
β”‚   └── test_utils.py
└── utils/
    └── utils.py


main.py is the script to be run with imports from the utils file/module

settings.json contains:
{
    "python.testing.pytestArgs": [
        "tests"
    ],
    "python.testing.unittestEnabled": false,
    "python.testing.pytestEnabled": true
}
Top answer
1 of 5
3
my_project/ β”œβ”€β”€ .vscode/ β”‚ └── settings.json β”œβ”€β”€ src/ β”‚ └── main.py β”œβ”€β”€ tests/ β”‚ └── test_utils.py └── utils/ └── utils.py Whether or not IDE/editor-specific files should be included in version control (e.g. Git) is a somewhat hot topic, and I know your question had nothing to do with that, but I just thought I'd mention that in most cases it's best to .gitignore them. I'll get back to this specific case later. If following a flat project structure, src should be a package and named after the project. If not, src should only contain packages (usually only one), and you should have a pyproject.toml file in the repository root containing the necessary metadata and possibly other configuration options. By using packages you simplify your imports and paths a lot, making your code far easier to test. main.py is the script to be run with imports from the utils file/module utils should not be in the repository root if it relies on other code in the project. Similarly, main.py shouldn't depend on anything higher up the directory tree. For self-contained scripts (for example, something used to simplify build processes in CI pipelines) the convention I've used is a scripts directory with independent script files. Side note; utils is a fairly generic name, and often there's a better way to structure your program where you wouldn't need that. settings.json contains: { "python.testing.pytestArgs": [ "tests" ], "python.testing.unittestEnabled": false, "python.testing.pytestEnabled": true } Instead of configuring pytest in an IDE-specific file, I'd very much recommend doing at least most of it in pyproject.toml or pytest's own configuration file, as then it'd behave the same no matter how you run it. For example, in this case I'd move at least the test file location to them. If you need an example, you could consider this: https://github.com/Diapolo10/python-ms
2 of 5
3
Your app should be a package. Packaging is Python's solution to universal module names.
🌐
Plain English
plainenglish.io β€Ί home β€Ί blog β€Ί python β€Ί structuring unit tests in python
Structuring Unit Tests in Python
July 25, 2020 - I usually put everything that configures pytest in the setup.cfg and the fixtures in a conftest.py within tests/. The Python style of writing tests is by creating a function which contains the test.
🌐
Pylenium
docs.pylenium.io β€Ί getting-started β€Ί project-structure-with-pytest
3. Project Structure with pytest | Pylenium.io
pytest uses specific naming conventions ... are at the Project Root (aka Workspace) pytest uses special functions called Fixtures to control the Setup and Teardown of tests and runs....
🌐
Plain English
python.plainenglish.io β€Ί unit-testing-in-python-structure-57acd51da923
Structuring Unit Tests in Python | Python in Plain English
February 5, 2021 - mpu <-- Root of the git repository β”œβ”€β”€ mpu <-- Root of the package β”‚ β”œβ”€β”€ datastructures/ β”‚ β”‚ β”œβ”€β”€ __init__.py β”‚ β”‚ └── trie β”‚ β”‚ β”œβ”€β”€ char_trie.py β”‚ β”‚ └── __init__.py β”‚ β”œβ”€β”€ geometry.py β”‚ β”œβ”€β”€ image.py β”‚ β”œβ”€β”€ __init__.py β”‚ β”œβ”€β”€ io.py β”‚ └── _version.py β”œβ”€β”€ README.md β”œβ”€β”€ requirements-dev.in β”œβ”€β”€ requirements-dev.txt β”œβ”€β”€ tests/ β”‚ β”œβ”€β”€ files/ β”‚ β”œβ”€β”€ test_char_trie.py β”‚ β”œβ”€β”€ test_datastructures.py β”‚ β”œβ”€β”€ test_geometry.py β”‚ β”œβ”€β”€ test_image.py β”‚ β”œβ”€β”€ test_io.py β”‚ └── test_main.py └── tox.ini
🌐
Testomat
testomat.io β€Ί home β€Ί python testing guide: how to write and run unit tests
Python Testing Guide: How to Write and Run Unit Tests
July 2, 2026 - Create a clear test project structure. This includes organizing all the tests, modules, and Python code files. This will optimize the testing process. Check the Python dependencies after installation.
Address: Ul. Koszykarska 27b-26, KrakΓ³w
🌐
Reddit
reddit.com β€Ί r/python β€Ί how to structure a python project to work with py.test?
r/Python on Reddit: How to structure a Python project to work with py.test?
August 16, 2016 -

This one example project I found here: https://github.com/kennethreitz/samplemod fails if sample/core.py imports sample/helpers.py as import helpers (it works if I do from . import helpers, but then it doesn't work to run it with python sample/core.py). Moreso, py.test recommends against having an __init__.py in the tests dir to begin with.

Is there a consistent way to organise a project such that it supports testing, packaging, and running it from the command line as a script rather than a module? (i.e. python code.py rather than python -m code). Ideally, all this while having a file structure where tests is a top-level directory and contains all tests.

Top answer
1 of 3
2
This question is best in r/learnpython Pytest specifically For pytest specifically, you should update your pytest.ini file and/or setup.cfg at the top of your repo and simply run py.test within your python virtual environment at the top of the repo. Hopefully you're using virtualenv or (better) vex. Ideally, you've also setup tox and potentially detox (ues a tox.ini or setup.cfg) so you can do more CI-like matrix testing against multiple environments. Tox also lets you build out environments for other things (like documentation). py.test (and tox or detox) will find your test files matched against test_* by default regardless of where the test files live. So you can structure your package with a top level tests folder or not -- whatever makes the most sense to you (and hopefully to whomever uses your code). By adding a __init__.py (not recommended) to your tests folder, it will get pulled into your package when its built. And in that scenario you can run tests on your target environment with a -m option, but I suspect you should really only run tests on your dev and qa environments (if you have both of those) and explicitly use pytest or tox. Command-lines generally I have two answers. I'm not sure which one you're actually looking for. Setup the script properly with a shebang. Add a console script to your setup.py First answer You might be looking to add this at the top of your file: #!/usr/bin/env python That will tell your bash shell to look for the default python in your environment and run it. Within a script, you'll want to add a few things, though: # !/usr/bin/env python # -*- coding: utf-8 -*- # file: hello.py def hello(): print('Hello!') if __name__ == '__main__': hello() This will tell the script to run hello only if it's in the 'main' environment within python...which is what the top level environment is when you start up the interpreter. You can check that with: $ python >>> print(__name__) __main__ Anything that falls under that __name__ == '__main__' line will only be executed from a top level python interpreter. The line will not be run during an import. Second answer The other option you may be looking for is a __main__.py and then adding a console script like so: entry_points = { 'console_scripts': [ 'command_line_name=package.__main__:function' ], } so if you did something like this: # file: hello_package/__main__.py def hello(): print('Hello!') and # file: setup.py from setuptools import setup ... setup( ... entry_points = { 'console_scripts': [ 'hello=hello_package.__main__:hello' ], } ... ) You could then run from your standard linux command-line: $ hello Hello! Command-line parsers Also, you'll want to think about how you write your command-line parser. Python comes with argparse but it's terribly obsolete at this point. Some later versions have integrated optparse, but while it's a better library than argparse the interface still leaves much room for improvement. Your best bet is to look at docopt and click. They're not really intended to be used together. The former provides a great way of specifying all of your command-line options at the top of your file within a docstring for that module. This makes it extremely easy to find the options for anyone looking at it later. And since you're using the docstring in the actual execution of the code, that also means that it will be kept up-to-date. click is the other option and provides a great decorator system. It's also modular enough that it can be used to produce more complex command-lines than docopt. But it's harder to know what the options are for the command-line at first glance, so learning/maintenance can be more difficult. I recommend this for smaller command-lines or command-lines that require multiple layers of commands (e.g. git).
2 of 3
1
This page explains the two right ways to do it.
🌐
YouTube
youtube.com β€Ί watch
Pytest Projects: Best Practices for Folder Structure and Imports - YouTube
Using PyTest is easy! But using it properly is much much harder. In this video you'll learn how to use PyTest in a proper python project (not just a single f...
Published: December 11, 2023
🌐
GitHub
github.com β€Ί ferdinandvanwyk β€Ί python_project_example
GitHub - ferdinandvanwyk/python_project_example: Simple example of a good project structure with pytest and sphinx implemented Β· GitHub
Simple example of a good project structure with pytest and sphinx implemented Β· Good pytest practises: http://pytest.org/latest/goodpractises.html Β· General Python testing information: http://pythontesting.net/start-here/ Directory structure and getting started with writing a setup.py: https://pythonhosted.org/an_example_pypi_project/setuptools.html Β·
Author: ferdinandvanwyk
🌐
Madhudadi
madhudadi.in β€Ί blog home β€Ί posts β€Ί python project best practices. β€Ί essential python project best practices for developers
Python Project Best Practices: Structure & Testing Guide | Madhu Dadi
June 26, 2026 - A good Python project structure includes a README.md, pyproject.toml, .gitignore, .env.example, src/ directory with main modules, tests/, scripts/, docs/, and a .venv/ directory.
🌐
Dlemfh
dlemfh.github.io β€Ί quick-scrap β€Ί python β€Ί project-structure β€Ί test-suites
Project Structure for Test Suites
To give the individual tests import context, create a tests/context.py file: import os import sys sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) import sample Β· Then, within the individual test modules, import the module like so: