Merged in hpk42/pytest-hpk/issue486 (pull request #147)
fix issue486: better reporting and handling of early conftest loading failures
This commit is contained in:
commit
7d6317802e
|
@ -48,6 +48,9 @@ NEXT (2.6)
|
||||||
- fix issue493: don't run tests in doc directory with ``python setup.py test``
|
- fix issue493: don't run tests in doc directory with ``python setup.py test``
|
||||||
(use tox -e doctesting for that)
|
(use tox -e doctesting for that)
|
||||||
|
|
||||||
|
- fix issue486: better reporting and handling of early conftest loading failures
|
||||||
|
|
||||||
|
|
||||||
2.5.2
|
2.5.2
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,13 @@ from _pytest import hookspec # the extension point definitions
|
||||||
from _pytest.core import PluginManager
|
from _pytest.core import PluginManager
|
||||||
|
|
||||||
# pytest startup
|
# pytest startup
|
||||||
|
#
|
||||||
|
class ConftestImportFailure(Exception):
|
||||||
|
def __init__(self, path, excinfo):
|
||||||
|
Exception.__init__(self, path, excinfo)
|
||||||
|
self.path = path
|
||||||
|
self.excinfo = excinfo
|
||||||
|
|
||||||
|
|
||||||
def main(args=None, plugins=None):
|
def main(args=None, plugins=None):
|
||||||
""" return exit code, after performing an in-process test run.
|
""" return exit code, after performing an in-process test run.
|
||||||
|
@ -16,8 +23,17 @@ def main(args=None, plugins=None):
|
||||||
:arg plugins: list of plugin objects to be auto-registered during
|
:arg plugins: list of plugin objects to be auto-registered during
|
||||||
initialization.
|
initialization.
|
||||||
"""
|
"""
|
||||||
config = _prepareconfig(args, plugins)
|
try:
|
||||||
return config.hook.pytest_cmdline_main(config=config)
|
config = _prepareconfig(args, plugins)
|
||||||
|
except ConftestImportFailure:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
tw = py.io.TerminalWriter(sys.stderr)
|
||||||
|
for line in py.std.traceback.format_exception(*e.excinfo):
|
||||||
|
tw.line(line.rstrip(), red=True)
|
||||||
|
tw.line("ERROR: could not load %s\n" % (e.path), red=True)
|
||||||
|
return 4
|
||||||
|
else:
|
||||||
|
return config.hook.pytest_cmdline_main(config=config)
|
||||||
|
|
||||||
class cmdline: # compatibility namespace
|
class cmdline: # compatibility namespace
|
||||||
main = staticmethod(main)
|
main = staticmethod(main)
|
||||||
|
@ -86,8 +102,7 @@ class PytestPluginManager(PluginManager):
|
||||||
config.addinivalue_line("markers",
|
config.addinivalue_line("markers",
|
||||||
"trylast: mark a hook implementation function such that the "
|
"trylast: mark a hook implementation function such that the "
|
||||||
"plugin machinery will try to call it last/as late as possible.")
|
"plugin machinery will try to call it last/as late as possible.")
|
||||||
while self._warnings:
|
for warning in self._warnings:
|
||||||
warning = self._warnings.pop(0)
|
|
||||||
config.warn(code="I1", message=warning)
|
config.warn(code="I1", message=warning)
|
||||||
|
|
||||||
|
|
||||||
|
@ -496,7 +511,8 @@ class Conftest(object):
|
||||||
continue
|
continue
|
||||||
conftestpath = parent.join("conftest.py")
|
conftestpath = parent.join("conftest.py")
|
||||||
if conftestpath.check(file=1):
|
if conftestpath.check(file=1):
|
||||||
clist.append(self.importconftest(conftestpath))
|
mod = self.importconftest(conftestpath)
|
||||||
|
clist.append(mod)
|
||||||
self._path2confmods[path] = clist
|
self._path2confmods[path] = clist
|
||||||
return clist
|
return clist
|
||||||
|
|
||||||
|
@ -522,7 +538,11 @@ class Conftest(object):
|
||||||
pkgpath = conftestpath.pypkgpath()
|
pkgpath = conftestpath.pypkgpath()
|
||||||
if pkgpath is None:
|
if pkgpath is None:
|
||||||
_ensure_removed_sysmodule(conftestpath.purebasename)
|
_ensure_removed_sysmodule(conftestpath.purebasename)
|
||||||
self._conftestpath2mod[conftestpath] = mod = conftestpath.pyimport()
|
try:
|
||||||
|
mod = conftestpath.pyimport()
|
||||||
|
except Exception:
|
||||||
|
raise ConftestImportFailure(conftestpath, sys.exc_info())
|
||||||
|
self._conftestpath2mod[conftestpath] = mod
|
||||||
dirpath = conftestpath.dirpath()
|
dirpath = conftestpath.dirpath()
|
||||||
if dirpath in self._path2confmods:
|
if dirpath in self._path2confmods:
|
||||||
for path, mods in self._path2confmods.items():
|
for path, mods in self._path2confmods.items():
|
||||||
|
@ -682,9 +702,19 @@ class Config(object):
|
||||||
self.pluginmanager.consider_preparse(args)
|
self.pluginmanager.consider_preparse(args)
|
||||||
self.pluginmanager.consider_setuptools_entrypoints()
|
self.pluginmanager.consider_setuptools_entrypoints()
|
||||||
self.pluginmanager.consider_env()
|
self.pluginmanager.consider_env()
|
||||||
self.known_args_namespace = self._parser.parse_known_args(args)
|
self.known_args_namespace = ns = self._parser.parse_known_args(args)
|
||||||
self.hook.pytest_load_initial_conftests(early_config=self,
|
try:
|
||||||
args=args, parser=self._parser)
|
self.hook.pytest_load_initial_conftests(early_config=self,
|
||||||
|
args=args, parser=self._parser)
|
||||||
|
except ConftestImportFailure:
|
||||||
|
e = sys.exc_info()[1]
|
||||||
|
if ns.help or ns.version:
|
||||||
|
# we don't want to prevent --help/--version to work
|
||||||
|
# so just let is pass and print a warning at the end
|
||||||
|
self.pluginmanager._warnings.append(
|
||||||
|
"could not load initial conftests (%s)\n" % e.path)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
def _checkversion(self):
|
def _checkversion(self):
|
||||||
import pytest
|
import pytest
|
||||||
|
|
|
@ -86,17 +86,9 @@ def showhelp(config):
|
||||||
tw.line("(shown according to specified file_or_dir or current dir "
|
tw.line("(shown according to specified file_or_dir or current dir "
|
||||||
"if not specified)")
|
"if not specified)")
|
||||||
for warning in config.pluginmanager._warnings:
|
for warning in config.pluginmanager._warnings:
|
||||||
tw.line("warning: %s" % (warning,))
|
tw.line("warning: %s" % (warning,), red=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
tw.line("conftest.py options:")
|
|
||||||
tw.line()
|
|
||||||
conftestitems = sorted(config._parser._conftestdict.items())
|
|
||||||
for name, help in conftest_options + conftestitems:
|
|
||||||
line = " %-15s %s" %(name, help)
|
|
||||||
tw.line(line[:tw.fullwidth])
|
|
||||||
tw.line()
|
|
||||||
#tw.sep( "=")
|
|
||||||
|
|
||||||
conftest_options = [
|
conftest_options = [
|
||||||
('pytest_plugins', 'list of plugin names to load'),
|
('pytest_plugins', 'list of plugin names to load'),
|
||||||
|
|
|
@ -124,6 +124,18 @@ class TestGeneralUsage:
|
||||||
"*ERROR: not found:*%s" %(p2.basename,)
|
"*ERROR: not found:*%s" %(p2.basename,)
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_issue486_better_reporting_on_conftest_load_failure(self, testdir):
|
||||||
|
testdir.makepyfile("")
|
||||||
|
testdir.makeconftest("import qwerty")
|
||||||
|
result = testdir.runpytest("--help")
|
||||||
|
result.stdout.fnmatch_lines("""
|
||||||
|
*--version*
|
||||||
|
*warning*conftest.py*
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest()
|
||||||
|
result.stderr.fnmatch_lines("""
|
||||||
|
*ERROR*could not load*conftest.py*
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
def test_early_skip(self, testdir):
|
def test_early_skip(self, testdir):
|
||||||
|
|
Loading…
Reference in New Issue