Generally, any instructions that have you modifying sys.path
in order to run your tests are sending you in the wrong direction. Your testing tool should be able to discover both your tests and your application code without requiring that sort of hackery.
I generally use pytest for running my tests. I would structure your example like this:
my-project/
├── src
│ ├── conftest.py
│ └── myproject
│ ├── __init__.py
│ └── script.py
└── tests
├── __init__.py
└── test_script.py
Assuming that src/myproject/script.py
looks like this:
def double(x: int):
return x*2
And tests/test_script.py
look like this:
import myproject.script
def test_double():
res = myproject.script.double(2)
assert res == 4
I can run tests from the my-project
directory by simply running pytest
:
$ pytest
========================================== test session starts ==========================================
platform linux -- Python 3.11.1, pytest-7.2.0, pluggy-1.0.0
rootdir: /home/lars/tmp/python/my-project
collected 1 item
tests/test_script.py . [100%]
=========================================== 1 passed in 0.00s ===========================================
In this setup, the file src/conftest.py
is what allows pytest to automatically discover the location of your application code. Alternatively, you could instead specify that in your pyproject.toml
file like this:
[tool.pytest.ini_options]
pythonpath = [
"src"
]
pytest also works if you write unittest
-style tests as you show in your question; the above behavior would be identical if tests/test_script.py
looked like:
import unittest
import myproject.script
class TestScript(unittest.TestCase):
def test_double(self):
res = myproject.script.double(2)
self.assertEqual(res, 4)
if __name__ == '__main__':
unittest.main()
(But I prefer pytest's simpler syntax.)
Possibly useful reading:
If you really want to use unittest
you can use the same directory layout, but you will need to update sys.path
for it to run correctly. The easiest way to do that is:
PYTHONPATH=$PWD/src python -m unittest
This will automatically discover all your tests and run them. You can run a single test like this:
PYTHONPATH=$PWD/src python -m tests.test_script
You can avoid needing to modify sys.path
if you use a simpler directory layout:
my-project/
├── myproject
│ ├── __init__.py
│ └── script.py
└── tests
├── __init__.py
└── test_script.py
Both pytest
and python -m unittest
, when run from the my-project
directory, will correctly discover and run your tests without requiring any path modifications.