make 'setup.py test' command support passing pytest specific arguments

Added a new 'setup.py test' command-line options --pytest-args/-a accepting all
pytest specific command-line arguments as a single whitespace separated string.

For example, the following command will run only tests containing ``binding`` in
their name, will stop on first failure and will automatically drop into Python's
post-mortem debugger on failure::

  setup.py test -a "-k binding -x --pdb"

Does not currently support passing pytest specific command-line arguments
containing embedded whitespace.
This commit is contained in:
Jurko Gospodnetić 2014-05-31 13:58:17 +02:00
parent 95e7b40d17
commit 3ece6d16a0
2 changed files with 45 additions and 19 deletions

View File

@ -407,22 +407,36 @@ folder instead. This functionality should be considered a band-aid though, and
setting up the target environment can be better done as described in the
`Setting up the development & testing environment`_ section.
The ``setup.py test`` command will build the project if needed and run its
complete test suite in the target Python environment. The project does not need
to be preinstalled into the target Python environment for this operation to
work, and neither will the operation leave it installed.
The ``setup.py test`` command will build the project if needed and run its test
suite in the target Python environment. The project does not need to be
preinstalled into the target Python environment for this operation to work, and
neither will the operation leave it installed.
Unless a more restricted test set is selected using ``pytest`` specific
command-line options, ``setup.py test`` command runs the complete project test
suite.
Specific ``pytest`` command-line options may be provided by passing them all as
a single whitespace separated string tunnelled via the ``setup.py test``
command's ``--pytest-args``/``-a`` command-line option.
For example, the following command will run only tests containing ``binding`` in
their name, will stop on first failure and will automatically drop into Python's
post-mortem debugger on failure::
setup.py test -a "-k binding -x --pdb"
Caveats:
* This method does not allow you to provide any extra ``pytest`` options when
running the project test suite.
* When running the ``setup.py test`` command in a Windows Python 2.5
environment without an included ctypes module (e.g. 64-bit CPython 2.5
distribution does not include ctypes) and having it automatically install the
colorama package version older than 0.1.11, you will get benign error messages
reporting colorama's atexit handlers failing. Running the same command again
avoids the issue since the colorama package will then already be installed.
Suggested workaround is to use a colorama package version 0.3.2 or newer.
* This method does not currently allow passing ``pytest`` specific command-line
options containing embedded whitespace.
* When running the ``setup.py test`` command in a Windows Python 2.5 environment
without an included ctypes module (e.g. 64-bit CPython 2.5 distribution does
not include ctypes) and having it automatically install the colorama package
version older than 0.1.11, you will get benign error messages reporting
colorama's atexit handlers failing. Running the same command again avoids the
issue since the colorama package will then already be installed. Suggested
workaround is to use a colorama package version 0.3.2 or newer.
Running the project tests - using ``pytest`` directly
-----------------------------------------------------

View File

@ -522,14 +522,20 @@ else:
else:
description = "run pytest based unit tests after a build"
# Disable base class's command-line options.
user_options = []
# Override base class's command-line options.
#TODO: pytest argument passing support could be improved if we could
# get distutils/setuptools to pass all unrecognized command-line
# parameters to us instead of complaining about them.
user_options = [("pytest-args=", "a", "arguments to pass to pytest "
"(whitespace separated, whitespaces in arguments not supported)")]
def initialize_options(self):
pass
self.pytest_args = None
def finalize_options(self):
pass
self.test_args = []
if self.pytest_args is not None:
self.test_args = self.pytest_args.split()
def run(self):
# shamelessly lifted from setuptools.command.test.test.run()
@ -539,7 +545,7 @@ else:
if dist.tests_require:
dist.fetch_build_eggs(dist.tests_require)
cmd = "pytest"
cmd = self._test_cmd_string()
if self.dry_run:
self.announce("skipping '%s' (dry run)" % (cmd,))
else:
@ -548,7 +554,13 @@ else:
def run_tests(self):
import pytest
sys.exit(pytest.main([]))
sys.exit(pytest.main(self.test_args))
def _test_cmd_string(self):
parts = ["pytest"]
if self.pytest_args:
parts.append(self.pytest_args)
return " ".join(parts)
distutils_cmdclass["test"] = TestCommand