fix issue127 improve pytest_addoption docs, add new config.getoption(name) method for consistency.

This commit is contained in:
holger krekel 2012-11-06 14:09:12 +01:00
parent dba2a8bc64
commit 33cd414420
10 changed files with 73 additions and 18 deletions

View File

@ -27,6 +27,9 @@ Changes between 2.3.2 and 2.3.3.dev
- fix issue217 - support mock.patch with pytest's fixtures - note that - fix issue217 - support mock.patch with pytest's fixtures - note that
you need either mock-1.0.1 or the python3.3 builtin unittest.mock. you need either mock-1.0.1 or the python3.3 builtin unittest.mock.
- fix issue127 - improve documentation for pytest_addoption() and
add a ``config.getoption(name)`` helper function for consistency.
Changes between 2.3.1 and 2.3.2 Changes between 2.3.1 and 2.3.2
----------------------------------- -----------------------------------

View File

@ -1,2 +1,2 @@
# #
__version__ = '2.3.3.dev4' __version__ = '2.3.3.dev5'

View File

@ -271,9 +271,8 @@ class CmdOptions(object):
class Config(object): class Config(object):
""" access to configuration values, pluginmanager and plugin hooks. """ """ access to configuration values, pluginmanager and plugin hooks. """
def __init__(self, pluginmanager=None): def __init__(self, pluginmanager=None):
#: command line option values, which must have been previously added #: access to command line option as attributes.
#: via calls like ``parser.addoption(...)`` or #: (deprecated), use :py:func:`getoption() <_pytest.config.Config.getoption>` instead
#: ``parser.getgroup(groupname).addoption(...)``
self.option = CmdOptions() self.option = CmdOptions()
self._parser = Parser( self._parser = Parser(
usage="usage: %prog [options] [file_or_dir] [file_or_dir] [...]", usage="usage: %prog [options] [file_or_dir] [file_or_dir] [...]",
@ -285,6 +284,7 @@ class Config(object):
self._conftest = Conftest(onimport=self._onimportconftest) self._conftest = Conftest(onimport=self._onimportconftest)
self.hook = self.pluginmanager.hook self.hook = self.pluginmanager.hook
self._inicache = {} self._inicache = {}
self._opt2dest = {}
self._cleanup = [] self._cleanup = []
@classmethod @classmethod
@ -305,6 +305,9 @@ class Config(object):
self.pluginmanager.consider_conftest(conftestmodule) self.pluginmanager.consider_conftest(conftestmodule)
def _processopt(self, opt): def _processopt(self, opt):
for name in opt._short_opts + opt._long_opts:
self._opt2dest[name] = opt.dest
if hasattr(opt, 'default') and opt.dest: if hasattr(opt, 'default') and opt.dest:
if not hasattr(self.option, opt.dest): if not hasattr(self.option, opt.dest):
setattr(self.option, opt.dest, opt.default) setattr(self.option, opt.dest, opt.default)
@ -383,8 +386,9 @@ class Config(object):
x.append(line) # modifies the cached list inline x.append(line) # modifies the cached list inline
def getini(self, name): def getini(self, name):
""" return configuration value from an ini file. If the """ return configuration value from an :ref:`ini file <inifiles>`. If the
specified name hasn't been registered through a prior ``parse.addini`` specified name hasn't been registered through a prior
:py:func:`parser.addini <pytest.config.Parser.addini>`
call (usually from a plugin), a ValueError is raised. """ call (usually from a plugin), a ValueError is raised. """
try: try:
return self._inicache[name] return self._inicache[name]
@ -438,8 +442,22 @@ class Config(object):
self._checkconftest(name) self._checkconftest(name)
return self._conftest.rget(name, path) return self._conftest.rget(name, path)
def getoption(self, name):
""" return command line option value.
:arg name: name of the option. You may also specify
the literal ``--OPT`` option instead of the "dest" option name.
"""
name = self._opt2dest.get(name, name)
try:
return getattr(self.option, name)
except AttributeError:
raise ValueError("no option named %r" % (name,))
def getvalue(self, name, path=None): def getvalue(self, name, path=None):
""" return ``name`` value looked set from command line options. """ return command line option value.
:arg name: name of the command line option
(deprecated) if we can't find the option also lookup (deprecated) if we can't find the option also lookup
the name in a matching conftest file. the name in a matching conftest file.

View File

@ -23,10 +23,28 @@ def pytest_cmdline_preparse(config, args):
"""modify command line arguments before option parsing. """ """modify command line arguments before option parsing. """
def pytest_addoption(parser): def pytest_addoption(parser):
"""use the parser to add optparse-style options and ini-style """register optparse-style options and ini-style config values.
config values via calls, see :py:func:`parser.addoption(...)
<_pytest.config.Parser.addoption>` This function must be implemented in a :ref:`plugin <pluginorder>` and is
and :py:func:`parser.addini(...) <_pytest.config.Parser.addini>`. called once at the beginning of a test run.
:arg parser: To add command line options, call
:py:func:`parser.addoption(...) <_pytest.config.Parser.addoption>`.
To add ini-file values call :py:func:`parser.addini(...)
<_pytest.config.Parser.addini>`.
Options can later be accessed through the
:py:class:`config <_pytest.config.Config>` object, respectively:
- :py:func:`config.getoption(name) <_pytest.config.Config.getoption>` to
retrieve the value of a command line option.
- :py:func:`config.getini(name) <_pytest.config.Config.getini>` to retrieve
a value read from an ini-style file.
The config object is passed around on many internal objects via the ``.config``
attribute or can be retrieved as the ``pytestconfig`` fixture or accessed
via (deprecated) ``pytest.config``.
""" """
def pytest_cmdline_main(config): def pytest_cmdline_main(config):
@ -35,7 +53,7 @@ def pytest_cmdline_main(config):
pytest_cmdline_main.firstresult = True pytest_cmdline_main.firstresult = True
def pytest_configure(config): def pytest_configure(config):
""" called after command line options have been parsed. """ called after command line options have been parsed
and all plugins and initial conftest files been loaded. and all plugins and initial conftest files been loaded.
""" """

View File

@ -12,6 +12,8 @@ configurations files by using the general help option::
This will display command line and configuration file settings This will display command line and configuration file settings
which were registered by installed plugins. which were registered by installed plugins.
.. _inifiles:
How test configuration is read from configuration INI-files How test configuration is read from configuration INI-files
------------------------------------------------------------- -------------------------------------------------------------

View File

@ -194,7 +194,7 @@ specifies via named environments::
import pytest import pytest
def pytest_addoption(parser): def pytest_addoption(parser):
parser.addoption("-E", dest="env", action="store", metavar="NAME", parser.addoption("-E", action="store", metavar="NAME",
help="only run tests matching the environment NAME.") help="only run tests matching the environment NAME.")
def pytest_configure(config): def pytest_configure(config):
@ -206,7 +206,7 @@ specifies via named environments::
envmarker = item.keywords.get("env", None) envmarker = item.keywords.get("env", None)
if envmarker is not None: if envmarker is not None:
envname = envmarker.args[0] envname = envmarker.args[0]
if envname != item.config.option.env: if envname != item.config.getoption("-E"):
pytest.skip("test requires env %r" % envname) pytest.skip("test requires env %r" % envname)
A test file using this local plugin:: A test file using this local plugin::

View File

@ -33,7 +33,7 @@ provide the ``cmdopt`` through a :ref:`fixture function <fixture function>`::
@pytest.fixture @pytest.fixture
def cmdopt(request): def cmdopt(request):
return request.config.option.cmdopt return request.config.getoption("--cmdopt")
Let's run this without supplying our new option:: Let's run this without supplying our new option::
@ -129,7 +129,7 @@ line option to control skipping of ``slow`` marked tests::
help="run slow tests") help="run slow tests")
def pytest_runtest_setup(item): def pytest_runtest_setup(item):
if 'slow' in item.keywords and not item.config.getvalue("runslow"): if 'slow' in item.keywords and not item.config.getoption("--runslow"):
pytest.skip("need --runslow option to run") pytest.skip("need --runslow option to run")
We can now write a test module like this:: We can now write a test module like this::

