refine initilization: read config also from a "pytest.ini" file if exists
and revert earlier commandline option and group ordering change.
This commit is contained in:
parent
fefac66079
commit
55dff651f4
|
@ -4,7 +4,7 @@ basic test configuration
|
||||||
Command line options and configuration file settings
|
Command line options and configuration file settings
|
||||||
-----------------------------------------------------------------
|
-----------------------------------------------------------------
|
||||||
|
|
||||||
You can get help on options and configuration options by running::
|
You can get help on options and ini-config values by running::
|
||||||
|
|
||||||
py.test -h # prints options _and_ config file settings
|
py.test -h # prints options _and_ config file settings
|
||||||
|
|
||||||
|
@ -14,23 +14,31 @@ which were registered by installed plugins.
|
||||||
how test configuration is read from setup/tox ini-files
|
how test configuration is read from setup/tox ini-files
|
||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
|
|
||||||
py.test looks for the first ``[pytest]`` section in either the first ``setup.cfg`` or the first ``tox.ini`` file found upwards from the arguments. Example::
|
py.test searched for the first matching ini-style configuration file
|
||||||
|
in the directories of command line argument and the directories above.
|
||||||
|
It looks for filenames in this order::
|
||||||
|
|
||||||
|
pytest.ini
|
||||||
|
tox.ini
|
||||||
|
setup.cfg
|
||||||
|
|
||||||
|
Searching stops when the first ``[pytest]`` section is found.
|
||||||
|
There is no merging of configuration values from multiple files. Example::
|
||||||
|
|
||||||
py.test path/to/testdir
|
py.test path/to/testdir
|
||||||
|
|
||||||
will look in the following dirs for a config file::
|
will look in the following dirs for a config file::
|
||||||
|
|
||||||
path/to/testdir/setup.cfg
|
path/to/testdir/pytest.ini
|
||||||
path/to/setup.cfg
|
|
||||||
path/setup.cfg
|
|
||||||
setup.cfg
|
|
||||||
... # up until root of filesystem
|
|
||||||
path/to/testdir/tox.ini
|
path/to/testdir/tox.ini
|
||||||
|
path/to/testdir/setup.cfg
|
||||||
|
path/to/pytest.ini
|
||||||
path/to/tox.ini
|
path/to/tox.ini
|
||||||
path/tox.ini
|
path/to/setup.cfg
|
||||||
... # up until root of filesystem
|
... # up until root of filesystem
|
||||||
|
|
||||||
If no path was provided at all the current working directory is used for the lookup.
|
If argument is provided to a py.test run, the current working directory
|
||||||
|
is used to start the search.
|
||||||
|
|
||||||
builtin configuration file options
|
builtin configuration file options
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
|
@ -236,6 +236,11 @@ class PluginManager(object):
|
||||||
for hint in self._hints:
|
for hint in self._hints:
|
||||||
tw.line("hint: %s" % hint)
|
tw.line("hint: %s" % hint)
|
||||||
|
|
||||||
|
def do_addoption(self, parser):
|
||||||
|
mname = "pytest_addoption"
|
||||||
|
methods = reversed(self.listattr(mname))
|
||||||
|
MultiCall(methods, {'parser': parser}).execute()
|
||||||
|
|
||||||
def do_configure(self, config):
|
def do_configure(self, config):
|
||||||
assert not hasattr(self, '_config')
|
assert not hasattr(self, '_config')
|
||||||
self._config = config
|
self._config = config
|
||||||
|
|
|
@ -21,6 +21,7 @@ class Parser:
|
||||||
self._processopt = processopt
|
self._processopt = processopt
|
||||||
self._usage = usage
|
self._usage = usage
|
||||||
self._inidict = {}
|
self._inidict = {}
|
||||||
|
self._ininames = []
|
||||||
self.hints = []
|
self.hints = []
|
||||||
|
|
||||||
def processoption(self, option):
|
def processoption(self, option):
|
||||||
|
@ -55,12 +56,12 @@ class Parser:
|
||||||
|
|
||||||
def parse(self, args):
|
def parse(self, args):
|
||||||
self.optparser = optparser = MyOptionParser(self)
|
self.optparser = optparser = MyOptionParser(self)
|
||||||
groups = list(reversed(self._groups)) + [self._anonymous]
|
groups = self._groups + [self._anonymous]
|
||||||
for group in groups:
|
for group in groups:
|
||||||
if group.options:
|
if group.options:
|
||||||
desc = group.description or group.name
|
desc = group.description or group.name
|
||||||
optgroup = py.std.optparse.OptionGroup(optparser, desc)
|
optgroup = py.std.optparse.OptionGroup(optparser, desc)
|
||||||
optgroup.add_options(reversed(group.options))
|
optgroup.add_options(group.options)
|
||||||
optparser.add_option_group(optgroup)
|
optparser.add_option_group(optgroup)
|
||||||
return self.optparser.parse_args([str(x) for x in args])
|
return self.optparser.parse_args([str(x) for x in args])
|
||||||
|
|
||||||
|
@ -74,6 +75,7 @@ class Parser:
|
||||||
""" add an ini-file option with the given name and description. """
|
""" add an ini-file option with the given name and description. """
|
||||||
assert type in (None, "pathlist", "args", "linelist")
|
assert type in (None, "pathlist", "args", "linelist")
|
||||||
self._inidict[name] = (help, type, default)
|
self._inidict[name] = (help, type, default)
|
||||||
|
self._ininames.append(name)
|
||||||
|
|
||||||
class OptionGroup:
|
class OptionGroup:
|
||||||
def __init__(self, name, description="", parser=None):
|
def __init__(self, name, description="", parser=None):
|
||||||
|
@ -290,7 +292,7 @@ class Config(object):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def _initini(self, args):
|
def _initini(self, args):
|
||||||
self.inicfg = getcfg(args, ["setup.cfg", "tox.ini",])
|
self.inicfg = getcfg(args, ["pytest.ini", "tox.ini", "setup.cfg"])
|
||||||
self._parser.addini('addopts', 'extra command line options', 'args')
|
self._parser.addini('addopts', 'extra command line options', 'args')
|
||||||
self._parser.addini('minversion', 'minimally required pytest version')
|
self._parser.addini('minversion', 'minimally required pytest version')
|
||||||
|
|
||||||
|
@ -303,7 +305,7 @@ class Config(object):
|
||||||
self.pluginmanager.consider_env()
|
self.pluginmanager.consider_env()
|
||||||
self.pluginmanager.consider_preparse(args)
|
self.pluginmanager.consider_preparse(args)
|
||||||
self._setinitialconftest(args)
|
self._setinitialconftest(args)
|
||||||
self.hook.pytest_addoption(parser=self._parser)
|
self.pluginmanager.do_addoption(self._parser)
|
||||||
|
|
||||||
def _checkversion(self):
|
def _checkversion(self):
|
||||||
minver = self.inicfg.get('minversion', None)
|
minver = self.inicfg.get('minversion', None)
|
||||||
|
@ -426,13 +428,16 @@ def getcfg(args, inibasenames):
|
||||||
args = [x for x in args if str(x)[0] != "-"]
|
args = [x for x in args if str(x)[0] != "-"]
|
||||||
if not args:
|
if not args:
|
||||||
args = [py.path.local()]
|
args = [py.path.local()]
|
||||||
for inibasename in inibasenames:
|
for arg in args:
|
||||||
for p in args:
|
arg = py.path.local(arg)
|
||||||
x = findupwards(p, inibasename)
|
if arg.check():
|
||||||
if x is not None:
|
for base in arg.parts(reverse=True):
|
||||||
iniconfig = py.iniconfig.IniConfig(x)
|
for inibasename in inibasenames:
|
||||||
if 'pytest' in iniconfig.sections:
|
p = base.join(inibasename)
|
||||||
return iniconfig['pytest']
|
if p.check():
|
||||||
|
iniconfig = py.iniconfig.IniConfig(p)
|
||||||
|
if 'pytest' in iniconfig.sections:
|
||||||
|
return iniconfig['pytest']
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def findupwards(current, basename):
|
def findupwards(current, basename):
|
||||||
|
|
|
@ -43,7 +43,8 @@ def showhelp(config):
|
||||||
tw.line("setup.cfg or tox.ini options to be put into [pytest] section:")
|
tw.line("setup.cfg or tox.ini options to be put into [pytest] section:")
|
||||||
tw.line()
|
tw.line()
|
||||||
|
|
||||||
for name, (help, type, default) in sorted(config._parser._inidict.items()):
|
for name in config._parser._ininames:
|
||||||
|
help, type, default = config._parser._inidict[name]
|
||||||
if type is None:
|
if type is None:
|
||||||
type = "string"
|
type = "string"
|
||||||
spec = "%s (%s)" % (name, type)
|
spec = "%s (%s)" % (name, type)
|
||||||
|
|
|
@ -28,7 +28,6 @@ def test_gen(testdir, anypython, standalone):
|
||||||
result = standalone.run(anypython, testdir, p)
|
result = standalone.run(anypython, testdir, p)
|
||||||
assert result.ret != 0
|
assert result.ret != 0
|
||||||
|
|
||||||
@py.test.mark.xfail(reason="fix-dist", run=False)
|
|
||||||
def test_rundist(testdir, pytestconfig, standalone):
|
def test_rundist(testdir, pytestconfig, standalone):
|
||||||
pytestconfig.pluginmanager.skipifmissing("xdist")
|
pytestconfig.pluginmanager.skipifmissing("xdist")
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
|
|
|
@ -418,7 +418,6 @@ class TestTerminalFunctional:
|
||||||
"*test_verbose_reporting.py:10: test_gen*FAIL*",
|
"*test_verbose_reporting.py:10: test_gen*FAIL*",
|
||||||
])
|
])
|
||||||
assert result.ret == 1
|
assert result.ret == 1
|
||||||
pytest.xfail("repair xdist")
|
|
||||||
pytestconfig.pluginmanager.skipifmissing("xdist")
|
pytestconfig.pluginmanager.skipifmissing("xdist")
|
||||||
result = testdir.runpytest(p1, '-v', '-n 1')
|
result = testdir.runpytest(p1, '-v', '-n 1')
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
|
|
|
@ -40,6 +40,30 @@ class TestParseIni:
|
||||||
"*tox.ini:2*requires*9.0*actual*"
|
"*tox.ini:2*requires*9.0*actual*"
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@py.test.mark.multi(name="setup.cfg tox.ini pytest.ini".split())
|
||||||
|
def test_ini_names(self, testdir, name):
|
||||||
|
testdir.tmpdir.join(name).write(py.std.textwrap.dedent("""
|
||||||
|
[pytest]
|
||||||
|
minversion = 1.0
|
||||||
|
"""))
|
||||||
|
config = Config()
|
||||||
|
config.parse([testdir.tmpdir])
|
||||||
|
assert config.getini("minversion") == "1.0"
|
||||||
|
|
||||||
|
def test_toxini_before_lower_pytestini(self, testdir):
|
||||||
|
sub = testdir.tmpdir.mkdir("sub")
|
||||||
|
sub.join("tox.ini").write(py.std.textwrap.dedent("""
|
||||||
|
[pytest]
|
||||||
|
minversion = 2.0
|
||||||
|
"""))
|
||||||
|
testdir.tmpdir.join("pytest.ini").write(py.std.textwrap.dedent("""
|
||||||
|
[pytest]
|
||||||
|
minversion = 1.5
|
||||||
|
"""))
|
||||||
|
config = Config()
|
||||||
|
config.parse([sub])
|
||||||
|
assert config.getini("minversion") == "2.0"
|
||||||
|
|
||||||
@py.test.mark.xfail(reason="probably not needed")
|
@py.test.mark.xfail(reason="probably not needed")
|
||||||
def test_confcutdir(self, testdir):
|
def test_confcutdir(self, testdir):
|
||||||
sub = testdir.mkdir("sub")
|
sub = testdir.mkdir("sub")
|
||||||
|
|
2
tox.ini
2
tox.ini
|
@ -1,6 +1,6 @@
|
||||||
[tox]
|
[tox]
|
||||||
distshare={homedir}/.tox/distshare
|
distshare={homedir}/.tox/distshare
|
||||||
envlist=py26,py27,py31,py27-xdist,py25,py24
|
envlist=py26,py27,py31,py32,py27-xdist,py25,py24
|
||||||
indexserver=
|
indexserver=
|
||||||
default http://pypi.testrun.org
|
default http://pypi.testrun.org
|
||||||
pypi http://pypi.python.org/simple
|
pypi http://pypi.python.org/simple
|
||||||
|
|
Loading…
Reference in New Issue