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.
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.
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.
How to structure a very simply Python project with pytest tests
How to structure a Python project to work with py.test?
[deleted by user]
What is the optimal structure for a Python project?
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
}
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.