This should be the easiest problem on earth, but even after extensive searching and tinkering, I'm still in deep trouble with finding a "correct" way to lay a directory structure and manage to run pytest etc correctly.
Let's say my I have a program called apple.
|- README.md |- apple | |-- __init__.py | |-- apple.py | - tests | |-- test_everything.py
The apple.py contains some functions, for examples sake let's call one eat()
. And the test_everything.py
file contains some tests like assert eat()=="foobar"
. So good so easy, but then the fun begins:
__init__.py
in the apple directory... correct? Empty or what should be inside?py.test
from the root directory? Or py.test tests
?__init__.py
in their test directory, but that's explicitly said to be wrong in the py.test documentation. So why god whytest_everything.py
file: an import apple
or from apple import *
? or something else entirelyeat()
or apple.eat()
?os.path.dirname
in pythonThis should be easy, but I've seen every combination of the above, not even speaking about tox and the myriad of other tools. Yet with the slightest error, you get thrown some ImportError: No module named 'apple'
or some other funky error.
What is the "right" way? The advice and the existing code on github etc follows extremely different conventions. For a medium-experienced coder, this should be much easier.
Project Structure The modules containing pytests should be named “test_*. py” or “*_test.py”. While the pytest discovery mechanism can find tests anywhere, pytests must be placed into separate directories from the product code packages. These directories may either be under the project root or under the Python package.
src/ — This is the folder that contains your python package codes. The structure of this folder varies on the application layout you have chosen. logs/ — log files are saved in this folder.
Running pytest without mentioning a filename will run all files of format test_*. py or *_test.py in the current directory and subdirectories. Pytest automatically identifies those files as test files.
Conventions for Python test discovery pytest implements the following standard test discovery: If no arguments are specified then collection starts from testpaths (if configured) or the current directory. Alternatively, command line arguments can be used in any combination of directories, file names or node ids.
__init__.py
in the apple directory... correct? Empty or what should be inside?Yes, correct. Most frequently empty. If you put foo = 42
in it you can later do from apple import foo
while you'll need to do from apple.apple import foo
if you put it in apple.py
. While it might seem convenient you should use it sparingly.
py.test should be able to find your tests regardless, but see below..
__init__.py
in their test directory, but that's explicitly said to be wrong in the py.test documentation. So why god whySo you can import a file in tests that provide common test functionality. In py.test that might be better achieved by creating fixtures in a file called tests/conftest.py
.
from apple import apple
apple.eat()
That seems very fragile. I would suggest either
(a) set the environment variable PYTHONPATH to point to the folder where README.md
is, or better
(b) create a setup.py file (at the same level as your README.md
file), here's a minimal one:
from setuptools import setup setup(name='apple', packages=['apple'])
Run the file like so:
python setup.py develop
now apple
is globally available and you should never see a no module named apple
problem again, i.e. you can run py.test from the root folder or the tests folder.
You can read more about setup.py
in the Python Packaging User Guide at https://packaging.python.org/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With