Run tests with tox
Why bother?
Running the unit tests we wrote previously is as simple as just executing pytest
in the dev environment, so why do anything else? Turns out there are many good reasons:
- You are not testing your code in a clean environment - there could be extra files, missing ones, environment variables, etc.
- You are testing the code as it appears in your repository folders, not as it appears after installation with
pip
- You are not testing whether the code can actually be
pip
installed - You are only testing the version of Python you have on your dev system
How does tox help?
Tox is a really cool bit of software, it does so much with almost no effort at all. With a minimal amount of configuration (see below) you can have tox create multiple virtual environments with different versions of Python, install your package into them and run all your tests.
[tox]
envlist = py37, py38, py39, py310
isolated_build=true
[testenv]
deps =
-rdist/requirements.txt
pytest
pytest-cov
pytest-mock
commands =
pytest --cov=my_project --cov-append --cov-branch
Installing tox
Since tox will be installing your project, it doesn't make much sense to make tox a project dependency. Instead you should make it available in your test environment independently. The simplest way is just to pip install tox
into your system Python. If you'd rather not clutter your system python with packages
Managing packages dependencies
Note the line -rdist/requirements.txt
above. This forces tox to pip install
all my package's dependencies as declared in requirements.txt
before installing the package.
I could skip this step and the dependencies would still get installed as pip
would determine they are required for the package.
However, by using a requirements.txt
file generated during packaging I can specify the exact versions of every dependency (known as pinning dependencies).
I also include this file with the installer so the production environment looks exactly like the one that was tested.
Managing test dependencies
When your project is installed by tox, the dev dependencies are not installed. This is as-expected as this is supposed to replicate a production environment. However, this means that if you want pytest in your environment (hint: you do) you need to ensure you include it as a dependency in the tox.ini file as shown above.
In the latest version of cookiecutter-snoap I have combined this step with the one above by including the test dependencies in my Poetry environment and then using the following command to create a combined requirements file, pinning both the runtime and test dependencies.
poetry export -f requirements.txt --with dev --output build/requirements-with-dev.txt
Managing multiple Python versions with pyenv
One thing that tox doesn't do is install Python for you. You need to have the Python versions with which you want to test installed on your test system. As XKCD confirms, multiple Python installs can quickly get out of hand. Luckily pyenv is here to help. If you are running on Windows, there is a Windows-friendly fork pyenv-win