This post is part 5 of the "Making a Python Package" series:
- Making a Python Package
- Making a Python Package II - writing docstrings
- Making a Python Package III - making an installable package
- Making a Python Package IV - writing unit tests
- Making a Python Package V - Testing with Tox
- Making a Python Package VI - including data files
- Making a Python Package VII - deploying
- Making a Python Package VIII - summary
Note: To get the material for this blog post, visit the v0.4.5 tag of Romans! Github project. To get it locally, and assuming you cloned the previous version, run
# clear last set of changes
$ git reset --hard HEAD
# checkout this version
$ git checkout tags/v0.4.5
To install
To follow the steps in this tutorial, you will need to install tox
pip install tox
Making a Python Package V: Testing with tox
We have written some unit tests and seen that they work with our Python environment. The tox
package is a way of automating testing, so that we can build a clean environment to test our pacakge in. It also allows us to automatically run our unit tests against multiple versions of Python (e.g. py27, py36, py37). Because my code uses f-strings, I cannot provide support for versions of Python lower than Python 3.6.
The goal is to run tox
and let it tell us of problems our code has. We will run the following:
pytest
: to run our unit tests and report functional errors,pycodestyle
: to check if our code is PEP8 compliant,pydocstyle
: to check if our docstrings are PEP257 compliant
Making tox.ini
The tox
package has a command tox-quickstart
that you can type in the shell to generate your tox.ini
file. You can also make the file manually. In the top-level directory, save the following code into tox.ini
:
[tox]
envlist=py36
[testenv]
deps =
pydocstyle
pycodestyle
pytest
commands =
- pydocstyle --ignore=D100,104 roman/
- pycodestyle roman/
pytest
This tells tox
:
- I only want to build against Python 3.6 (
envlist=py36
), - The commands I want to run depend on
pydocstyle
,pycodestyle
andpytest
being installed, - I want to run the three commands under the "[commands]" section.
The dashes in front of a command mean "ignore the exit code of this function". Both pydocstyle
and pycodestyle
give non-zero exit codes if they find any violations, and tox
stops on any command that has a non-zero exit code. We want to run all three of these commands, even if one of them finds an issue, so we use the leading dash to ignore the exit code.
When this is all done, your directory should look like
roman_package
+-- roman/
+-- __init__.py
+-- roman.py
+-- temperature.py
+-- setup.py
+-- tests/
+-- __init__.py
+-- test_roman.py
+-- tox.ini
+-- README.md
Using tox
Simply type tox
at the command prompt, and the tests will run!
We see that while all our unit tests pass, there are quite a few errors picked up by pydocstyle
(these errors all start with a D
). We will fix those in the next branch, when we move on to deploying our solution.
Summary and next steps
In this article, we showed how to setup tox.ini
so that we could do all our linting and testing in one step. Although we didn't take advantage of it, tox
is also a tool for testing against multiple Python releases at once.
The next step in our series is one that most projects won't need: how to package datafiles (such as CSVs) in your package. This is a confusing step, so feel free to skip ahead to deployment if you don't need it.