Tutorial

This tutorial will walk you through installing, configuring, and running Nox.

Installation

Nox can be easily installed via pip:

pip install --upgrade nox

Usually you install this globally, similar to tox, pip, and other similar tools.

Running Nox

The simplest way of running Nox will run all sessions defined in noxfile.py:

nox

However, if you wish to run a single session or subset of sessions you can use the -s argument:

nox --sessions lint tests-2.7
nox -s lint

You can read more about invoking Nox in Command-line usage.

Creating a noxfile

When you run nox, it looks for a file named noxfile.py in the current directory. This file contains all of the session definitions. A session is an environment and a set of commands to run in that environment. Sessions are analogous to environments in tox.

Sessions are declared using the @nox.session decorator:

@nox.session
def lint(session):
    session.install('flake8')
    session.run('flake8')

If you run this via nox you should see output similar to this:

nox > Running session lint
nox > virtualenv /tmp/example/.nox/lint
nox > pip install --upgrade flake8
nox > flake8
nox > Session lint successful. :)

Setting up virtualenvs and installing dependencies

Nox automatically creates a separate virtualenv for every session. You can choose which Python interpreter to use when declaring the session. When you install dependencies or run commands within a session, they all use the session’s virtualenv. Here’s an example of a session that uses Python 2.7, installs dependencies in various ways, and runs a command:

@nox.session(python='2.7')
def tests(session):
    # Install py.test
    session.install('pytest')
    # Install everything in requirements-dev.txt
    session.install('-r', 'requirements-dev.txt')
    # Install the current package in editable mode.
    session.install('-e', '.')
    # Run py.test. This uses the py.test executable in the virtualenv.
    session.run('py.test')

You can create as many session as you want and sessions can use multiple Python versions, for example:

@nox.session(python=['2.7', '3.6'])
def tests(session):
    ...

If you specify multiple Python versions, Nox will create separate sessions for each Python version. If you run nox --list-sessions, you’ll see that this generates the following set of sessions:

* tests-2.7
* tests-3.6

You can read more about configuring sessions in Configuration & API.

Running commands

Running a command in a session is easy - just pass the command name and arguments to session.run():

@nox.session
def tests(session):
    session.install('pytest')
    session.run('pytest', '-k', 'not slow')

There are some other helpful methods on nox.sessions.Session. For example, to change the current working directory you can use session.chdir():

session.chdir('docs')
session.run('sphinx-build', 'html')

Passing arguments into sessions

Often it’s useful to pass arguments into your test session. Here’s a quick example that demonstrates how to use arguments to run tests against a particular file:

@nox.session
def test(session):
    session.install('py.test')

    if session.posargs:
        test_files = session.posargs
    else:
        test_files = ['test_a.py', 'test_b.py']

    session.run('pytest', *test_files)

Now you if you run:

nox

Then nox will run:

pytest test_a.py test_b.py

But if you run:

nox -- test_c.py

Then nox will run:

pytest test_c.py

Parametrizing sessions

Session arguments can be parametrized with the nox.parametrize() decorator. Here’s a typical example of parametrizing the Django version to install:

@nox.session
@nox.parametrize('django', ['1.9', '2.0'])
def tests(session, django):
    session.install(f'django=={django}')
    session.run('py.test')

When you run nox, it will create a two distinct sessions:

$ nox
nox > Running session tests(django='1.9')
nox > pip install --upgrade django==1.9
...
nox > Running session tests(djano='2.0')
nox > pip install --upgrade django==2.0

nox.parametrize() has an interface and usage intentionally similar to py.test’s parametrize.

parametrize(arg_names, arg_values_list)

Parametrize a session.

Add new invocations to the underlying session function using the list of arg_values_list for the given arg_names. Parametrization is performed during session discovery and each invocation appears as a separate session to nox.

Parameters:
  • arg_names (Sequence[str]) – A list of argument names.
  • arg_values_list (Sequence[Union[Any, Tuple]]) – The list of argument values determines how often a session is invoked with different argument values. If only one argument names was specified then this is a simple list of values, for example [1, 2, 3]. If N argument names were specified, this must be a list of N-tuples, where each tuple-element specifies a value for its respective argument name, for example [(1, 'a'), (2, 'b')].

You can also stack the decorator to produce sessions that are a combination of the arguments, for example:

@nox.session
@nox.parametrize('django', ['1.9', '2.0'])
@nox.parametrize('database', ['postgres', 'mysql'])
def tests(session, django, database):
    ...

If you run nox --list-sessions, you’ll see that this generates the following set of sessions:

* tests(django='1.9', database='postgres')
* tests(django='2.0', database='mysql')
* tests(django='1.9', database='postgres')
* tests(django='2.0', database='mysql')

If you only want to run one of the parametrized sessions, see Specifying parametrized sessions.