diff --git a/CHANGELOG b/CHANGELOG index d8641ac64..fa8673018 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,11 @@ Changes between 2.0.0 and 2.0.1.dev1 ---------------------------------------------- +- introduce a pytest_cmdline_processargs(args) hook + to allow dynamic computation of command line arguments. + This fixes a regression because py.test prior to 2.0 + allowed to set command line options from conftest.py + files which so far pytest-2.0 only allowed from ini-files now. - fix issue7: assert failures in doctest modules. unexpected failures in doctests will not generally show nicer, i.e. within the doctest failing context. diff --git a/_pytest/config.py b/_pytest/config.py index 93fdeb393..2becdc91c 100644 --- a/_pytest/config.py +++ b/_pytest/config.py @@ -305,6 +305,8 @@ class Config(object): self.pluginmanager.consider_env() self._setinitialconftest(args) self.pluginmanager.do_addoption(self._parser) + if addopts: + self.hook.pytest_cmdline_processargs(config=self, args=args) def _checkversion(self): minver = self.inicfg.get('minversion', None) diff --git a/_pytest/hookspec.py b/_pytest/hookspec.py index bc6d5405e..23d3137b5 100644 --- a/_pytest/hookspec.py +++ b/_pytest/hookspec.py @@ -19,6 +19,9 @@ def pytest_cmdline_parse(pluginmanager, args): """return initialized config object, parsing the specified args. """ pytest_cmdline_parse.firstresult = True +def pytest_cmdline_processargs(config, args): + """modify command line arguments before option parsing. """ + def pytest_addoption(parser): """add optparse-style options and ini-style config values via calls to ``parser.addoption`` and ``parser.addini(...)``. @@ -202,7 +205,6 @@ def pytest_doctest_prepare_content(content): """ return processed content for a given doctest""" pytest_doctest_prepare_content.firstresult = True - # ------------------------------------------------------------------------- # error handling and internal debugging hooks # ------------------------------------------------------------------------- diff --git a/doc/Makefile b/doc/Makefile index 3469e9959..4c0871aa0 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -40,7 +40,7 @@ clean: -rm -rf $(BUILDDIR)/* install: clean html - rsync -avz _build/html/ code:www-pytest/ + rsync -avz _build/html/ code:www-pytest/2.0.1dev html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html diff --git a/doc/example/simple.txt b/doc/example/simple.txt index 87c6a9b13..23f89bf59 100644 --- a/doc/example/simple.txt +++ b/doc/example/simple.txt @@ -138,11 +138,42 @@ let's run the full monty:: E assert 4 < 4 test_compute.py:3: AssertionError - 1 failed, 4 passed in 0.03 seconds + 1 failed, 4 passed in 0.02 seconds As expected when running the full range of ``param1`` values we'll get an error on the last one. +dynamically adding command line options +-------------------------------------------------------------- + +.. regendoc:wipe + +Through :confval:`addopts` you can statically add command line +options for your project. You can also dynamically modify +the command line arguments before they get processed:: + + # content of conftest.py + import sys + def pytest_cmdline_processargs(args): + if 'xdist' in sys.modules: # pytest-xdist plugin + import multiprocessing + num = max(multiprocessing.cpu_count() / 2, 1) + args[:] = ["-n", str(num)] + args + +If you have the :ref:`xdist plugin ` installed +you will now always perform test runs using a number +of subprocesses close to your CPU. Running in an empty +directory with the above conftest.py:: + + $ py.test + =========================== test session starts ============================ + platform linux2 -- Python 2.6.5 -- pytest-2.0.1.dev3 + gw0 I / gw1 I / gw2 I / gw3 I + gw0 [0] / gw1 [0] / gw2 [0] / gw3 [0] + + scheduling tests via LoadScheduling + + ============================= in 0.29 seconds ============================= .. _`retrieved by hooks as item keywords`: @@ -183,12 +214,12 @@ and when running it will see a skipped "slow" test:: $ py.test -rs # "-rs" means report details on the little 's' =========================== test session starts ============================ - platform linux2 -- Python 2.6.5 -- pytest-2.0.0 + platform linux2 -- Python 2.6.5 -- pytest-2.0.1.dev3 collecting ... collected 2 items test_module.py .s ========================= short test summary info ========================== - SKIP [1] /tmp/doc-exec-479/conftest.py:9: need --runslow option to run + SKIP [1] /tmp/doc-exec-25/conftest.py:9: need --runslow option to run =================== 1 passed, 1 skipped in 0.02 seconds ==================== @@ -196,7 +227,7 @@ Or run it including the ``slow`` marked test:: $ py.test --runslow =========================== test session starts ============================ - platform linux2 -- Python 2.6.5 -- pytest-2.0.0 + platform linux2 -- Python 2.6.5 -- pytest-2.0.1.dev3 collecting ... collected 2 items test_module.py .. diff --git a/doc/plugins.txt b/doc/plugins.txt index 80a3d9e65..2c640c178 100644 --- a/doc/plugins.txt +++ b/doc/plugins.txt @@ -271,6 +271,7 @@ initialisation, command line and configuration hooks .. currentmodule:: _pytest.hookspec +.. autofunction:: pytest_cmdline_processargs .. autofunction:: pytest_cmdline_parse .. autofunction:: pytest_namespace .. autofunction:: pytest_addoption diff --git a/testing/test_config.py b/testing/test_config.py index 954909a81..c3257ac20 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -82,7 +82,6 @@ class TestConfigCmdlineParsing: class TestConfigAPI: - def test_config_trace(self, testdir): config = testdir.Config() l = [] @@ -252,3 +251,14 @@ def test_plugin_preparse_prevents_setuptools_loading(testdir, monkeypatch): config = testdir.parseconfig("-p", "no:mytestplugin") plugin = config.pluginmanager.getplugin("mytestplugin") assert plugin == -1 + +def test_cmdline_processargs_simple(testdir): + testdir.makeconftest(""" + def pytest_cmdline_processargs(args): + args.append("-h") + """) + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + "*pytest*", + "*-h*", + ])