Trusted answers to developer questions
Trusted Answers to Developer Questions

Related Tags

community creator

How to use tox with a Makefile to automate Python-related tasks

Haseeb Majid

In this article, we will go over how we can use a makefile and tox to automate various Python-related, command-line (CLI) tools. This article assumes you are running bash or an equivalent.


tox is an automation tool that is primarily used to add in testing. On the tox website, it describes itself as:

tox aims to automate and standardize testing in Python. It is part of a larger vision of easing the packaging, testing, and release process of Python software.

You can define a configuration file tox.ini – this is where you will define all of your tox environments. In the example below, we have two environments, testenv to run our tests and testenv:lint to linta tool that analyzes source code to flag programming errors, bugs, stylistic errors, and suspicious constructs. our code with Flake8.


envlist = py36,py37,lint

basepython =
    {lint}: {env:TOXPYTHON:python3}
    py36: {env:TOXPYTHON:python3.6}
    py37: {env:TOXPYTHON:python3.7}
passenv = *
install_command = pip install {opts} {packages}
deps =
usedevelop = false
commands = pytest -v {posargs} tests

skip_install = true
deps = flake8
commands = flake8 src/

tox creates a virtual environment (virtualenv) for each tox environment defined in the configuration file (tox.ini). It then runs our command within that virtualenv, you can see these if you take a look in the .tox folder. So, in our lint example, it would create a virtualenv called lint in the .tox folder, install our dependencies (flake8), and finally run the command flake8 src/ (within the lint virtualenv). You can read more about how tox works over here. So, how do we run a Tox environment? Well,like so:


# Install Tox
pip install tox
# Run the tox environment
tox -e lint

We can pass extra parameters to tox environments using the {posargs}. So, for example, if we had an environment defined as:


skip_install = true
deps = bumpversion
commands = bumpversion --verbose {posargs}

We could run it like so, tox -e bumpversion -- --allow-dirty patch (note the extra --).

As you can see, tox allows us to automate tedious Python-related tasks like code formatting, running the lint, and running unit tests. We can test our code against different versions of Python as well, such as Python3.6 or Python3.7, to make sure our code is compatible with both.

If we wanted to run pytest against python3.6 we could do it like so, tox -e py36. If we want to run pytest against python3.7 we could do it with, tox -e py37 (given the same configuration file as above). Some common tools used in conjunction with tox are:


Makefiles are often used in C/C++ programs to compile the code/generate binaries, etc., and to automate (often long-winded) tasks. To use a make file, all you need to do is create a file called Makefile. Each “job” in the makefile is called a target; for example, a makefile may look like:

PY = py36

# prompt_example> make test PY=py36 OPTIONS="-- -s"
.PHONY: test
	@tox -e $(PY) $(OPTIONS)

.PHONY: lint
	@tox -e lint

So, now, if we want to run our linter, we could do make lint – to run our tests, we can type the command make test. If we want to specify a Python version, we could do make test PY=py37 (note how $(PY) is a variable we can override). This may remind you of tools available to other languages such as package.json for JavaScript/NodeJS. The main advantage of using a Makefile with tox is that we can define targets in our makefile that aren’t specifically related to Python tools, such as cleaning our project:

.PHONY: clean
	@find . -type f -name '*.pyc' -delete
	@find . -type d -name '__pycache__' | xargs rm -rf
	@find . -type d -name '*.ropeproject' | xargs rm -rf
	@rm -rf build/
	@rm -rf dist/
	@rm -f src/*.egg*
	@rm -f MANIFEST
	@rm -rf docs/build/
	@rm -f .coverage.*

That’s it! A simple introduction on how you can use a Makefile and tox to automate various, tedious tasks.


community creator

View all Courses

Keep Exploring