View File

@ -5,7 +5,7 @@ Working with plugins and conftest files
py.test implements all aspects of configuration, collection, running and reporting by calling `well specified hooks`_. Virtually any Python module can be registered as a plugin. It can implement any number of hook functions (usually two or three) which all have a ``pytest_`` prefix, making hook functions easy to distinguish and find. There are three basic location types: py.test implements all aspects of configuration, collection, running and reporting by calling `well specified hooks`_. Virtually any Python module can be registered as a plugin. It can implement any number of hook functions (usually two or three) which all have a ``pytest_`` prefix, making hook functions easy to distinguish and find. There are three basic location types:
* `builtin plugins`_: loaded from py.test's own ``pytest/plugin`` directory. * `builtin plugins`_: loaded from py.test's internal ``_pytest`` directory.
* `external plugins`_: modules discovered through `setuptools entry points`_ * `external plugins`_: modules discovered through `setuptools entry points`_
* `conftest.py plugins`_: modules auto-discovered in test directories * `conftest.py plugins`_: modules auto-discovered in test directories
@ -155,6 +155,8 @@ If a package is installed this way, py.test will load
``myproject.pluginmodule`` as a plugin which can define ``myproject.pluginmodule`` as a plugin which can define
`well specified hooks`_. `well specified hooks`_.
.. _`pluginorder`:
Plugin discovery order at tool startup Plugin discovery order at tool startup
-------------------------------------------- --------------------------------------------
@ -175,6 +177,7 @@ py.test loads plugin modules at tool startup in the following way:
* by recursively loading all plugins specified by the * by recursively loading all plugins specified by the
``pytest_plugins`` variable in ``conftest.py`` files ``pytest_plugins`` variable in ``conftest.py`` files
Requiring/Loading plugins in a test module or conftest file Requiring/Loading plugins in a test module or conftest file
------------------------------------------------------------- -------------------------------------------------------------

View File

@ -24,7 +24,7 @@ def main():
name='pytest', name='pytest',
description='py.test: simple powerful testing with Python', description='py.test: simple powerful testing with Python',
long_description = long_description, long_description = long_description,
version='2.3.3.dev4', version='2.3.3.dev5',
url='http://pytest.org', url='http://pytest.org',
license='MIT license', license='MIT license',
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],

View File

@ -103,6 +103,16 @@ class TestConfigAPI:
assert config.getvalue("x", o) == 1 assert config.getvalue("x", o) == 1
pytest.raises(KeyError, 'config.getvalue("y", o)') pytest.raises(KeyError, 'config.getvalue("y", o)')
def test_config_getoption(self, testdir):
testdir.makeconftest("""
def pytest_addoption(parser):
parser.addoption("--hello", "-X", dest="hello")
""")
config = testdir.parseconfig("--hello=this")
for x in ("hello", "--hello", "-X"):
assert config.getoption(x) == "this"
pytest.raises(ValueError, "config.getoption('qweqwe')")
def test_config_getvalueorskip(self, testdir): def test_config_getvalueorskip(self, testdir):
config = testdir.parseconfig() config = testdir.parseconfig()
pytest.raises(pytest.skip.Exception, pytest.raises(pytest.skip.Exception,
@ -304,3 +314,4 @@ def test_cmdline_processargs_simple(testdir):
"*pytest*", "*pytest*",
"*-h*", "*-h*",
]) ])