- refine lsof checking
- make runpytest() create an inline testing process instead of a subprocess one --HG-- branch : testrefactor
This commit is contained in:
parent
d3e363b97a
commit
a8afba054a
|
@ -38,8 +38,11 @@ def main(args=None, plugins=None):
|
||||||
tw.line("ERROR: could not load %s\n" % (e.path), red=True)
|
tw.line("ERROR: could not load %s\n" % (e.path), red=True)
|
||||||
return 4
|
return 4
|
||||||
else:
|
else:
|
||||||
|
try:
|
||||||
config.pluginmanager.check_pending()
|
config.pluginmanager.check_pending()
|
||||||
return config.hook.pytest_cmdline_main(config=config)
|
return config.hook.pytest_cmdline_main(config=config)
|
||||||
|
finally:
|
||||||
|
config._ensure_unconfigure()
|
||||||
except UsageError as e:
|
except UsageError as e:
|
||||||
for msg in e.args:
|
for msg in e.args:
|
||||||
sys.stderr.write("ERROR: %s\n" %(msg,))
|
sys.stderr.write("ERROR: %s\n" %(msg,))
|
||||||
|
@ -85,12 +88,18 @@ def _prepareconfig(args=None, plugins=None):
|
||||||
if not isinstance(args, str):
|
if not isinstance(args, str):
|
||||||
raise ValueError("not a string or argument list: %r" % (args,))
|
raise ValueError("not a string or argument list: %r" % (args,))
|
||||||
args = shlex.split(args)
|
args = shlex.split(args)
|
||||||
pluginmanager = get_config().pluginmanager
|
config = get_config()
|
||||||
|
pluginmanager = config.pluginmanager
|
||||||
|
try:
|
||||||
if plugins:
|
if plugins:
|
||||||
for plugin in plugins:
|
for plugin in plugins:
|
||||||
pluginmanager.register(plugin)
|
pluginmanager.register(plugin)
|
||||||
return pluginmanager.hook.pytest_cmdline_parse(
|
return pluginmanager.hook.pytest_cmdline_parse(
|
||||||
pluginmanager=pluginmanager, args=args)
|
pluginmanager=pluginmanager, args=args)
|
||||||
|
except BaseException:
|
||||||
|
config._ensure_unconfigure()
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
def exclude_pytest_names(name):
|
def exclude_pytest_names(name):
|
||||||
return not name.startswith(name) or name == "pytest_plugins" or \
|
return not name.startswith(name) or name == "pytest_plugins" or \
|
||||||
|
@ -263,7 +272,10 @@ class PytestPluginManager(PluginManager):
|
||||||
|
|
||||||
def consider_pluginarg(self, arg):
|
def consider_pluginarg(self, arg):
|
||||||
if arg.startswith("no:"):
|
if arg.startswith("no:"):
|
||||||
self.set_blocked(arg[3:])
|
name = arg[3:]
|
||||||
|
self.set_blocked(name)
|
||||||
|
if not name.startswith("pytest_"):
|
||||||
|
self.set_blocked("pytest_" + name)
|
||||||
else:
|
else:
|
||||||
self.import_plugin(arg)
|
self.import_plugin(arg)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
""" (disabled by default) support for testing pytest and pytest plugins. """
|
""" (disabled by default) support for testing pytest and pytest plugins. """
|
||||||
import sys
|
import sys
|
||||||
|
import traceback
|
||||||
import os
|
import os
|
||||||
import codecs
|
import codecs
|
||||||
import re
|
import re
|
||||||
|
@ -287,7 +288,8 @@ class TmpTestdir:
|
||||||
break
|
break
|
||||||
self.tmpdir = tmpdir
|
self.tmpdir = tmpdir
|
||||||
self.plugins = []
|
self.plugins = []
|
||||||
self._savesyspath = list(sys.path)
|
self._savesyspath = (list(sys.path), list(sys.meta_path))
|
||||||
|
self._savemodulekeys = set(sys.modules)
|
||||||
self.chdir() # always chdir
|
self.chdir() # always chdir
|
||||||
self.request.addfinalizer(self.finalize)
|
self.request.addfinalizer(self.finalize)
|
||||||
|
|
||||||
|
@ -303,22 +305,22 @@ class TmpTestdir:
|
||||||
has finished.
|
has finished.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
sys.path[:] = self._savesyspath
|
sys.path[:], sys.meta_path[:] = self._savesyspath
|
||||||
if hasattr(self, '_olddir'):
|
if hasattr(self, '_olddir'):
|
||||||
self._olddir.chdir()
|
self._olddir.chdir()
|
||||||
self.delete_loaded_modules()
|
self.delete_loaded_modules()
|
||||||
|
|
||||||
def delete_loaded_modules(self):
|
def delete_loaded_modules(self):
|
||||||
"""Delete modules that have been loaded from tmpdir.
|
"""Delete modules that have been loaded during a test.
|
||||||
|
|
||||||
This allows the interpreter to catch module changes in case
|
This allows the interpreter to catch module changes in case
|
||||||
the module is re-imported.
|
the module is re-imported.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
for name, mod in list(sys.modules.items()):
|
for name in set(sys.modules).difference(self._savemodulekeys):
|
||||||
if mod:
|
# it seems zope.interfaces is keeping some state
|
||||||
fn = getattr(mod, '__file__', None)
|
# (used by twisted related tests)
|
||||||
if fn and fn.startswith(str(self.tmpdir)):
|
if name != "zope.interface":
|
||||||
del sys.modules[name]
|
del sys.modules[name]
|
||||||
|
|
||||||
def make_hook_recorder(self, pluginmanager):
|
def make_hook_recorder(self, pluginmanager):
|
||||||
|
@ -584,16 +586,27 @@ class TmpTestdir:
|
||||||
reprec.ret = ret
|
reprec.ret = ret
|
||||||
return reprec
|
return reprec
|
||||||
|
|
||||||
def inline_runpytest(self, *args):
|
def inline_runpytest(self, *args, **kwargs):
|
||||||
""" Return result of running pytest in-process, providing a similar
|
""" Return result of running pytest in-process, providing a similar
|
||||||
interface to what self.runpytest() provides. """
|
interface to what self.runpytest() provides. """
|
||||||
|
if kwargs.get("syspathinsert"):
|
||||||
|
self.syspathinsert()
|
||||||
now = time.time()
|
now = time.time()
|
||||||
capture = py.io.StdCaptureFD()
|
capture = py.io.StdCapture()
|
||||||
|
try:
|
||||||
try:
|
try:
|
||||||
reprec = self.inline_run(*args)
|
reprec = self.inline_run(*args)
|
||||||
|
except SystemExit as e:
|
||||||
|
class reprec:
|
||||||
|
ret = e.args[0]
|
||||||
|
except Exception:
|
||||||
|
traceback.print_exc()
|
||||||
|
class reprec:
|
||||||
|
ret = 3
|
||||||
finally:
|
finally:
|
||||||
out, err = capture.reset()
|
out, err = capture.reset()
|
||||||
assert out or err
|
sys.stdout.write(out)
|
||||||
|
sys.stderr.write(err)
|
||||||
|
|
||||||
res = RunResult(reprec.ret,
|
res = RunResult(reprec.ret,
|
||||||
out.split("\n"), err.split("\n"),
|
out.split("\n"), err.split("\n"),
|
||||||
|
@ -601,6 +614,9 @@ class TmpTestdir:
|
||||||
res.reprec = reprec
|
res.reprec = reprec
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def runpytest(self, *args, **kwargs):
|
||||||
|
return self.inline_runpytest(*args, **kwargs)
|
||||||
|
|
||||||
def parseconfig(self, *args):
|
def parseconfig(self, *args):
|
||||||
"""Return a new py.test Config instance from given commandline args.
|
"""Return a new py.test Config instance from given commandline args.
|
||||||
|
|
||||||
|
@ -822,7 +838,7 @@ class TmpTestdir:
|
||||||
command = self._getsysprepend() + command
|
command = self._getsysprepend() + command
|
||||||
return self.run(sys.executable, "-c", command)
|
return self.run(sys.executable, "-c", command)
|
||||||
|
|
||||||
def runpytest(self, *args):
|
def runpytest_subprocess(self, *args):
|
||||||
"""Run py.test as a subprocess with given arguments.
|
"""Run py.test as a subprocess with given arguments.
|
||||||
|
|
||||||
Any plugins added to the :py:attr:`plugins` list will added
|
Any plugins added to the :py:attr:`plugins` list will added
|
||||||
|
|
|
@ -7,7 +7,7 @@ def test_failure_demo_fails_properly(testdir):
|
||||||
target = testdir.tmpdir.join(failure_demo.basename)
|
target = testdir.tmpdir.join(failure_demo.basename)
|
||||||
failure_demo.copy(target)
|
failure_demo.copy(target)
|
||||||
failure_demo.copy(testdir.tmpdir.join(failure_demo.basename))
|
failure_demo.copy(testdir.tmpdir.join(failure_demo.basename))
|
||||||
result = testdir.runpytest(target)
|
result = testdir.runpytest(target, syspathinsert=True)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*42 failed*"
|
"*42 failed*"
|
||||||
])
|
])
|
||||||
|
|
|
@ -82,7 +82,7 @@ class TestGeneralUsage:
|
||||||
def test_option(pytestconfig):
|
def test_option(pytestconfig):
|
||||||
assert pytestconfig.option.xyz == "123"
|
assert pytestconfig.option.xyz == "123"
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest("-p", "pytest_xyz", "--xyz=123")
|
result = testdir.runpytest("-p", "pytest_xyz", "--xyz=123", syspathinsert=True)
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
'*1 passed*',
|
'*1 passed*',
|
||||||
|
@ -353,7 +353,8 @@ class TestGeneralUsage:
|
||||||
*unrecognized*
|
*unrecognized*
|
||||||
""")
|
""")
|
||||||
|
|
||||||
def test_getsourcelines_error_issue553(self, testdir):
|
def test_getsourcelines_error_issue553(self, testdir, monkeypatch):
|
||||||
|
monkeypatch.setattr("inspect.getsourcelines", None)
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
def raise_error(obj):
|
def raise_error(obj):
|
||||||
raise IOError('source code not available')
|
raise IOError('source code not available')
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import pytest
|
import pytest
|
||||||
import sys
|
import sys
|
||||||
|
import gc
|
||||||
|
|
||||||
pytest_plugins = "pytester",
|
pytest_plugins = "pytester",
|
||||||
|
|
||||||
|
@ -17,8 +18,8 @@ class LsofFdLeakChecker(object):
|
||||||
|
|
||||||
def _parse_lsof_output(self, out):
|
def _parse_lsof_output(self, out):
|
||||||
def isopen(line):
|
def isopen(line):
|
||||||
return line.startswith('f') and (
|
return line.startswith('f') and ("deleted" not in line and
|
||||||
"deleted" not in line and 'mem' not in line and "txt" not in line and 'cwd' not in line)
|
'mem' not in line and "txt" not in line and 'cwd' not in line)
|
||||||
|
|
||||||
open_files = []
|
open_files = []
|
||||||
|
|
||||||
|
@ -32,46 +33,49 @@ class LsofFdLeakChecker(object):
|
||||||
|
|
||||||
return open_files
|
return open_files
|
||||||
|
|
||||||
|
def matching_platform(self):
|
||||||
|
try:
|
||||||
|
py.process.cmdexec("lsof -v")
|
||||||
|
except py.process.cmdexec.Error:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
@pytest.hookimpl_opts(hookwrapper=True, tryfirst=True)
|
||||||
|
def pytest_runtest_item(self, item):
|
||||||
|
lines1 = self.get_open_files()
|
||||||
|
yield
|
||||||
|
if hasattr(sys, "pypy_version_info"):
|
||||||
|
gc.collect()
|
||||||
|
lines2 = self.get_open_files()
|
||||||
|
|
||||||
|
new_fds = set([t[0] for t in lines2]) - set([t[0] for t in lines1])
|
||||||
|
leaked_files = [t for t in lines2 if t[0] in new_fds]
|
||||||
|
if leaked_files:
|
||||||
|
error = []
|
||||||
|
error.append("***** %s FD leakage detected" % len(leaked_files))
|
||||||
|
error.extend([str(f) for f in leaked_files])
|
||||||
|
error.append("*** Before:")
|
||||||
|
error.extend([str(f) for f in lines1])
|
||||||
|
error.append("*** After:")
|
||||||
|
error.extend([str(f) for f in lines2])
|
||||||
|
error.append(error[0])
|
||||||
|
error.append("*** function %s:%s: %s " % item.location)
|
||||||
|
pytest.fail("\n".join(error), pytrace=False)
|
||||||
|
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
parser.addoption('--lsof',
|
parser.addoption('--lsof',
|
||||||
action="store_true", dest="lsof", default=False,
|
action="store_true", dest="lsof", default=False,
|
||||||
help=("run FD checks if lsof is available"))
|
help=("run FD checks if lsof is available"))
|
||||||
|
|
||||||
def pytest_runtest_setup(item):
|
|
||||||
config = item.config
|
def pytest_configure(config):
|
||||||
config._basedir = py.path.local()
|
|
||||||
if config.getvalue("lsof"):
|
if config.getvalue("lsof"):
|
||||||
try:
|
checker = LsofFdLeakChecker()
|
||||||
config._fd_leak_checker = LsofFdLeakChecker()
|
if checker.matching_platform():
|
||||||
config._openfiles = config._fd_leak_checker.get_open_files()
|
config.pluginmanager.register(checker)
|
||||||
except py.process.cmdexec.Error:
|
|
||||||
pass
|
|
||||||
|
|
||||||
#def pytest_report_header():
|
|
||||||
# return "pid: %s" % os.getpid()
|
|
||||||
|
|
||||||
def check_open_files(config):
|
|
||||||
lines2 = config._fd_leak_checker.get_open_files()
|
|
||||||
new_fds = set([t[0] for t in lines2]) - set([t[0] for t in config._openfiles])
|
|
||||||
open_files = [t for t in lines2 if t[0] in new_fds]
|
|
||||||
if open_files:
|
|
||||||
error = []
|
|
||||||
error.append("***** %s FD leakage detected" % len(open_files))
|
|
||||||
error.extend([str(f) for f in open_files])
|
|
||||||
error.append("*** Before:")
|
|
||||||
error.extend([str(f) for f in config._openfiles])
|
|
||||||
error.append("*** After:")
|
|
||||||
error.extend([str(f) for f in lines2])
|
|
||||||
error.append(error[0])
|
|
||||||
raise AssertionError("\n".join(error))
|
|
||||||
|
|
||||||
@pytest.hookimpl_opts(hookwrapper=True, trylast=True)
|
|
||||||
def pytest_runtest_teardown(item):
|
|
||||||
yield
|
|
||||||
item.config._basedir.chdir()
|
|
||||||
if hasattr(item.config, '_openfiles'):
|
|
||||||
check_open_files(item.config)
|
|
||||||
|
|
||||||
# XXX copied from execnet's conftest.py - needs to be merged
|
# XXX copied from execnet's conftest.py - needs to be merged
|
||||||
winpymap = {
|
winpymap = {
|
||||||
|
|
|
@ -626,10 +626,8 @@ def test_setup_only_available_in_subdir(testdir):
|
||||||
"""))
|
"""))
|
||||||
sub1.join("test_in_sub1.py").write("def test_1(): pass")
|
sub1.join("test_in_sub1.py").write("def test_1(): pass")
|
||||||
sub2.join("test_in_sub2.py").write("def test_2(): pass")
|
sub2.join("test_in_sub2.py").write("def test_2(): pass")
|
||||||
result = testdir.inline_runpytest("-v", "-s")
|
result = testdir.runpytest("-v", "-s")
|
||||||
result.stdout.fnmatch_lines([
|
result.assert_outcomes(passed=2)
|
||||||
"*2 passed*"
|
|
||||||
])
|
|
||||||
|
|
||||||
def test_modulecol_roundtrip(testdir):
|
def test_modulecol_roundtrip(testdir):
|
||||||
modcol = testdir.getmodulecol("pass", withinit=True)
|
modcol = testdir.getmodulecol("pass", withinit=True)
|
||||||
|
|
|
@ -99,10 +99,8 @@ class TestFillFixtures:
|
||||||
|
|
||||||
sub1.join("test_in_sub1.py").write("def test_1(arg1): pass")
|
sub1.join("test_in_sub1.py").write("def test_1(arg1): pass")
|
||||||
sub2.join("test_in_sub2.py").write("def test_2(arg2): pass")
|
sub2.join("test_in_sub2.py").write("def test_2(arg2): pass")
|
||||||
result = testdir.inline_runpytest("-v")
|
result = testdir.runpytest("-v")
|
||||||
result.stdout.fnmatch_lines([
|
result.assert_outcomes(passed=2)
|
||||||
"*2 passed*"
|
|
||||||
])
|
|
||||||
|
|
||||||
def test_extend_fixture_module_class(self, testdir):
|
def test_extend_fixture_module_class(self, testdir):
|
||||||
testfile = testdir.makepyfile("""
|
testfile = testdir.makepyfile("""
|
||||||
|
|
|
@ -663,7 +663,7 @@ class TestMetafuncFunctional:
|
||||||
"""))
|
"""))
|
||||||
sub1.join("test_in_sub1.py").write("def test_1(): pass")
|
sub1.join("test_in_sub1.py").write("def test_1(): pass")
|
||||||
sub2.join("test_in_sub2.py").write("def test_2(): pass")
|
sub2.join("test_in_sub2.py").write("def test_2(): pass")
|
||||||
result = testdir.inline_runpytest("-v", "-s", sub1, sub2, sub1)
|
result = testdir.runpytest("-v", "-s", sub1, sub2, sub1)
|
||||||
result.assert_outcomes(passed=3)
|
result.assert_outcomes(passed=3)
|
||||||
|
|
||||||
def test_generate_same_function_names_issue403(self, testdir):
|
def test_generate_same_function_names_issue403(self, testdir):
|
||||||
|
|
|
@ -451,7 +451,7 @@ def test_assertion_options(testdir):
|
||||||
x = 3
|
x = 3
|
||||||
assert x == 4
|
assert x == 4
|
||||||
""")
|
""")
|
||||||
result = testdir.inline_runpytest()
|
result = testdir.runpytest()
|
||||||
assert "3 == 4" in result.stdout.str()
|
assert "3 == 4" in result.stdout.str()
|
||||||
off_options = (("--no-assert",),
|
off_options = (("--no-assert",),
|
||||||
("--nomagic",),
|
("--nomagic",),
|
||||||
|
@ -461,7 +461,7 @@ def test_assertion_options(testdir):
|
||||||
("--assert=plain", "--nomagic"),
|
("--assert=plain", "--nomagic"),
|
||||||
("--assert=plain", "--no-assert", "--nomagic"))
|
("--assert=plain", "--no-assert", "--nomagic"))
|
||||||
for opt in off_options:
|
for opt in off_options:
|
||||||
result = testdir.runpytest(*opt)
|
result = testdir.runpytest_subprocess(*opt)
|
||||||
assert "3 == 4" not in result.stdout.str()
|
assert "3 == 4" not in result.stdout.str()
|
||||||
|
|
||||||
def test_old_assert_mode(testdir):
|
def test_old_assert_mode(testdir):
|
||||||
|
@ -469,7 +469,7 @@ def test_old_assert_mode(testdir):
|
||||||
def test_in_old_mode():
|
def test_in_old_mode():
|
||||||
assert "@py_builtins" not in globals()
|
assert "@py_builtins" not in globals()
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest("--assert=reinterp")
|
result = testdir.runpytest_subprocess("--assert=reinterp")
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
|
|
||||||
def test_triple_quoted_string_issue113(testdir):
|
def test_triple_quoted_string_issue113(testdir):
|
||||||
|
|
|
@ -453,7 +453,7 @@ def test_rewritten():
|
||||||
assert not os.path.exists(__cached__)
|
assert not os.path.exists(__cached__)
|
||||||
assert not os.path.exists(os.path.dirname(__cached__))""")
|
assert not os.path.exists(os.path.dirname(__cached__))""")
|
||||||
monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", "1")
|
monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", "1")
|
||||||
assert testdir.runpytest().ret == 0
|
assert testdir.runpytest_subprocess().ret == 0
|
||||||
|
|
||||||
@pytest.mark.skipif('"__pypy__" in sys.modules')
|
@pytest.mark.skipif('"__pypy__" in sys.modules')
|
||||||
def test_pyc_vs_pyo(self, testdir, monkeypatch):
|
def test_pyc_vs_pyo(self, testdir, monkeypatch):
|
||||||
|
@ -615,10 +615,8 @@ class TestAssertionRewriteHookDetails(object):
|
||||||
testdir.makepyfile(**contents)
|
testdir.makepyfile(**contents)
|
||||||
testdir.maketxtfile(**{'testpkg/resource': "Load me please."})
|
testdir.maketxtfile(**{'testpkg/resource': "Load me please."})
|
||||||
|
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest_subprocess()
|
||||||
result.stdout.fnmatch_lines([
|
result.assert_outcomes(passed=1)
|
||||||
'* 1 passed*',
|
|
||||||
])
|
|
||||||
|
|
||||||
def test_read_pyc(self, tmpdir):
|
def test_read_pyc(self, tmpdir):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -121,7 +121,7 @@ def test_capturing_unicode(testdir, method):
|
||||||
print (sys.stdout)
|
print (sys.stdout)
|
||||||
print (%s)
|
print (%s)
|
||||||
""" % obj)
|
""" % obj)
|
||||||
result = testdir.runpytest("--capture=%s" % method)
|
result = testdir.runpytest_subprocess("--capture=%s" % method)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*1 passed*"
|
"*1 passed*"
|
||||||
])
|
])
|
||||||
|
@ -133,7 +133,7 @@ def test_capturing_bytes_in_utf8_encoding(testdir, method):
|
||||||
def test_unicode():
|
def test_unicode():
|
||||||
print ('b\\u00f6y')
|
print ('b\\u00f6y')
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest("--capture=%s" % method)
|
result = testdir.runpytest_subprocess("--capture=%s" % method)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*1 passed*"
|
"*1 passed*"
|
||||||
])
|
])
|
||||||
|
@ -144,7 +144,7 @@ def test_collect_capturing(testdir):
|
||||||
print ("collect %s failure" % 13)
|
print ("collect %s failure" % 13)
|
||||||
import xyz42123
|
import xyz42123
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p)
|
result = testdir.runpytest_subprocess(p)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*Captured stdout*",
|
"*Captured stdout*",
|
||||||
"*collect 13 failure*",
|
"*collect 13 failure*",
|
||||||
|
@ -165,7 +165,7 @@ class TestPerTestCapturing:
|
||||||
print ("in func2")
|
print ("in func2")
|
||||||
assert 0
|
assert 0
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p)
|
result = testdir.runpytest_subprocess(p)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"setup module*",
|
"setup module*",
|
||||||
"setup test_func1*",
|
"setup test_func1*",
|
||||||
|
@ -188,7 +188,7 @@ class TestPerTestCapturing:
|
||||||
def teardown_function(func):
|
def teardown_function(func):
|
||||||
print ("in teardown")
|
print ("in teardown")
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p)
|
result = testdir.runpytest_subprocess(p)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*test_func():*",
|
"*test_func():*",
|
||||||
"*Captured stdout during setup*",
|
"*Captured stdout during setup*",
|
||||||
|
@ -206,7 +206,7 @@ class TestPerTestCapturing:
|
||||||
print ("in func2")
|
print ("in func2")
|
||||||
assert 0
|
assert 0
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p)
|
result = testdir.runpytest_subprocess(p)
|
||||||
s = result.stdout.str()
|
s = result.stdout.str()
|
||||||
assert "in func1" not in s
|
assert "in func1" not in s
|
||||||
assert "in func2" in s
|
assert "in func2" in s
|
||||||
|
@ -222,7 +222,7 @@ class TestPerTestCapturing:
|
||||||
print ("in func1")
|
print ("in func1")
|
||||||
pass
|
pass
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p)
|
result = testdir.runpytest_subprocess(p)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
'*teardown_function*',
|
'*teardown_function*',
|
||||||
'*Captured stdout*',
|
'*Captured stdout*',
|
||||||
|
@ -240,7 +240,7 @@ class TestPerTestCapturing:
|
||||||
def test_func():
|
def test_func():
|
||||||
pass
|
pass
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p)
|
result = testdir.runpytest_subprocess(p)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*def teardown_module(mod):*",
|
"*def teardown_module(mod):*",
|
||||||
"*Captured stdout*",
|
"*Captured stdout*",
|
||||||
|
@ -259,7 +259,7 @@ class TestPerTestCapturing:
|
||||||
sys.stderr.write(str(2))
|
sys.stderr.write(str(2))
|
||||||
raise ValueError
|
raise ValueError
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p1)
|
result = testdir.runpytest_subprocess(p1)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*test_capturing_outerr.py .F",
|
"*test_capturing_outerr.py .F",
|
||||||
"====* FAILURES *====",
|
"====* FAILURES *====",
|
||||||
|
@ -282,7 +282,7 @@ class TestLoggingInteraction:
|
||||||
logging.basicConfig(stream=stream)
|
logging.basicConfig(stream=stream)
|
||||||
stream.close() # to free memory/release resources
|
stream.close() # to free memory/release resources
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p)
|
result = testdir.runpytest_subprocess(p)
|
||||||
result.stderr.str().find("atexit") == -1
|
result.stderr.str().find("atexit") == -1
|
||||||
|
|
||||||
def test_logging_and_immediate_setupteardown(self, testdir):
|
def test_logging_and_immediate_setupteardown(self, testdir):
|
||||||
|
@ -301,7 +301,7 @@ class TestLoggingInteraction:
|
||||||
""")
|
""")
|
||||||
for optargs in (('--capture=sys',), ('--capture=fd',)):
|
for optargs in (('--capture=sys',), ('--capture=fd',)):
|
||||||
print (optargs)
|
print (optargs)
|
||||||
result = testdir.runpytest(p, *optargs)
|
result = testdir.runpytest_subprocess(p, *optargs)
|
||||||
s = result.stdout.str()
|
s = result.stdout.str()
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*WARN*hello3", # errors show first!
|
"*WARN*hello3", # errors show first!
|
||||||
|
@ -327,7 +327,7 @@ class TestLoggingInteraction:
|
||||||
""")
|
""")
|
||||||
for optargs in (('--capture=sys',), ('--capture=fd',)):
|
for optargs in (('--capture=sys',), ('--capture=fd',)):
|
||||||
print (optargs)
|
print (optargs)
|
||||||
result = testdir.runpytest(p, *optargs)
|
result = testdir.runpytest_subprocess(p, *optargs)
|
||||||
s = result.stdout.str()
|
s = result.stdout.str()
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*WARN*hello3", # errors come first
|
"*WARN*hello3", # errors come first
|
||||||
|
@ -348,7 +348,7 @@ class TestLoggingInteraction:
|
||||||
logging.warn("hello432")
|
logging.warn("hello432")
|
||||||
assert 0
|
assert 0
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(
|
result = testdir.runpytest_subprocess(
|
||||||
p, "--traceconfig",
|
p, "--traceconfig",
|
||||||
"-p", "no:capturelog")
|
"-p", "no:capturelog")
|
||||||
assert result.ret != 0
|
assert result.ret != 0
|
||||||
|
@ -364,7 +364,7 @@ class TestLoggingInteraction:
|
||||||
logging.warn("hello435")
|
logging.warn("hello435")
|
||||||
""")
|
""")
|
||||||
# make sure that logging is still captured in tests
|
# make sure that logging is still captured in tests
|
||||||
result = testdir.runpytest("-s", "-p", "no:capturelog")
|
result = testdir.runpytest_subprocess("-s", "-p", "no:capturelog")
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
result.stderr.fnmatch_lines([
|
result.stderr.fnmatch_lines([
|
||||||
"WARNING*hello435*",
|
"WARNING*hello435*",
|
||||||
|
@ -383,7 +383,7 @@ class TestLoggingInteraction:
|
||||||
logging.warn("hello433")
|
logging.warn("hello433")
|
||||||
assert 0
|
assert 0
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p, "-p", "no:capturelog")
|
result = testdir.runpytest_subprocess(p, "-p", "no:capturelog")
|
||||||
assert result.ret != 0
|
assert result.ret != 0
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"WARNING*hello433*",
|
"WARNING*hello433*",
|
||||||
|
@ -410,7 +410,7 @@ class TestCaptureFixture:
|
||||||
def test_two(capfd, capsys):
|
def test_two(capfd, capsys):
|
||||||
pass
|
pass
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p)
|
result = testdir.runpytest_subprocess(p)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*ERROR*setup*test_one*",
|
"*ERROR*setup*test_one*",
|
||||||
"*capsys*capfd*same*time*",
|
"*capsys*capfd*same*time*",
|
||||||
|
@ -425,7 +425,7 @@ class TestCaptureFixture:
|
||||||
print ("xxx42xxx")
|
print ("xxx42xxx")
|
||||||
assert 0
|
assert 0
|
||||||
""" % method)
|
""" % method)
|
||||||
result = testdir.runpytest(p)
|
result = testdir.runpytest_subprocess(p)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"xxx42xxx",
|
"xxx42xxx",
|
||||||
])
|
])
|
||||||
|
@ -447,7 +447,7 @@ class TestCaptureFixture:
|
||||||
def test_hello(capsys, missingarg):
|
def test_hello(capsys, missingarg):
|
||||||
pass
|
pass
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p)
|
result = testdir.runpytest_subprocess(p)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*test_partial_setup_failure*",
|
"*test_partial_setup_failure*",
|
||||||
"*1 error*",
|
"*1 error*",
|
||||||
|
@ -461,7 +461,7 @@ class TestCaptureFixture:
|
||||||
os.write(1, str(42).encode('ascii'))
|
os.write(1, str(42).encode('ascii'))
|
||||||
raise KeyboardInterrupt()
|
raise KeyboardInterrupt()
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p)
|
result = testdir.runpytest_subprocess(p)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*KeyboardInterrupt*"
|
"*KeyboardInterrupt*"
|
||||||
])
|
])
|
||||||
|
@ -474,7 +474,7 @@ class TestCaptureFixture:
|
||||||
def test_log(capsys):
|
def test_log(capsys):
|
||||||
logging.error('x')
|
logging.error('x')
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p)
|
result = testdir.runpytest_subprocess(p)
|
||||||
assert 'closed' not in result.stderr.str()
|
assert 'closed' not in result.stderr.str()
|
||||||
|
|
||||||
|
|
||||||
|
@ -485,7 +485,7 @@ def test_setup_failure_does_not_kill_capturing(testdir):
|
||||||
raise ValueError(42)
|
raise ValueError(42)
|
||||||
"""))
|
"""))
|
||||||
sub1.join("test_mod.py").write("def test_func1(): pass")
|
sub1.join("test_mod.py").write("def test_func1(): pass")
|
||||||
result = testdir.runpytest(testdir.tmpdir, '--traceconfig')
|
result = testdir.runpytest_subprocess(testdir.tmpdir, '--traceconfig')
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*ValueError(42)*",
|
"*ValueError(42)*",
|
||||||
"*1 error*"
|
"*1 error*"
|
||||||
|
@ -500,7 +500,7 @@ def test_fdfuncarg_skips_on_no_osdup(testdir):
|
||||||
def test_hello(capfd):
|
def test_hello(capfd):
|
||||||
pass
|
pass
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest("--capture=no")
|
result = testdir.runpytest_subprocess("--capture=no")
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*1 skipped*"
|
"*1 skipped*"
|
||||||
])
|
])
|
||||||
|
@ -512,7 +512,7 @@ def test_capture_conftest_runtest_setup(testdir):
|
||||||
print ("hello19")
|
print ("hello19")
|
||||||
""")
|
""")
|
||||||
testdir.makepyfile("def test_func(): pass")
|
testdir.makepyfile("def test_func(): pass")
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest_subprocess()
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
assert 'hello19' not in result.stdout.str()
|
assert 'hello19' not in result.stdout.str()
|
||||||
|
|
||||||
|
@ -526,7 +526,7 @@ def test_capture_badoutput_issue412(testdir):
|
||||||
os.write(1, omg)
|
os.write(1, omg)
|
||||||
assert 0
|
assert 0
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest('--cap=fd')
|
result = testdir.runpytest_subprocess('--cap=fd')
|
||||||
result.stdout.fnmatch_lines('''
|
result.stdout.fnmatch_lines('''
|
||||||
*def test_func*
|
*def test_func*
|
||||||
*assert 0*
|
*assert 0*
|
||||||
|
@ -541,7 +541,7 @@ def test_capture_early_option_parsing(testdir):
|
||||||
print ("hello19")
|
print ("hello19")
|
||||||
""")
|
""")
|
||||||
testdir.makepyfile("def test_func(): pass")
|
testdir.makepyfile("def test_func(): pass")
|
||||||
result = testdir.runpytest("-vs")
|
result = testdir.runpytest_subprocess("-vs")
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
assert 'hello19' in result.stdout.str()
|
assert 'hello19' in result.stdout.str()
|
||||||
|
|
||||||
|
@ -562,7 +562,7 @@ def test_capture_binary_output(testdir):
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
test_foo()
|
test_foo()
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest('--assert=plain')
|
result = testdir.runpytest_subprocess('--assert=plain')
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
'*2 passed*',
|
'*2 passed*',
|
||||||
])
|
])
|
||||||
|
@ -885,7 +885,7 @@ class TestStdCaptureFD(TestStdCapture):
|
||||||
os.write(1, "hello\\n".encode("ascii"))
|
os.write(1, "hello\\n".encode("ascii"))
|
||||||
assert 0
|
assert 0
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest_subprocess()
|
||||||
result.stdout.fnmatch_lines("""
|
result.stdout.fnmatch_lines("""
|
||||||
*test_x*
|
*test_x*
|
||||||
*assert 0*
|
*assert 0*
|
||||||
|
@ -936,7 +936,7 @@ class TestStdCaptureFDinvalidFD:
|
||||||
cap = StdCaptureFD(out=False, err=False, in_=True)
|
cap = StdCaptureFD(out=False, err=False, in_=True)
|
||||||
cap.stop_capturing()
|
cap.stop_capturing()
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest("--capture=fd")
|
result = testdir.runpytest_subprocess("--capture=fd")
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
assert result.parseoutcomes()['passed'] == 3
|
assert result.parseoutcomes()['passed'] == 3
|
||||||
|
|
||||||
|
@ -971,7 +971,7 @@ def test_close_and_capture_again(testdir):
|
||||||
os.write(1, b"hello\\n")
|
os.write(1, b"hello\\n")
|
||||||
assert 0
|
assert 0
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest_subprocess()
|
||||||
result.stdout.fnmatch_lines("""
|
result.stdout.fnmatch_lines("""
|
||||||
*test_capture_again*
|
*test_capture_again*
|
||||||
*assert 0*
|
*assert 0*
|
||||||
|
|
|
@ -296,7 +296,6 @@ class TestSession:
|
||||||
subdir.ensure("__init__.py")
|
subdir.ensure("__init__.py")
|
||||||
target = subdir.join(p.basename)
|
target = subdir.join(p.basename)
|
||||||
p.move(target)
|
p.move(target)
|
||||||
testdir.chdir()
|
|
||||||
subdir.chdir()
|
subdir.chdir()
|
||||||
config = testdir.parseconfig(p.basename)
|
config = testdir.parseconfig(p.basename)
|
||||||
rcol = Session(config=config)
|
rcol = Session(config=config)
|
||||||
|
@ -470,7 +469,6 @@ class Test_getinitialnodes:
|
||||||
assert col.config is config
|
assert col.config is config
|
||||||
|
|
||||||
def test_pkgfile(self, testdir):
|
def test_pkgfile(self, testdir):
|
||||||
testdir.chdir()
|
|
||||||
tmpdir = testdir.tmpdir
|
tmpdir = testdir.tmpdir
|
||||||
subdir = tmpdir.join("subdir")
|
subdir = tmpdir.join("subdir")
|
||||||
x = subdir.ensure("x.py")
|
x = subdir.ensure("x.py")
|
||||||
|
|
|
@ -961,7 +961,7 @@ class TestPytestPluginManager:
|
||||||
""")
|
""")
|
||||||
p.copy(p.dirpath("skipping2.py"))
|
p.copy(p.dirpath("skipping2.py"))
|
||||||
monkeypatch.setenv("PYTEST_PLUGINS", "skipping2")
|
monkeypatch.setenv("PYTEST_PLUGINS", "skipping2")
|
||||||
result = testdir.runpytest("-rw", "-p", "skipping1", "--traceconfig")
|
result = testdir.runpytest("-rw", "-p", "skipping1", syspathinsert=True)
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"WI1*skipped plugin*skipping1*hello*",
|
"WI1*skipped plugin*skipping1*hello*",
|
||||||
|
@ -990,7 +990,7 @@ class TestPytestPluginManager:
|
||||||
assert plugin is not None
|
assert plugin is not None
|
||||||
""")
|
""")
|
||||||
monkeypatch.setenv('PYTEST_PLUGINS', 'pytest_x500', prepend=",")
|
monkeypatch.setenv('PYTEST_PLUGINS', 'pytest_x500', prepend=",")
|
||||||
result = testdir.runpytest(p)
|
result = testdir.runpytest(p, syspathinsert=True)
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
result.stdout.fnmatch_lines(["*1 passed*"])
|
result.stdout.fnmatch_lines(["*1 passed*"])
|
||||||
|
|
||||||
|
|
|
@ -75,8 +75,6 @@ class TestDoctests:
|
||||||
assert isinstance(items[0].parent, DoctestModule)
|
assert isinstance(items[0].parent, DoctestModule)
|
||||||
assert items[0].parent is items[1].parent
|
assert items[0].parent is items[1].parent
|
||||||
|
|
||||||
@pytest.mark.xfail('hasattr(sys, "pypy_version_info")', reason=
|
|
||||||
"pypy leaks one FD")
|
|
||||||
def test_simple_doctestfile(self, testdir):
|
def test_simple_doctestfile(self, testdir):
|
||||||
p = testdir.maketxtfile(test_doc="""
|
p = testdir.maketxtfile(test_doc="""
|
||||||
>>> x = 1
|
>>> x = 1
|
||||||
|
|
|
@ -16,7 +16,6 @@ class Standalone:
|
||||||
assert self.script.check()
|
assert self.script.check()
|
||||||
|
|
||||||
def run(self, anypython, testdir, *args):
|
def run(self, anypython, testdir, *args):
|
||||||
testdir.chdir()
|
|
||||||
return testdir._run(anypython, self.script, *args)
|
return testdir._run(anypython, self.script, *args)
|
||||||
|
|
||||||
def test_gen(testdir, anypython, standalone):
|
def test_gen(testdir, anypython, standalone):
|
||||||
|
|
|
@ -53,14 +53,14 @@ def test_traceconfig(testdir):
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_debug(testdir, monkeypatch):
|
def test_debug(testdir, monkeypatch):
|
||||||
result = testdir.runpytest("--debug")
|
result = testdir.runpytest_subprocess("--debug")
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
p = testdir.tmpdir.join("pytestdebug.log")
|
p = testdir.tmpdir.join("pytestdebug.log")
|
||||||
assert "pytest_sessionstart" in p.read()
|
assert "pytest_sessionstart" in p.read()
|
||||||
|
|
||||||
def test_PYTEST_DEBUG(testdir, monkeypatch):
|
def test_PYTEST_DEBUG(testdir, monkeypatch):
|
||||||
monkeypatch.setenv("PYTEST_DEBUG", "1")
|
monkeypatch.setenv("PYTEST_DEBUG", "1")
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest_subprocess()
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
result.stderr.fnmatch_lines([
|
result.stderr.fnmatch_lines([
|
||||||
"*pytest_plugin_registered*",
|
"*pytest_plugin_registered*",
|
||||||
|
|
|
@ -260,7 +260,7 @@ class TestPDB:
|
||||||
|
|
||||||
def test_pdb_collection_failure_is_shown(self, testdir):
|
def test_pdb_collection_failure_is_shown(self, testdir):
|
||||||
p1 = testdir.makepyfile("""xxx """)
|
p1 = testdir.makepyfile("""xxx """)
|
||||||
result = testdir.runpytest("--pdb", p1)
|
result = testdir.runpytest_subprocess("--pdb", p1)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*NameError*xxx*",
|
"*NameError*xxx*",
|
||||||
"*1 error*",
|
"*1 error*",
|
||||||
|
|
|
@ -203,7 +203,6 @@ class TestNewSession(SessionTests):
|
||||||
|
|
||||||
|
|
||||||
def test_plugin_specify(testdir):
|
def test_plugin_specify(testdir):
|
||||||
testdir.chdir()
|
|
||||||
pytest.raises(ImportError, """
|
pytest.raises(ImportError, """
|
||||||
testdir.parseconfig("-p", "nqweotexistent")
|
testdir.parseconfig("-p", "nqweotexistent")
|
||||||
""")
|
""")
|
||||||
|
|
Loading…
Reference in New Issue