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,11 +428,14 @@ 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 arg in args: | ||||||
|  |         arg = py.path.local(arg) | ||||||
|  |         if arg.check(): | ||||||
|  |             for base in arg.parts(reverse=True): | ||||||
|                 for inibasename in inibasenames: |                 for inibasename in inibasenames: | ||||||
|         for p in args: |                     p = base.join(inibasename) | ||||||
|             x = findupwards(p, inibasename) |                     if p.check(): | ||||||
|             if x is not None: |                         iniconfig = py.iniconfig.IniConfig(p) | ||||||
|                 iniconfig = py.iniconfig.IniConfig(x) |  | ||||||
|                         if 'pytest' in iniconfig.sections: |                         if 'pytest' in iniconfig.sections: | ||||||
|                             return iniconfig['pytest'] |                             return iniconfig['pytest'] | ||||||
|     return {} |     return {} | ||||||
|  |  | ||||||
|  | @ -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