cjolowicz / hypermodern-python

Hypermodern Python
https://medium.com/@cjolowicz/hypermodern-python-d44485d9d769
MIT License
611 stars 90 forks source link

Pytest default src layout tweak #309

Open rnickle opened 2 years ago

rnickle commented 2 years ago

Claudio,

Thank you very much for this comprehensive article, which I discovered from a recent Talk Python to Me podcast (362).

I was struck by the use of src layout, which I have seen before but did not understand. I immediately tried to adopt it for a small project, but was struck that if I created a blank project with src layout, pytest was not working by default.

For example:

$ poetry new --name rnickle_template --src rnickle_template
$ ls
README.rst  poetry.lock  pyproject.toml  src  tests
$ pytest | grep ^E
E   ModuleNotFoundError: No module named 'rnickle_template'
ERROR tests/test_rnickle_template.py

There's an easy fix:

$ touch src/conftest.py
$ pytest
[ redacted ]
= 1 passed in 0.39s =

Or in pytest >= 7:

[tool.pytest.ini_options]
pythonpath = [
  "src"
]

Perhaps we can add a comment about that to the setup page?

Thanks,

Rick

cjolowicz commented 2 years ago

Hi @rnickle thank you for the feedback!

You need to install your project for pytest to be able to import it. This is by design. Without the src layout, pytest will import your project from the source tree, which can lead to problems if the source tree is dirty or when there are packaging issues. Testing the installed version of your project ensures that you're testing the version of the code that your users get when they install your package.

There are different ways to do this. The easiest (but not the best way) is to use poetry install, then poetry run pytest. This assumes that you have added pytest as a development dependency. The reason it's not the best way is that Poetry installs your package using an editable install, which amounts to running tests against your source tree. (An editable install is essentially a glorified symlink.)

For this reason, I would recommend to use something like Nox, or at least virtualenv. The later articles in the series explain how to do this. (Also check out nox-poetry for better integration of Nox and Poetry. It's not mentioned in the blog, but it's a part of the companion project template.)