remove old ways to set option defaults, relying on global setup.cfg or tox.ini files now.
revamp py.test --help-config --HG-- branch : trunk
This commit is contained in:
parent
b86b1628bb
commit
c9e629c870
|
@ -3,7 +3,9 @@ Changes between 1.3.4 and 2.0.0dev0
|
||||||
|
|
||||||
- pytest-2.0 is now its own package and depends on pylib-2.0
|
- pytest-2.0 is now its own package and depends on pylib-2.0
|
||||||
- introduce a new way to set config options via ini-style files,
|
- introduce a new way to set config options via ini-style files,
|
||||||
by default setup.cfg and tox.ini files are searched.
|
by default setup.cfg and tox.ini files are searched. The old
|
||||||
|
ways (certain environment variables, dynamic conftest.py reading
|
||||||
|
is removed).
|
||||||
- fix issue126 - introduce py.test.set_trace() to trace execution via
|
- fix issue126 - introduce py.test.set_trace() to trace execution via
|
||||||
PDB during the running of tests even if capturing is ongoing.
|
PDB during the running of tests even if capturing is ongoing.
|
||||||
- fix issue123 - new "python -m py.test" invocation for py.test
|
- fix issue123 - new "python -m py.test" invocation for py.test
|
||||||
|
|
|
@ -8,12 +8,12 @@ basic test configuration
|
||||||
Command line options
|
Command line options
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
You can see command line options by running::
|
You can get help on options and configuration by running::
|
||||||
|
|
||||||
py.test -h
|
py.test -h # or --help
|
||||||
|
|
||||||
This will display all available command line options
|
This will display command line options, ini-settings and conftest.py
|
||||||
in your specific environment.
|
settings in your specific environment.
|
||||||
|
|
||||||
reading test configuration from ini-files
|
reading test configuration from ini-files
|
||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
|
@ -28,12 +28,12 @@ Possible entries in a ``[pytest]`` section are:
|
||||||
|
|
||||||
minversion = 2.1 # will fail if we run with pytest-2.0
|
minversion = 2.1 # will fail if we run with pytest-2.0
|
||||||
|
|
||||||
.. confval:: appendargs = OPTS
|
.. confval:: addargs = OPTS
|
||||||
|
|
||||||
append the specified ``OPTS`` to the command line arguments as if they
|
add the specified ``OPTS`` to the set of command line arguments as if they
|
||||||
had been specified by the user. Example::
|
had been specified by the user. Example::
|
||||||
|
|
||||||
appendargs = --maxfail=2 -rf # exit after 2 failures, report fail info
|
addargs = --maxfail=2 -rf # exit after 2 failures, report fail info
|
||||||
|
|
||||||
|
|
||||||
setting persistent option defaults
|
setting persistent option defaults
|
||||||
|
|
|
@ -45,7 +45,7 @@ class Parser:
|
||||||
self._anonymous.addoption(*opts, **attrs)
|
self._anonymous.addoption(*opts, **attrs)
|
||||||
|
|
||||||
def parse(self, args):
|
def parse(self, args):
|
||||||
optparser = MyOptionParser(self)
|
self.optparser = optparser = MyOptionParser(self)
|
||||||
groups = self._groups + [self._anonymous]
|
groups = self._groups + [self._anonymous]
|
||||||
for group in groups:
|
for group in groups:
|
||||||
if group.options:
|
if group.options:
|
||||||
|
@ -53,7 +53,7 @@ class Parser:
|
||||||
optgroup = py.std.optparse.OptionGroup(optparser, desc)
|
optgroup = py.std.optparse.OptionGroup(optparser, desc)
|
||||||
optgroup.add_options(group.options)
|
optgroup.add_options(group.options)
|
||||||
optparser.add_option_group(optgroup)
|
optparser.add_option_group(optgroup)
|
||||||
return optparser.parse_args([str(x) for x in args])
|
return self.optparser.parse_args([str(x) for x in args])
|
||||||
|
|
||||||
def parse_setoption(self, args, option):
|
def parse_setoption(self, args, option):
|
||||||
parsedoption, args = self.parse(args)
|
parsedoption, args = self.parse(args)
|
||||||
|
@ -91,7 +91,8 @@ class OptionGroup:
|
||||||
class MyOptionParser(py.std.optparse.OptionParser):
|
class MyOptionParser(py.std.optparse.OptionParser):
|
||||||
def __init__(self, parser):
|
def __init__(self, parser):
|
||||||
self._parser = parser
|
self._parser = parser
|
||||||
py.std.optparse.OptionParser.__init__(self, usage=parser._usage)
|
py.std.optparse.OptionParser.__init__(self, usage=parser._usage,
|
||||||
|
add_help_option=False)
|
||||||
def format_epilog(self, formatter):
|
def format_epilog(self, formatter):
|
||||||
hints = self._parser.hints
|
hints = self._parser.hints
|
||||||
if hints:
|
if hints:
|
||||||
|
@ -248,6 +249,12 @@ class Config(object):
|
||||||
self.trace("loaded conftestmodule %r" %(conftestmodule,))
|
self.trace("loaded conftestmodule %r" %(conftestmodule,))
|
||||||
self.pluginmanager.consider_conftest(conftestmodule)
|
self.pluginmanager.consider_conftest(conftestmodule)
|
||||||
|
|
||||||
|
def _processopt(self, opt):
|
||||||
|
if hasattr(opt, 'default') and opt.dest:
|
||||||
|
if not hasattr(self.option, opt.dest):
|
||||||
|
setattr(self.option, opt.dest, opt.default)
|
||||||
|
|
||||||
|
|
||||||
def _getmatchingplugins(self, fspath):
|
def _getmatchingplugins(self, fspath):
|
||||||
allconftests = self._conftest._conftestpath2mod.values()
|
allconftests = self._conftest._conftestpath2mod.values()
|
||||||
plugins = [x for x in self.pluginmanager.getplugins()
|
plugins = [x for x in self.pluginmanager.getplugins()
|
||||||
|
@ -259,31 +266,6 @@ class Config(object):
|
||||||
if getattr(self.option, 'traceconfig', None):
|
if getattr(self.option, 'traceconfig', None):
|
||||||
self.hook.pytest_trace(category="config", msg=msg)
|
self.hook.pytest_trace(category="config", msg=msg)
|
||||||
|
|
||||||
def _processopt(self, opt):
|
|
||||||
if hasattr(opt, 'default') and opt.dest:
|
|
||||||
val = os.environ.get("PYTEST_OPTION_" + opt.dest.upper(), None)
|
|
||||||
if val is not None:
|
|
||||||
if opt.type == "int":
|
|
||||||
val = int(val)
|
|
||||||
elif opt.type == "long":
|
|
||||||
val = long(val)
|
|
||||||
elif opt.type == "float":
|
|
||||||
val = float(val)
|
|
||||||
elif not opt.type and opt.action in ("store_true", "store_false"):
|
|
||||||
val = eval(val)
|
|
||||||
opt.default = val
|
|
||||||
else:
|
|
||||||
name = "option_" + opt.dest
|
|
||||||
try:
|
|
||||||
opt.default = self._conftest.rget(name)
|
|
||||||
except (ValueError, KeyError):
|
|
||||||
try:
|
|
||||||
opt.default = self.inicfg[opt.dest]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
if not hasattr(self.option, opt.dest):
|
|
||||||
setattr(self.option, opt.dest, opt.default)
|
|
||||||
|
|
||||||
def _setinitialconftest(self, args):
|
def _setinitialconftest(self, args):
|
||||||
# capture output during conftest init (#issue93)
|
# capture output during conftest init (#issue93)
|
||||||
name = hasattr(os, 'dup') and 'StdCaptureFD' or 'StdCapture'
|
name = hasattr(os, 'dup') and 'StdCaptureFD' or 'StdCapture'
|
||||||
|
@ -300,6 +282,10 @@ class Config(object):
|
||||||
|
|
||||||
def _preparse(self, args):
|
def _preparse(self, args):
|
||||||
self.inicfg = getcfg(args, ["setup.cfg", "tox.ini",])
|
self.inicfg = getcfg(args, ["setup.cfg", "tox.ini",])
|
||||||
|
if self.inicfg:
|
||||||
|
newargs = self.inicfg.get("addargs", None)
|
||||||
|
if newargs:
|
||||||
|
args[:] = args + py.std.shlex.split(newargs)
|
||||||
self._checkversion()
|
self._checkversion()
|
||||||
self.pluginmanager.consider_setuptools_entrypoints()
|
self.pluginmanager.consider_setuptools_entrypoints()
|
||||||
self.pluginmanager.consider_env()
|
self.pluginmanager.consider_env()
|
||||||
|
@ -325,10 +311,6 @@ class Config(object):
|
||||||
"can only parse cmdline args at most once per Config object")
|
"can only parse cmdline args at most once per Config object")
|
||||||
self._preparse(args)
|
self._preparse(args)
|
||||||
self._parser.hints.extend(self.pluginmanager._hints)
|
self._parser.hints.extend(self.pluginmanager._hints)
|
||||||
if self.inicfg:
|
|
||||||
newargs = self.inicfg.get("appendargs", None)
|
|
||||||
if newargs:
|
|
||||||
args += py.std.shlex.split(newargs)
|
|
||||||
args = self._parser.parse_setoption(args, self.option)
|
args = self._parser.parse_setoption(args, self.option)
|
||||||
if not args:
|
if not args:
|
||||||
args.append(py.std.os.getcwd())
|
args.append(py.std.os.getcwd())
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
""" provide version info, conftest/environment config names.
|
""" provide version info, conftest/environment config names.
|
||||||
"""
|
"""
|
||||||
import py
|
import py
|
||||||
|
import pytest
|
||||||
import inspect, sys
|
import inspect, sys
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
group = parser.getgroup('debugconfig')
|
group = parser.getgroup('debugconfig')
|
||||||
group.addoption('--version', action="store_true",
|
group.addoption('--version', action="store_true",
|
||||||
help="display py lib version and import information.")
|
help="display py lib version and import information.")
|
||||||
|
group._addoption("-h", "--help", action="store_true", dest="help",
|
||||||
|
help="show help message and configuration info")
|
||||||
group._addoption('-p', action="append", dest="plugins", default = [],
|
group._addoption('-p', action="append", dest="plugins", default = [],
|
||||||
metavar="name",
|
metavar="name",
|
||||||
help="early-load given plugin (multi-allowed).")
|
help="early-load given plugin (multi-allowed).")
|
||||||
|
@ -19,56 +22,47 @@ def pytest_addoption(parser):
|
||||||
group.addoption('--debug',
|
group.addoption('--debug',
|
||||||
action="store_true", dest="debug", default=False,
|
action="store_true", dest="debug", default=False,
|
||||||
help="generate and show internal debugging information.")
|
help="generate and show internal debugging information.")
|
||||||
group.addoption("--help-config", action="store_true", dest="helpconfig",
|
|
||||||
help="show available conftest.py and ENV-variable names.")
|
|
||||||
|
|
||||||
|
|
||||||
def pytest_cmdline_main(config):
|
def pytest_cmdline_main(config):
|
||||||
if config.option.version:
|
if config.option.version:
|
||||||
p = py.path.local(py.__file__).dirpath()
|
p = py.path.local(pytest.__file__).dirpath()
|
||||||
sys.stderr.write("This is py.test version %s, imported from %s\n" %
|
sys.stderr.write("This is py.test version %s, imported from %s\n" %
|
||||||
(py.__version__, p))
|
(py.__version__, p))
|
||||||
return 0
|
return 0
|
||||||
elif config.option.helpconfig:
|
elif config.option.help:
|
||||||
config.pluginmanager.do_configure(config)
|
config.pluginmanager.do_configure(config)
|
||||||
showpluginhelp(config)
|
showhelp(config)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def showpluginhelp(config):
|
def showhelp(config):
|
||||||
options = []
|
|
||||||
for group in config._parser._groups:
|
|
||||||
options.extend(group.options)
|
|
||||||
widths = [0] * 10
|
|
||||||
tw = py.io.TerminalWriter()
|
tw = py.io.TerminalWriter()
|
||||||
tw.sep("-")
|
tw.write(config._parser.optparser.format_help())
|
||||||
tw.line("%-13s | %-18s | %-25s | %s" %(
|
tw.line()
|
||||||
"cmdline name", "conftest.py name", "ENV-variable name", "help"))
|
tw.line()
|
||||||
tw.sep("-")
|
tw.sep( "=", "ini-settings")
|
||||||
|
tw.line("the following values can be defined in [pytest] sections of")
|
||||||
|
tw.line("setup.cfg or tox.ini files:")
|
||||||
|
tw.line()
|
||||||
|
|
||||||
options = [opt for opt in options if opt._long_opts]
|
for name, help in ini_settings:
|
||||||
options.sort(key=lambda x: x._long_opts)
|
line = " %-15s %s" %(name, help)
|
||||||
for opt in options:
|
|
||||||
if not opt._long_opts or not opt.dest:
|
|
||||||
continue
|
|
||||||
optstrings = list(opt._long_opts) # + list(opt._short_opts)
|
|
||||||
optstrings = filter(None, optstrings)
|
|
||||||
optstring = "|".join(optstrings)
|
|
||||||
line = "%-13s | %-18s | %-25s | %s" %(
|
|
||||||
optstring,
|
|
||||||
"option_%s" % opt.dest,
|
|
||||||
"PYTEST_OPTION_%s" % opt.dest.upper(),
|
|
||||||
opt.help and opt.help or "",
|
|
||||||
)
|
|
||||||
tw.line(line[:tw.fullwidth])
|
tw.line(line[:tw.fullwidth])
|
||||||
|
|
||||||
|
tw.line() ; tw.line()
|
||||||
|
#tw.sep( "=", "conftest.py settings")
|
||||||
|
tw.line("the following values can be defined in conftest.py files")
|
||||||
|
tw.line()
|
||||||
for name, help in conftest_options:
|
for name, help in conftest_options:
|
||||||
line = "%-13s | %-18s | %-25s | %s" %(
|
line = " %-15s %s" %(name, help)
|
||||||
"",
|
|
||||||
name,
|
|
||||||
"",
|
|
||||||
help,
|
|
||||||
)
|
|
||||||
tw.line(line[:tw.fullwidth])
|
tw.line(line[:tw.fullwidth])
|
||||||
tw.sep("-")
|
tw.line()
|
||||||
|
tw.sep( "=")
|
||||||
|
|
||||||
|
ini_settings = (
|
||||||
|
('addargs', 'extra command line arguments'),
|
||||||
|
('minversion', 'minimally required pytest version'),
|
||||||
|
)
|
||||||
|
|
||||||
conftest_options = (
|
conftest_options = (
|
||||||
('pytest_plugins', 'list of plugin names to load'),
|
('pytest_plugins', 'list of plugin names to load'),
|
||||||
|
@ -79,7 +73,9 @@ conftest_options = (
|
||||||
def pytest_report_header(config):
|
def pytest_report_header(config):
|
||||||
lines = []
|
lines = []
|
||||||
if config.option.debug or config.option.traceconfig:
|
if config.option.debug or config.option.traceconfig:
|
||||||
lines.append("using py lib: %s" % (py.path.local(py.__file__).dirpath()))
|
lines.append("using: pytest-%s pylib-%s" %
|
||||||
|
(pytest.__version__,py.__version__))
|
||||||
|
|
||||||
if config.option.traceconfig:
|
if config.option.traceconfig:
|
||||||
lines.append("active plugins:")
|
lines.append("active plugins:")
|
||||||
plugins = []
|
plugins = []
|
||||||
|
@ -149,12 +145,11 @@ def getargs(func):
|
||||||
startindex = inspect.ismethod(func) and 1 or 0
|
startindex = inspect.ismethod(func) and 1 or 0
|
||||||
return args[startindex:]
|
return args[startindex:]
|
||||||
|
|
||||||
def collectattr(obj, prefixes=("pytest_",)):
|
def collectattr(obj):
|
||||||
methods = {}
|
methods = {}
|
||||||
for apiname in dir(obj):
|
for apiname in dir(obj):
|
||||||
for prefix in prefixes:
|
if apiname.startswith("pytest_"):
|
||||||
if apiname.startswith(prefix):
|
methods[apiname] = getattr(obj, apiname)
|
||||||
methods[apiname] = getattr(obj, apiname)
|
|
||||||
return methods
|
return methods
|
||||||
|
|
||||||
def formatdef(func):
|
def formatdef(func):
|
||||||
|
|
|
@ -242,6 +242,9 @@ class TmpTestdir:
|
||||||
def makefile(self, ext, *args, **kwargs):
|
def makefile(self, ext, *args, **kwargs):
|
||||||
return self._makefile(ext, args, kwargs)
|
return self._makefile(ext, args, kwargs)
|
||||||
|
|
||||||
|
def makeini(self, source):
|
||||||
|
return self.makefile('cfg', setup=source)
|
||||||
|
|
||||||
def makeconftest(self, source):
|
def makeconftest(self, source):
|
||||||
return self.makepyfile(conftest=source)
|
return self.makepyfile(conftest=source)
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,13 @@ def test_version(testdir):
|
||||||
'*py.test*%s*imported from*' % (py.version, )
|
'*py.test*%s*imported from*' % (py.version, )
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_helpconfig(testdir):
|
def test_help(testdir):
|
||||||
result = testdir.runpytest("--help-config")
|
result = testdir.runpytest("--help")
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*cmdline*conftest*ENV*",
|
"*-v*verbose*",
|
||||||
|
"*ini-settings*",
|
||||||
|
"*conftest.py*",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_collectattr():
|
def test_collectattr():
|
||||||
|
|
|
@ -466,8 +466,8 @@ def test_getreportopt():
|
||||||
testdict.update(dict(reportchars="sfx"))
|
testdict.update(dict(reportchars="sfx"))
|
||||||
assert getreportopt(config) == "sfx"
|
assert getreportopt(config) == "sfx"
|
||||||
|
|
||||||
def test_terminalreporter_reportopt_conftestsetting(testdir):
|
def test_terminalreporter_reportopt_addargs(testdir):
|
||||||
testdir.makeconftest("option_report = 'skipped'")
|
testdir.makeini("[pytest]\naddargs=-rs")
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
def pytest_funcarg__tr(request):
|
def pytest_funcarg__tr(request):
|
||||||
tr = request.config.pluginmanager.getplugin("terminalreporter")
|
tr = request.config.pluginmanager.getplugin("terminalreporter")
|
||||||
|
|
|
@ -16,19 +16,10 @@ class TestParseIni:
|
||||||
config._preparse([sub])
|
config._preparse([sub])
|
||||||
assert config.inicfg['name'] == 'value'
|
assert config.inicfg['name'] == 'value'
|
||||||
|
|
||||||
def test_getvalue(self, tmpdir):
|
|
||||||
tmpdir.join("setup.cfg").write(py.code.Source("""
|
|
||||||
[pytest]
|
|
||||||
verbose = True
|
|
||||||
"""))
|
|
||||||
config = Config()
|
|
||||||
config._preparse([tmpdir])
|
|
||||||
assert config.option.verbose
|
|
||||||
|
|
||||||
def test_append_parse_args(self, tmpdir):
|
def test_append_parse_args(self, tmpdir):
|
||||||
tmpdir.join("setup.cfg").write(py.code.Source("""
|
tmpdir.join("setup.cfg").write(py.code.Source("""
|
||||||
[pytest]
|
[pytest]
|
||||||
appendargs = --verbose
|
addargs = --verbose
|
||||||
"""))
|
"""))
|
||||||
config = Config()
|
config = Config()
|
||||||
config.parse([tmpdir])
|
config.parse([tmpdir])
|
||||||
|
@ -46,32 +37,6 @@ class TestParseIni:
|
||||||
])
|
])
|
||||||
|
|
||||||
class TestConfigCmdlineParsing:
|
class TestConfigCmdlineParsing:
|
||||||
def test_parser_addoption_default_env(self, testdir, monkeypatch):
|
|
||||||
import os
|
|
||||||
config = testdir.Config()
|
|
||||||
config._preparse([testdir.tmpdir])
|
|
||||||
group = config._parser.getgroup("hello")
|
|
||||||
|
|
||||||
monkeypatch.setitem(os.environ, 'PYTEST_OPTION_OPTION1', 'True')
|
|
||||||
group.addoption("--option1", action="store_true")
|
|
||||||
assert group.options[0].default == True
|
|
||||||
|
|
||||||
monkeypatch.setitem(os.environ, 'PYTEST_OPTION_OPTION2', 'abc')
|
|
||||||
group.addoption("--option2", action="store", default="x")
|
|
||||||
assert group.options[1].default == "abc"
|
|
||||||
|
|
||||||
monkeypatch.setitem(os.environ, 'PYTEST_OPTION_OPTION3', '32')
|
|
||||||
group.addoption("--option3", action="store", type="int")
|
|
||||||
assert group.options[2].default == 32
|
|
||||||
|
|
||||||
group.addoption("--option4", action="store", type="int")
|
|
||||||
assert group.options[3].default == ("NO", "DEFAULT")
|
|
||||||
|
|
||||||
def test_parser_addoption_default_conftest(self, testdir, monkeypatch):
|
|
||||||
import os
|
|
||||||
testdir.makeconftest("option_verbose=True")
|
|
||||||
config = testdir.parseconfig()
|
|
||||||
assert config.option.verbose
|
|
||||||
|
|
||||||
def test_parsing_again_fails(self, testdir):
|
def test_parsing_again_fails(self, testdir):
|
||||||
config = testdir.reparseconfig([testdir.tmpdir])
|
config = testdir.reparseconfig([testdir.tmpdir])
|
||||||
|
|
|
@ -2,11 +2,11 @@ import py
|
||||||
from pytest.plugin import config as parseopt
|
from pytest.plugin import config as parseopt
|
||||||
|
|
||||||
class TestParser:
|
class TestParser:
|
||||||
def test_init(self, capsys):
|
def test_no_help_by_default(self, capsys):
|
||||||
parser = parseopt.Parser(usage="xyz")
|
parser = parseopt.Parser(usage="xyz")
|
||||||
py.test.raises(SystemExit, 'parser.parse(["-h"])')
|
py.test.raises(SystemExit, 'parser.parse(["-h"])')
|
||||||
out, err = capsys.readouterr()
|
out, err = capsys.readouterr()
|
||||||
assert out.find("xyz") != -1
|
assert err.find("no such option") != -1
|
||||||
|
|
||||||
def test_group_add_and_get(self):
|
def test_group_add_and_get(self):
|
||||||
parser = parseopt.Parser()
|
parser = parseopt.Parser()
|
||||||
|
|
Loading…
Reference in New Issue