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.

Discussions

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
[deleted by user]
My first thought is that those files are going to end up installed in your package directory when you install it with pip or included in a wheel or however you package up your code. Why would you want to include tests in a 'deliverable' like that? More on reddit.com
🌐 r/Python
10
4
October 26, 2022
What is the optimal structure for a Python project?
3 tips from me: When you use typing everywhere then you are forcing yourself to omit the circular dependencies (we cannot have circular dependencies imports in python) between modules which is the easiest way to keep a very basic structure. Think of the modules hierarchy while structuring the python code. Which module is high level (e.g. dashboard, GUI) and which is low level (e.g. some utils module build upon a standard library). Always import a module that has a lower level of abstraction (or in other words, lower complexity) in the module with higher complexity. E.g. GUI module imports storage access module and not the other way around. More on reddit.com
🌐 r/Python
52
253
December 25, 2023
🌐
GitHub
gist.github.com β€Ί tasdikrahman β€Ί 2bdb3fb31136a3768fac
Typical Directory structure for python tests Β· GitHub
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
🌐
The Hitchhiker's Guide to Python
docs.python-guide.org β€Ί writing β€Ί structure
Structuring Your Project β€” The Hitchhiker's Guide to Python
Some people will assert that you should distribute your tests within your module itself – I disagree. It often increases complexity for your users; many test suites often require additional dependencies and runtime contexts. If you look at most of my projects or any Pocoo project, you’ll notice a Makefile lying around.
🌐
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 - Here is an example of a complete ... Python: We are going to have two different files math_functions.py which contain different mathematical functions and test_math_functions.py which contains tests related to math_functions.py...
🌐
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
🌐
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 Β·
Find elsewhere
🌐
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
🌐
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
🌐
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. This might seem weird to you if you come from a Java / JUnit-influenced testing world.
🌐
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/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.
🌐
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.
🌐
Coderwall
coderwall.com β€Ί p β€Ί lt2kew β€Ί python-creating-your-project-structure
Python: Creating Your Project Structure (Example)
August 26, 2025 - As already written in Unit Testing in Python and Short Introduction to Unit Testing, I cannot emphasize the importance of testing enough. With unit tests you can guide the development, verify your functionalities and document the behavior of your application. Add your tests in the project/tests folder (see tests-folder in the example project).
🌐
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.
🌐
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. This can be done using the pip package management system. Use the pip check command to run the check. ... Create virtual environments. It ensures that the packages and their versions are specific to your project and do not interfere with the packages in other projects and vice versa.
Address: Ul. Koszykarska 27b-26, KrakΓ³w
🌐
Krython
krython.com β€Ί tutorial β€Ί python β€Ί test-organization-project-structure
πŸ“˜ Test Organization: Project Structure - Tutorial | Krython
# βœ… Safe - proper Python packages! tests/ β”œβ”€β”€ __init__.py β”œβ”€β”€ unit/ β”‚ β”œβ”€β”€ __init__.py # πŸ“¦ Makes it a package! β”‚ └── test_user.py Β· 🎯 Mirror Source Structure: Test structure should match source structure ... # 🎯 Blog project test structure!
🌐
Pylenium
docs.pylenium.io β€Ί getting-started β€Ί project-structure-with-pytest
3. Project Structure with pytest | Pylenium.io
pytest uses specific naming conventions and project structure Β· You should have created these in the previous step, but they are required for Pylenium to do its magic. conftest.py Β· pylenium.json Β· pytest.ini Β· Make sure these are at the Project Root (aka Workspace) pytest uses special functions called Fixtures to control the Setup and Teardown of tests and runs.
🌐
Python Tutorial
pythontutorial.net β€Ί home β€Ί python unit testing β€Ί organizing code & running unittest
Run Unittest in Python: Organizing Code & Running Unittest
July 9, 2022 - And you should place the test code in a directory called test to make it obvious. For demonstration purposes, we’ll create a sample project with the following structure: D:\python-unit-testing β”œβ”€β”€ shapes | β”œβ”€β”€ circle.py | β”œβ”€β”€ shape.py | └── square.py └── test β”œβ”€β”€ test_circle.py β”œβ”€β”€ test_square.py └── __init__.pyCopy
🌐
TryzTech
tryztech.com β€Ί home β€Ί blog β€Ί python project structure: venv, pip, requirements, and testing
Python Project Structure: venv, pip, Requirements, and Testing | TryzTech
August 21, 2026 - src/expense_tracker/ contains the main source code. tests/ contains tests. requirements.txt records dependencies. README.md explains how to run the project. You do not need this structure for every tiny exercise, but it is a solid pattern once a project becomes more serious. A virtual environment separates project dependencies from your global Python installation. This keeps one project from breaking another. A virtual environment is not a new Python version. It is an isolated workspace with its own package location and executables, so pytest and other packages for this project do not mix with a different project.