Merge remote-tracking branch 'upstream/features' into integrate-pytest-warnings

This commit is contained in:
Bruno Oliveira 2016-11-22 14:35:39 -02:00
commit bd343ef757
40 changed files with 307 additions and 8 deletions

View File

@ -81,10 +81,10 @@ Changes
Thanks `@RonnyPfannschmidt`_ for the report and `@nicoddemus`_ for the PR. Thanks `@RonnyPfannschmidt`_ for the report and `@nicoddemus`_ for the PR.
* Report teardown output on test failure (`#442`_). * Report teardown output on test failure (`#442`_).
Thanks `@matclab`_ or the PR. Thanks `@matclab`_ for the PR.
* Fix teardown error message in generated xUnit XML. * Fix teardown error message in generated xUnit XML.
Thanks `@gdyuldin`_ or the PR. Thanks `@gdyuldin`_ for the PR.
* Properly handle exceptions in ``multiprocessing`` tasks (`#1984`_). * Properly handle exceptions in ``multiprocessing`` tasks (`#1984`_).
Thanks `@adborden`_ for the report and `@nicoddemus`_ for the PR. Thanks `@adborden`_ for the report and `@nicoddemus`_ for the PR.

View File

@ -87,6 +87,7 @@ class FastFilesCompleter:
completion.append(x[prefix_dir:]) completion.append(x[prefix_dir:])
return completion return completion
if os.environ.get('_ARGCOMPLETE'): if os.environ.get('_ARGCOMPLETE'):
try: try:
import argcomplete.completers import argcomplete.completers

View File

@ -343,6 +343,7 @@ class Traceback(list):
l.append(entry.frame.f_locals) l.append(entry.frame.f_locals)
return None return None
co_equal = compile('__recursioncache_locals_1 == __recursioncache_locals_2', co_equal = compile('__recursioncache_locals_1 == __recursioncache_locals_2',
'?', 'eval') '?', 'eval')
@ -846,6 +847,7 @@ def getrawcode(obj, trycall=True):
return x return x
return obj return obj
if sys.version_info[:2] >= (3, 5): # RecursionError introduced in 3.5 if sys.version_info[:2] >= (3, 5): # RecursionError introduced in 3.5
def is_recursion_error(excinfo): def is_recursion_error(excinfo):
return excinfo.errisinstance(RecursionError) # noqa return excinfo.errisinstance(RecursionError) # noqa

View File

@ -265,6 +265,7 @@ def findsource(obj):
source.lines = [line.rstrip() for line in sourcelines] source.lines = [line.rstrip() for line in sourcelines]
return source, lineno return source, lineno
def getsource(obj, **kwargs): def getsource(obj, **kwargs):
import _pytest._code import _pytest._code
obj = _pytest._code.getrawcode(obj) obj = _pytest._code.getrawcode(obj)
@ -275,6 +276,7 @@ def getsource(obj, **kwargs):
assert isinstance(strsrc, str) assert isinstance(strsrc, str)
return Source(strsrc, **kwargs) return Source(strsrc, **kwargs)
def deindent(lines, offset=None): def deindent(lines, offset=None):
if offset is None: if offset is None:
for line in lines: for line in lines:
@ -288,6 +290,7 @@ def deindent(lines, offset=None):
if offset == 0: if offset == 0:
return list(lines) return list(lines)
newlines = [] newlines = []
def readline_generator(lines): def readline_generator(lines):
for line in lines: for line in lines:
yield line + '\n' yield line + '\n'

View File

@ -80,10 +80,12 @@ def install_importhook(config):
config._assertstate.hook = hook = rewrite.AssertionRewritingHook(config) config._assertstate.hook = hook = rewrite.AssertionRewritingHook(config)
sys.meta_path.insert(0, hook) sys.meta_path.insert(0, hook)
config._assertstate.trace('installed rewrite import hook') config._assertstate.trace('installed rewrite import hook')
def undo(): def undo():
hook = config._assertstate.hook hook = config._assertstate.hook
if hook is not None and hook in sys.meta_path: if hook is not None and hook in sys.meta_path:
sys.meta_path.remove(hook) sys.meta_path.remove(hook)
config.add_cleanup(undo) config.add_cleanup(undo)
return hook return hook

View File

@ -276,6 +276,7 @@ def _write_pyc(state, co, source_stat, pyc):
fp.close() fp.close()
return True return True
RN = "\r\n".encode("utf-8") RN = "\r\n".encode("utf-8")
N = "\n".encode("utf-8") N = "\n".encode("utf-8")

View File

@ -153,6 +153,7 @@ class CaptureManager:
item.add_report_section(when, "stdout", out) item.add_report_section(when, "stdout", out)
item.add_report_section(when, "stderr", err) item.add_report_section(when, "stderr", err)
error_capsysfderror = "cannot use capsys and capfd at the same time" error_capsysfderror = "cannot use capsys and capfd at the same time"

View File

@ -65,9 +65,11 @@ def main(args=None, plugins=None):
class cmdline: # compatibility namespace class cmdline: # compatibility namespace
main = staticmethod(main) main = staticmethod(main)
class UsageError(Exception): class UsageError(Exception):
""" error in pytest usage or invocation""" """ error in pytest usage or invocation"""
_preinit = [] _preinit = []
default_plugins = ( default_plugins = (
@ -594,7 +596,7 @@ class Argument:
if typ == 'choice': if typ == 'choice':
warnings.warn( warnings.warn(
'type argument to addoption() is a string %r.' 'type argument to addoption() is a string %r.'
' For parsearg this is optional and when supplied ' ' For parsearg this is optional and when supplied'
' should be a type.' ' should be a type.'
' (options: %s)' % (typ, names), ' (options: %s)' % (typ, names),
DeprecationWarning, DeprecationWarning,
@ -818,9 +820,11 @@ class Notset:
def __repr__(self): def __repr__(self):
return "<NOTSET>" return "<NOTSET>"
notset = Notset() notset = Notset()
FILE_OR_DIR = 'file_or_dir' FILE_OR_DIR = 'file_or_dir'
class Config(object): class Config(object):
""" access to configuration values, pluginmanager and plugin hooks. """ """ access to configuration values, pluginmanager and plugin hooks. """
@ -843,9 +847,11 @@ class Config(object):
self._warn = self.pluginmanager._warn self._warn = self.pluginmanager._warn
self.pluginmanager.register(self, "pytestconfig") self.pluginmanager.register(self, "pytestconfig")
self._configured = False self._configured = False
def do_setns(dic): def do_setns(dic):
import pytest import pytest
setns(pytest, dic) setns(pytest, dic)
self.hook.pytest_namespace.call_historic(do_setns, {}) self.hook.pytest_namespace.call_historic(do_setns, {})
self.hook.pytest_addoption.call_historic(kwargs=dict(parser=self._parser)) self.hook.pytest_addoption.call_historic(kwargs=dict(parser=self._parser))

View File

@ -31,10 +31,12 @@ def pytest_configure(config):
config.pluginmanager.register(PdbInvoke(), 'pdbinvoke') config.pluginmanager.register(PdbInvoke(), 'pdbinvoke')
old = (pdb.set_trace, pytestPDB._pluginmanager) old = (pdb.set_trace, pytestPDB._pluginmanager)
def fin(): def fin():
pdb.set_trace, pytestPDB._pluginmanager = old pdb.set_trace, pytestPDB._pluginmanager = old
pytestPDB._config = None pytestPDB._config = None
pytestPDB._pdb_cls = pdb.Pdb pytestPDB._pdb_cls = pdb.Pdb
pdb.set_trace = pytest.set_trace pdb.set_trace = pytest.set_trace
pytestPDB._pluginmanager = config.pluginmanager pytestPDB._pluginmanager = config.pluginmanager
pytestPDB._config = config pytestPDB._config = config

View File

@ -32,11 +32,13 @@ scope2props["function"] = scope2props["instance"] + ("function", "keywords")
def scopeproperty(name=None, doc=None): def scopeproperty(name=None, doc=None):
def decoratescope(func): def decoratescope(func):
scopename = name or func.__name__ scopename = name or func.__name__
def provide(self): def provide(self):
if func.__name__ in scope2props[self.scope]: if func.__name__ in scope2props[self.scope]:
return func(self) return func(self)
raise AttributeError("%s not available in %s-scoped context" % ( raise AttributeError("%s not available in %s-scoped context" % (
scopename, self.scope)) scopename, self.scope))
return property(provide, None, None, func.__doc__) return property(provide, None, None, func.__doc__)
return decoratescope return decoratescope

View File

@ -41,12 +41,14 @@ def pytest_cmdline_parse():
config.trace.root.setwriter(debugfile.write) config.trace.root.setwriter(debugfile.write)
undo_tracing = config.pluginmanager.enable_tracing() undo_tracing = config.pluginmanager.enable_tracing()
sys.stderr.write("writing pytestdebug information to %s\n" % path) sys.stderr.write("writing pytestdebug information to %s\n" % path)
def unset_tracing(): def unset_tracing():
debugfile.close() debugfile.close()
sys.stderr.write("wrote pytestdebug information to %s\n" % sys.stderr.write("wrote pytestdebug information to %s\n" %
debugfile.name) debugfile.name)
config.trace.root.setwriter(None) config.trace.root.setwriter(None)
undo_tracing() undo_tracing()
config.add_cleanup(unset_tracing) config.add_cleanup(unset_tracing)
def pytest_cmdline_main(config): def pytest_cmdline_main(config):

View File

@ -27,6 +27,7 @@ else:
class Junit(py.xml.Namespace): class Junit(py.xml.Namespace):
pass pass
# We need to get the subset of the invalid unicode ranges according to # We need to get the subset of the invalid unicode ranges according to
# XML 1.0 which are valid in this python build. Hence we calculate # XML 1.0 which are valid in this python build. Hence we calculate
# this dynamically instead of hardcoding it. The spec range of valid # this dynamically instead of hardcoding it. The spec range of valid

View File

@ -60,6 +60,8 @@ def pytest_cmdline_main(config):
tw.line() tw.line()
config._ensure_unconfigure() config._ensure_unconfigure()
return 0 return 0
pytest_cmdline_main.tryfirst = True pytest_cmdline_main.tryfirst = True

View File

@ -11,6 +11,7 @@ def pytest_addoption(parser):
choices=['failed', 'all'], choices=['failed', 'all'],
help="send failed|all info to bpaste.net pastebin service.") help="send failed|all info to bpaste.net pastebin service.")
@pytest.hookimpl(trylast=True) @pytest.hookimpl(trylast=True)
def pytest_configure(config): def pytest_configure(config):
import py import py
@ -23,13 +24,16 @@ def pytest_configure(config):
# pastebin file will be utf-8 encoded binary file # pastebin file will be utf-8 encoded binary file
config._pastebinfile = tempfile.TemporaryFile('w+b') config._pastebinfile = tempfile.TemporaryFile('w+b')
oldwrite = tr._tw.write oldwrite = tr._tw.write
def tee_write(s, **kwargs): def tee_write(s, **kwargs):
oldwrite(s, **kwargs) oldwrite(s, **kwargs)
if py.builtin._istext(s): if py.builtin._istext(s):
s = s.encode('utf-8') s = s.encode('utf-8')
config._pastebinfile.write(s) config._pastebinfile.write(s)
tr._tw.write = tee_write tr._tw.write = tee_write
def pytest_unconfigure(config): def pytest_unconfigure(config):
if hasattr(config, '_pastebinfile'): if hasattr(config, '_pastebinfile'):
# get terminal contents and delete file # get terminal contents and delete file
@ -45,6 +49,7 @@ def pytest_unconfigure(config):
pastebinurl = create_new_paste(sessionlog) pastebinurl = create_new_paste(sessionlog)
tr.write_line("pastebin session-log: %s\n" % pastebinurl) tr.write_line("pastebin session-log: %s\n" % pastebinurl)
def create_new_paste(contents): def create_new_paste(contents):
""" """
Creates a new paste using bpaste.net service. Creates a new paste using bpaste.net service.
@ -72,6 +77,7 @@ def create_new_paste(contents):
else: else:
return 'bad response: ' + response return 'bad response: ' + response
def pytest_terminal_summary(terminalreporter): def pytest_terminal_summary(terminalreporter):
import _pytest.config import _pytest.config
if terminalreporter.config.option.pastebin != "failed": if terminalreporter.config.option.pastebin != "failed":

View File

@ -482,10 +482,12 @@ class Testdir:
for name, value in items: for name, value in items:
p = self.tmpdir.join(name).new(ext=ext) p = self.tmpdir.join(name).new(ext=ext)
source = Source(value) source = Source(value)
def my_totext(s, encoding="utf-8"): def my_totext(s, encoding="utf-8"):
if py.builtin._isbytes(s): if py.builtin._isbytes(s):
s = py.builtin._totext(s, encoding=encoding) s = py.builtin._totext(s, encoding=encoding)
return s return s
source_unicode = "\n".join([my_totext(line) for line in source.lines]) source_unicode = "\n".join([my_totext(line) for line in source.lines])
source = py.builtin._totext(source_unicode) source = py.builtin._totext(source_unicode)
content = source.strip().encode("utf-8") # + "\n" content = source.strip().encode("utf-8") # + "\n"
@ -695,12 +697,15 @@ class Testdir:
# warning which will trigger to say they can no longer be # warning which will trigger to say they can no longer be
# re-written, which is fine as they are already re-written. # re-written, which is fine as they are already re-written.
orig_warn = AssertionRewritingHook._warn_already_imported orig_warn = AssertionRewritingHook._warn_already_imported
def revert(): def revert():
AssertionRewritingHook._warn_already_imported = orig_warn AssertionRewritingHook._warn_already_imported = orig_warn
self.request.addfinalizer(revert) self.request.addfinalizer(revert)
AssertionRewritingHook._warn_already_imported = lambda *a: None AssertionRewritingHook._warn_already_imported = lambda *a: None
rec = [] rec = []
class Collect: class Collect:
def pytest_configure(x, config): def pytest_configure(x, config):
rec.append(self.make_hook_recorder(config.pluginmanager)) rec.append(self.make_hook_recorder(config.pluginmanager))
@ -735,10 +740,13 @@ class Testdir:
try: try:
reprec = self.inline_run(*args, **kwargs) reprec = self.inline_run(*args, **kwargs)
except SystemExit as e: except SystemExit as e:
class reprec: class reprec:
ret = e.args[0] ret = e.args[0]
except Exception: except Exception:
traceback.print_exc() traceback.print_exc()
class reprec: class reprec:
ret = 3 ret = 3
finally: finally:

View File

@ -214,9 +214,12 @@ class PyobjMixin(PyobjContext):
if obj is None: if obj is None:
self._obj = obj = self._getobj() self._obj = obj = self._getobj()
return obj return obj
def fset(self, value): def fset(self, value):
self._obj = value self._obj = value
return property(fget, fset, None, "underlying python object") return property(fget, fset, None, "underlying python object")
obj = obj() obj = obj()
def _getobj(self): def _getobj(self):

View File

@ -517,8 +517,10 @@ def exit(msg):
__tracebackhide__ = True __tracebackhide__ = True
raise Exit(msg) raise Exit(msg)
exit.Exception = Exit exit.Exception = Exit
def skip(msg=""): def skip(msg=""):
""" skip an executing test with the given message. Note: it's usually """ skip an executing test with the given message. Note: it's usually
better to use the pytest.mark.skipif marker to declare a test to be better to use the pytest.mark.skipif marker to declare a test to be
@ -527,8 +529,11 @@ def skip(msg=""):
""" """
__tracebackhide__ = True __tracebackhide__ = True
raise Skipped(msg=msg) raise Skipped(msg=msg)
skip.Exception = Skipped skip.Exception = Skipped
def fail(msg="", pytrace=True): def fail(msg="", pytrace=True):
""" explicitly fail an currently-executing test with the given Message. """ explicitly fail an currently-executing test with the given Message.
@ -537,6 +542,8 @@ def fail(msg="", pytrace=True):
""" """
__tracebackhide__ = True __tracebackhide__ = True
raise Failed(msg=msg, pytrace=pytrace) raise Failed(msg=msg, pytrace=pytrace)
fail.Exception = Failed fail.Exception = Failed

View File

@ -25,8 +25,10 @@ def pytest_configure(config):
if config.option.runxfail: if config.option.runxfail:
old = pytest.xfail old = pytest.xfail
config._cleanup.append(lambda: setattr(pytest, "xfail", old)) config._cleanup.append(lambda: setattr(pytest, "xfail", old))
def nop(*args, **kwargs): def nop(*args, **kwargs):
pass pass
nop.Exception = XFailed nop.Exception = XFailed
setattr(pytest, "xfail", nop) setattr(pytest, "xfail", nop)
@ -65,6 +67,8 @@ def xfail(reason=""):
""" xfail an executing test or setup functions with the given reason.""" """ xfail an executing test or setup functions with the given reason."""
__tracebackhide__ = True __tracebackhide__ = True
raise XFailed(reason) raise XFailed(reason)
xfail.Exception = XFailed xfail.Exception = XFailed

View File

@ -81,6 +81,7 @@ def get_user():
except (ImportError, KeyError): except (ImportError, KeyError):
return None return None
# backward compatibility # backward compatibility
TempdirHandler = TempdirFactory TempdirHandler = TempdirFactory

View File

@ -186,6 +186,7 @@ def pytest_runtest_protocol(item):
ut = sys.modules['twisted.python.failure'] ut = sys.modules['twisted.python.failure']
Failure__init__ = ut.Failure.__init__ Failure__init__ = ut.Failure.__init__
check_testcase_implements_trial_reporter() check_testcase_implements_trial_reporter()
def excstore(self, exc_value=None, exc_type=None, exc_tb=None, def excstore(self, exc_value=None, exc_type=None, exc_tb=None,
captureVars=None): captureVars=None):
if exc_value is None: if exc_value is None:
@ -199,6 +200,7 @@ def pytest_runtest_protocol(item):
captureVars=captureVars) captureVars=captureVars)
except TypeError: except TypeError:
Failure__init__(self, exc_value, exc_type, exc_tb) Failure__init__(self, exc_value, exc_type, exc_tb)
ut.Failure.__init__ = excstore ut.Failure.__init__ = excstore
yield yield
ut.Failure.__init__ = Failure__init__ ut.Failure.__init__ = Failure__init__

View File

@ -24,6 +24,7 @@ def test_code_with_class():
pass pass
pytest.raises(TypeError, "_pytest._code.Code(A)") pytest.raises(TypeError, "_pytest._code.Code(A)")
if True: if True:
def x(): def x():
pass pass
@ -68,8 +69,10 @@ def test_code_from_func():
def test_unicode_handling(): def test_unicode_handling():
value = py.builtin._totext('\xc4\x85\xc4\x87\n', 'utf-8').encode('utf8') value = py.builtin._totext('\xc4\x85\xc4\x87\n', 'utf-8').encode('utf8')
def f(): def f():
raise Exception(value) raise Exception(value)
excinfo = pytest.raises(Exception, f) excinfo = pytest.raises(Exception, f)
str(excinfo) str(excinfo)
if sys.version_info[0] < 3: if sys.version_info[0] < 3:
@ -79,8 +82,10 @@ def test_unicode_handling():
@pytest.mark.skipif(sys.version_info[0] >= 3, reason='python 2 only issue') @pytest.mark.skipif(sys.version_info[0] >= 3, reason='python 2 only issue')
def test_unicode_handling_syntax_error(): def test_unicode_handling_syntax_error():
value = py.builtin._totext('\xc4\x85\xc4\x87\n', 'utf-8').encode('utf8') value = py.builtin._totext('\xc4\x85\xc4\x87\n', 'utf-8').encode('utf8')
def f(): def f():
raise SyntaxError('invalid syntax', (None, 1, 3, value)) raise SyntaxError('invalid syntax', (None, 1, 3, value))
excinfo = pytest.raises(Exception, f) excinfo = pytest.raises(Exception, f)
str(excinfo) str(excinfo)
if sys.version_info[0] < 3: if sys.version_info[0] < 3:

View File

@ -56,13 +56,15 @@ def test_excinfo_simple():
def test_excinfo_getstatement(): def test_excinfo_getstatement():
def g(): def g():
raise ValueError raise ValueError
def f(): def f():
g() g()
try: try:
f() f()
except ValueError: except ValueError:
excinfo = _pytest._code.ExceptionInfo() excinfo = _pytest._code.ExceptionInfo()
linenumbers = [_pytest._code.getrawcode(f).co_firstlineno - 1 + 3, linenumbers = [_pytest._code.getrawcode(f).co_firstlineno - 1 + 4,
_pytest._code.getrawcode(f).co_firstlineno - 1 + 1, _pytest._code.getrawcode(f).co_firstlineno - 1 + 1,
_pytest._code.getrawcode(g).co_firstlineno - 1 + 1, ] _pytest._code.getrawcode(g).co_firstlineno - 1 + 1, ]
l = list(excinfo.traceback) l = list(excinfo.traceback)
@ -168,11 +170,13 @@ class TestTraceback_f_g_h:
# #
raise ValueError raise ValueError
# #
def g(): def g():
# #
__tracebackhide__ = tracebackhide __tracebackhide__ = tracebackhide
f() f()
# #
def h(): def h():
# #
g() g()
@ -214,15 +218,18 @@ class TestTraceback_f_g_h:
def test_traceback_no_recursion_index(self): def test_traceback_no_recursion_index(self):
def do_stuff(): def do_stuff():
raise RuntimeError raise RuntimeError
def reraise_me(): def reraise_me():
import sys import sys
exc, val, tb = sys.exc_info() exc, val, tb = sys.exc_info()
py.builtin._reraise(exc, val, tb) py.builtin._reraise(exc, val, tb)
def f(n): def f(n):
try: try:
do_stuff() do_stuff()
except: except:
reraise_me() reraise_me()
excinfo = pytest.raises(RuntimeError, f, 8) excinfo = pytest.raises(RuntimeError, f, 8)
traceback = excinfo.traceback traceback = excinfo.traceback
recindex = traceback.recursionindex() recindex = traceback.recursionindex()
@ -245,17 +252,18 @@ class TestTraceback_f_g_h:
excinfo = pytest.raises(ValueError, fail) excinfo = pytest.raises(ValueError, fail)
assert excinfo.traceback.recursionindex() is None assert excinfo.traceback.recursionindex() is None
def test_traceback_getcrashentry(self): def test_traceback_getcrashentry(self):
def i(): def i():
__tracebackhide__ = True __tracebackhide__ = True
raise ValueError raise ValueError
def h(): def h():
i() i()
def g(): def g():
__tracebackhide__ = True __tracebackhide__ = True
h() h()
def f(): def f():
g() g()
@ -271,6 +279,7 @@ class TestTraceback_f_g_h:
def g(): def g():
__tracebackhide__ = True __tracebackhide__ = True
raise ValueError raise ValueError
def f(): def f():
__tracebackhide__ = True __tracebackhide__ = True
g() g()
@ -465,11 +474,13 @@ raise ValueError()
class FakeCode(object): class FakeCode(object):
class raw: class raw:
co_filename = '?' co_filename = '?'
path = '?' path = '?'
firstlineno = 5 firstlineno = 5
def fullsource(self): def fullsource(self):
return None return None
fullsource = property(fullsource) fullsource = property(fullsource)
class FakeFrame(object): class FakeFrame(object):
@ -491,17 +502,21 @@ raise ValueError()
class FakeExcinfo(_pytest._code.ExceptionInfo): class FakeExcinfo(_pytest._code.ExceptionInfo):
typename = "Foo" typename = "Foo"
value = Exception() value = Exception()
def __init__(self): def __init__(self):
pass pass
def exconly(self, tryshort): def exconly(self, tryshort):
return "EXC" return "EXC"
def errisinstance(self, cls): def errisinstance(self, cls):
return False return False
excinfo = FakeExcinfo() excinfo = FakeExcinfo()
class FakeRawTB(object): class FakeRawTB(object):
tb_next = None tb_next = None
tb = FakeRawTB() tb = FakeRawTB()
excinfo.traceback = Traceback(tb) excinfo.traceback = Traceback(tb)
@ -719,8 +734,10 @@ raise ValueError()
excinfo = pytest.raises(ValueError, mod.entry) excinfo = pytest.raises(ValueError, mod.entry)
p = FormattedExcinfo() p = FormattedExcinfo()
def raiseos(): def raiseos():
raise OSError(2) raise OSError(2)
monkeypatch.setattr(py.std.os, 'getcwd', raiseos) monkeypatch.setattr(py.std.os, 'getcwd', raiseos)
assert p._makepath(__file__) == __file__ assert p._makepath(__file__) == __file__
p.repr_traceback(excinfo) p.repr_traceback(excinfo)
@ -789,9 +806,11 @@ raise ValueError()
def test_reprexcinfo_unicode(self): def test_reprexcinfo_unicode(self):
from _pytest._code.code import TerminalRepr from _pytest._code.code import TerminalRepr
class MyRepr(TerminalRepr): class MyRepr(TerminalRepr):
def toterminal(self, tw): def toterminal(self, tw):
tw.line(py.builtin._totext("я", "utf-8")) tw.line(py.builtin._totext("я", "utf-8"))
x = py.builtin._totext(MyRepr()) x = py.builtin._totext(MyRepr())
assert x == py.builtin._totext("я", "utf-8") assert x == py.builtin._totext("я", "utf-8")

View File

@ -383,10 +383,13 @@ class TestFunction:
config = testdir.parseconfigure() config = testdir.parseconfigure()
session = testdir.Session(config) session = testdir.Session(config)
session._fixturemanager = FixtureManager(session) session._fixturemanager = FixtureManager(session)
def func1(): def func1():
pass pass
def func2(): def func2():
pass pass
f1 = pytest.Function(name="name", parent=session, config=config, f1 = pytest.Function(name="name", parent=session, config=config,
args=(1,), callobj=func1) args=(1,), callobj=func1)
assert f1 == f1 assert f1 == f1
@ -547,12 +550,15 @@ class TestFunction:
def test_pyfunc_call(self, testdir): def test_pyfunc_call(self, testdir):
item = testdir.getitem("def test_func(): raise ValueError") item = testdir.getitem("def test_func(): raise ValueError")
config = item.config config = item.config
class MyPlugin1: class MyPlugin1:
def pytest_pyfunc_call(self, pyfuncitem): def pytest_pyfunc_call(self, pyfuncitem):
raise ValueError raise ValueError
class MyPlugin2: class MyPlugin2:
def pytest_pyfunc_call(self, pyfuncitem): def pytest_pyfunc_call(self, pyfuncitem):
return True return True
config.pluginmanager.register(MyPlugin1()) config.pluginmanager.register(MyPlugin1())
config.pluginmanager.register(MyPlugin2()) config.pluginmanager.register(MyPlugin2())
config.hook.pytest_runtest_setup(item=item) config.hook.pytest_runtest_setup(item=item)

View File

@ -10,15 +10,20 @@ from _pytest import fixtures
def test_getfuncargnames(): def test_getfuncargnames():
def f(): pass def f(): pass
assert not fixtures.getfuncargnames(f) assert not fixtures.getfuncargnames(f)
def g(arg): pass def g(arg): pass
assert fixtures.getfuncargnames(g) == ('arg',) assert fixtures.getfuncargnames(g) == ('arg',)
def h(arg1, arg2="hello"): pass def h(arg1, arg2="hello"): pass
assert fixtures.getfuncargnames(h) == ('arg1',) assert fixtures.getfuncargnames(h) == ('arg1',)
def h(arg1, arg2, arg3="hello"): pass def h(arg1, arg2, arg3="hello"): pass
assert fixtures.getfuncargnames(h) == ('arg1', 'arg2') assert fixtures.getfuncargnames(h) == ('arg1', 'arg2')
class A: class A:
def f(self, arg1, arg2="hello"): def f(self, arg1, arg2="hello"):
pass pass
assert fixtures.getfuncargnames(A().f) == ('arg1',) assert fixtures.getfuncargnames(A().f) == ('arg1',)
if sys.version_info < (3,0): if sys.version_info < (3,0):
assert fixtures.getfuncargnames(A.f) == ('arg1',) assert fixtures.getfuncargnames(A.f) == ('arg1',)
@ -869,8 +874,10 @@ class TestRequestCachedSetup:
item1 = testdir.getitem("def test_func(): pass") item1 = testdir.getitem("def test_func(): pass")
req1 = fixtures.FixtureRequest(item1) req1 = fixtures.FixtureRequest(item1)
l = ["hello", "world"] l = ["hello", "world"]
def setup(): def setup():
return l.pop() return l.pop()
ret1 = req1.cached_setup(setup, extrakey=1) ret1 = req1.cached_setup(setup, extrakey=1)
ret2 = req1.cached_setup(setup, extrakey=2) ret2 = req1.cached_setup(setup, extrakey=2)
assert ret2 == "hello" assert ret2 == "hello"
@ -884,10 +891,13 @@ class TestRequestCachedSetup:
item1 = testdir.getitem("def test_func(): pass") item1 = testdir.getitem("def test_func(): pass")
req1 = fixtures.FixtureRequest(item1) req1 = fixtures.FixtureRequest(item1)
l = [] l = []
def setup(): def setup():
l.append("setup") l.append("setup")
def teardown(val): def teardown(val):
l.append("teardown") l.append("teardown")
req1.cached_setup(setup, teardown, scope="function") req1.cached_setup(setup, teardown, scope="function")
assert l == ['setup'] assert l == ['setup']
# artificial call of finalizer # artificial call of finalizer

View File

@ -63,10 +63,12 @@ class TestOEJSKITSpecials:
def test_wrapped_getfslineno(): def test_wrapped_getfslineno():
def func(): def func():
pass pass
def wrap(f): def wrap(f):
func.__wrapped__ = f func.__wrapped__ = f
func.patchings = ["qwe"] func.patchings = ["qwe"]
return func return func
@wrap @wrap
def wrapped_func(x, y, z): def wrapped_func(x, y, z):
pass pass
@ -77,28 +79,36 @@ def test_wrapped_getfslineno():
class TestMockDecoration: class TestMockDecoration:
def test_wrapped_getfuncargnames(self): def test_wrapped_getfuncargnames(self):
from _pytest.compat import getfuncargnames from _pytest.compat import getfuncargnames
def wrap(f): def wrap(f):
def func(): def func():
pass pass
func.__wrapped__ = f func.__wrapped__ = f
return func return func
@wrap @wrap
def f(x): def f(x):
pass pass
l = getfuncargnames(f) l = getfuncargnames(f)
assert l == ("x",) assert l == ("x",)
def test_wrapped_getfuncargnames_patching(self): def test_wrapped_getfuncargnames_patching(self):
from _pytest.compat import getfuncargnames from _pytest.compat import getfuncargnames
def wrap(f): def wrap(f):
def func(): def func():
pass pass
func.__wrapped__ = f func.__wrapped__ = f
func.patchings = ["qwe"] func.patchings = ["qwe"]
return func return func
@wrap @wrap
def f(x, y, z): def f(x, y, z):
pass pass
l = getfuncargnames(f) l = getfuncargnames(f)
assert l == ("y", "z") assert l == ("y", "z")

View File

@ -20,8 +20,10 @@ class TestMetafunc:
# initiliazation # initiliazation
class FixtureInfo: class FixtureInfo:
name2fixturedefs = None name2fixturedefs = None
def __init__(self, names): def __init__(self, names):
self.names_closure = names self.names_closure = names
names = fixtures.getfuncargnames(func) names = fixtures.getfuncargnames(func)
fixtureinfo = FixtureInfo(names) fixtureinfo = FixtureInfo(names)
return python.Metafunc(func, fixtureinfo, None) return python.Metafunc(func, fixtureinfo, None)
@ -65,7 +67,9 @@ class TestMetafunc:
def test_addcall_param(self): def test_addcall_param(self):
def func(arg1): pass def func(arg1): pass
metafunc = self.Metafunc(func) metafunc = self.Metafunc(func)
class obj: pass class obj: pass
metafunc.addcall(param=obj) metafunc.addcall(param=obj)
metafunc.addcall(param=obj) metafunc.addcall(param=obj)
metafunc.addcall(param=1) metafunc.addcall(param=1)
@ -76,8 +80,11 @@ class TestMetafunc:
def test_addcall_funcargs(self): def test_addcall_funcargs(self):
def func(x): pass def func(x): pass
metafunc = self.Metafunc(func) metafunc = self.Metafunc(func)
class obj: pass class obj: pass
metafunc.addcall(funcargs={"x": 2}) metafunc.addcall(funcargs={"x": 2})
metafunc.addcall(funcargs={"x": 3}) metafunc.addcall(funcargs={"x": 3})
pytest.raises(pytest.fail.Exception, "metafunc.addcall({'xyz': 0})") pytest.raises(pytest.fail.Exception, "metafunc.addcall({'xyz': 0})")
@ -142,8 +149,10 @@ class TestMetafunc:
def test_parametrize_with_userobjects(self): def test_parametrize_with_userobjects(self):
def func(x, y): pass def func(x, y): pass
metafunc = self.Metafunc(func) metafunc = self.Metafunc(func)
class A: class A:
pass pass
metafunc.parametrize("x", [A(), A()]) metafunc.parametrize("x", [A(), A()])
metafunc.parametrize("y", list("ab")) metafunc.parametrize("y", list("ab"))
assert metafunc._calls[0].id == "x0-a" assert metafunc._calls[0].id == "x0-a"
@ -254,6 +263,7 @@ class TestMetafunc:
@pytest.mark.issue351 @pytest.mark.issue351
def test_idmaker_idfn(self): def test_idmaker_idfn(self):
from _pytest.python import idmaker from _pytest.python import idmaker
def ids(val): def ids(val):
if isinstance(val, Exception): if isinstance(val, Exception):
return repr(val) return repr(val)
@ -270,6 +280,7 @@ class TestMetafunc:
@pytest.mark.issue351 @pytest.mark.issue351
def test_idmaker_idfn_unique_names(self): def test_idmaker_idfn_unique_names(self):
from _pytest.python import idmaker from _pytest.python import idmaker
def ids(val): def ids(val):
return 'a' return 'a'
@ -285,6 +296,7 @@ class TestMetafunc:
@pytest.mark.issue351 @pytest.mark.issue351
def test_idmaker_idfn_exception(self): def test_idmaker_idfn_exception(self):
from _pytest.python import idmaker from _pytest.python import idmaker
def ids(val): def ids(val):
raise Exception("bad code") raise Exception("bad code")

View File

@ -13,12 +13,15 @@ PY3 = sys.version_info >= (3, 0)
@pytest.fixture @pytest.fixture
def mock_config(): def mock_config():
class Config(object): class Config(object):
verbose = False verbose = False
def getoption(self, name): def getoption(self, name):
if name == 'verbose': if name == 'verbose':
return self.verbose return self.verbose
raise KeyError('Not mocked out: %s' % name) raise KeyError('Not mocked out: %s' % name)
return Config() return Config()

View File

@ -104,20 +104,29 @@ class TestAssertionRewrite:
def f(): def f():
assert False assert False
assert getmsg(f) == "assert False" assert getmsg(f) == "assert False"
def f(): def f():
f = False f = False
assert f assert f
assert getmsg(f) == "assert False" assert getmsg(f) == "assert False"
def f(): def f():
assert a_global # noqa assert a_global # noqa
assert getmsg(f, {"a_global" : False}) == "assert False" assert getmsg(f, {"a_global" : False}) == "assert False"
def f(): def f():
assert sys == 42 assert sys == 42
assert getmsg(f, {"sys" : sys}) == "assert sys == 42" assert getmsg(f, {"sys" : sys}) == "assert sys == 42"
def f(): def f():
assert cls == 42 # noqa assert cls == 42 # noqa
class X(object): class X(object):
pass pass
assert getmsg(f, {"cls" : X}) == "assert cls == 42" assert getmsg(f, {"cls" : X}) == "assert cls == 42"
def test_assert_already_has_message(self): def test_assert_already_has_message(self):
@ -190,78 +199,110 @@ class TestAssertionRewrite:
def f(): def f():
f = g = False f = g = False
assert f and g assert f and g
assert getmsg(f) == "assert (False)" assert getmsg(f) == "assert (False)"
def f(): def f():
f = True f = True
g = False g = False
assert f and g assert f and g
assert getmsg(f) == "assert (True and False)" assert getmsg(f) == "assert (True and False)"
def f(): def f():
f = False f = False
g = True g = True
assert f and g assert f and g
assert getmsg(f) == "assert (False)" assert getmsg(f) == "assert (False)"
def f(): def f():
f = g = False f = g = False
assert f or g assert f or g
assert getmsg(f) == "assert (False or False)" assert getmsg(f) == "assert (False or False)"
def f(): def f():
f = g = False f = g = False
assert not f and not g assert not f and not g
getmsg(f, must_pass=True) getmsg(f, must_pass=True)
def x(): def x():
return False return False
def f(): def f():
assert x() and x() assert x() and x()
assert getmsg(f, {"x" : x}) == """assert (False) assert getmsg(f, {"x" : x}) == """assert (False)
+ where False = x()""" + where False = x()"""
def f(): def f():
assert False or x() assert False or x()
assert getmsg(f, {"x" : x}) == """assert (False or False) assert getmsg(f, {"x" : x}) == """assert (False or False)
+ where False = x()""" + where False = x()"""
def f(): def f():
assert 1 in {} and 2 in {} assert 1 in {} and 2 in {}
assert getmsg(f) == "assert (1 in {})" assert getmsg(f) == "assert (1 in {})"
def f(): def f():
x = 1 x = 1
y = 2 y = 2
assert x in {1 : None} and y in {} assert x in {1 : None} and y in {}
assert getmsg(f) == "assert (1 in {1: None} and 2 in {})" assert getmsg(f) == "assert (1 in {1: None} and 2 in {})"
def f(): def f():
f = True f = True
g = False g = False
assert f or g assert f or g
getmsg(f, must_pass=True) getmsg(f, must_pass=True)
def f(): def f():
f = g = h = lambda: True f = g = h = lambda: True
assert f() and g() and h() assert f() and g() and h()
getmsg(f, must_pass=True) getmsg(f, must_pass=True)
def test_short_circut_evaluation(self): def test_short_circut_evaluation(self):
def f(): def f():
assert True or explode # noqa assert True or explode # noqa
getmsg(f, must_pass=True) getmsg(f, must_pass=True)
def f(): def f():
x = 1 x = 1
assert x == 1 or x == 2 assert x == 1 or x == 2
getmsg(f, must_pass=True) getmsg(f, must_pass=True)
def test_unary_op(self): def test_unary_op(self):
def f(): def f():
x = True x = True
assert not x assert not x
assert getmsg(f) == "assert not True" assert getmsg(f) == "assert not True"
def f(): def f():
x = 0 x = 0
assert ~x + 1 assert ~x + 1
assert getmsg(f) == "assert (~0 + 1)" assert getmsg(f) == "assert (~0 + 1)"
def f(): def f():
x = 3 x = 3
assert -x + x assert -x + x
assert getmsg(f) == "assert (-3 + 3)" assert getmsg(f) == "assert (-3 + 3)"
def f(): def f():
x = 0 x = 0
assert +x + x assert +x + x
assert getmsg(f) == "assert (+0 + 0)" assert getmsg(f) == "assert (+0 + 0)"
def test_binary_op(self): def test_binary_op(self):
@ -269,7 +310,9 @@ class TestAssertionRewrite:
x = 1 x = 1
y = -1 y = -1
assert x + y assert x + y
assert getmsg(f) == "assert (1 + -1)" assert getmsg(f) == "assert (1 + -1)"
def f(): def f():
assert not 5 % 4 assert not 5 % 4
assert getmsg(f) == "assert not (5 % 4)" assert getmsg(f) == "assert not (5 % 4)"
@ -277,7 +320,9 @@ class TestAssertionRewrite:
def test_boolop_percent(self): def test_boolop_percent(self):
def f(): def f():
assert 3 % 2 and False assert 3 % 2 and False
assert getmsg(f) == "assert ((3 % 2) and False)" assert getmsg(f) == "assert ((3 % 2) and False)"
def f(): def f():
assert False or 4 % 2 assert False or 4 % 2
assert getmsg(f) == "assert (False or (4 % 2))" assert getmsg(f) == "assert (False or (4 % 2))"
@ -298,113 +343,159 @@ class TestAssertionRewrite:
def test_call(self): def test_call(self):
def g(a=42, *args, **kwargs): def g(a=42, *args, **kwargs):
return False return False
ns = {"g" : g} ns = {"g" : g}
def f(): def f():
assert g() assert g()
assert getmsg(f, ns) == """assert False assert getmsg(f, ns) == """assert False
+ where False = g()""" + where False = g()"""
def f(): def f():
assert g(1) assert g(1)
assert getmsg(f, ns) == """assert False assert getmsg(f, ns) == """assert False
+ where False = g(1)""" + where False = g(1)"""
def f(): def f():
assert g(1, 2) assert g(1, 2)
assert getmsg(f, ns) == """assert False assert getmsg(f, ns) == """assert False
+ where False = g(1, 2)""" + where False = g(1, 2)"""
def f(): def f():
assert g(1, g=42) assert g(1, g=42)
assert getmsg(f, ns) == """assert False assert getmsg(f, ns) == """assert False
+ where False = g(1, g=42)""" + where False = g(1, g=42)"""
def f(): def f():
assert g(1, 3, g=23) assert g(1, 3, g=23)
assert getmsg(f, ns) == """assert False assert getmsg(f, ns) == """assert False
+ where False = g(1, 3, g=23)""" + where False = g(1, 3, g=23)"""
def f(): def f():
seq = [1, 2, 3] seq = [1, 2, 3]
assert g(*seq) assert g(*seq)
assert getmsg(f, ns) == """assert False assert getmsg(f, ns) == """assert False
+ where False = g(*[1, 2, 3])""" + where False = g(*[1, 2, 3])"""
def f(): def f():
x = "a" x = "a"
assert g(**{x : 2}) assert g(**{x : 2})
assert getmsg(f, ns) == """assert False assert getmsg(f, ns) == """assert False
+ where False = g(**{'a': 2})""" + where False = g(**{'a': 2})"""
def test_attribute(self): def test_attribute(self):
class X(object): class X(object):
g = 3 g = 3
ns = {"x" : X} ns = {"x" : X}
def f(): def f():
assert not x.g # noqa assert not x.g # noqa
assert getmsg(f, ns) == """assert not 3 assert getmsg(f, ns) == """assert not 3
+ where 3 = x.g""" + where 3 = x.g"""
def f(): def f():
x.a = False # noqa x.a = False # noqa
assert x.a # noqa assert x.a # noqa
assert getmsg(f, ns) == """assert False assert getmsg(f, ns) == """assert False
+ where False = x.a""" + where False = x.a"""
def test_comparisons(self): def test_comparisons(self):
def f(): def f():
a, b = range(2) a, b = range(2)
assert b < a assert b < a
assert getmsg(f) == """assert 1 < 0""" assert getmsg(f) == """assert 1 < 0"""
def f(): def f():
a, b, c = range(3) a, b, c = range(3)
assert a > b > c assert a > b > c
assert getmsg(f) == """assert 0 > 1""" assert getmsg(f) == """assert 0 > 1"""
def f(): def f():
a, b, c = range(3) a, b, c = range(3)
assert a < b > c assert a < b > c
assert getmsg(f) == """assert 1 > 2""" assert getmsg(f) == """assert 1 > 2"""
def f(): def f():
a, b, c = range(3) a, b, c = range(3)
assert a < b <= c assert a < b <= c
getmsg(f, must_pass=True) getmsg(f, must_pass=True)
def f(): def f():
a, b, c = range(3) a, b, c = range(3)
assert a < b assert a < b
assert b < c assert b < c
getmsg(f, must_pass=True) getmsg(f, must_pass=True)
def test_len(self): def test_len(self):
def f(): def f():
l = list(range(10)) l = list(range(10))
assert len(l) == 11 assert len(l) == 11
assert getmsg(f).startswith("""assert 10 == 11 assert getmsg(f).startswith("""assert 10 == 11
+ where 10 = len([""") + where 10 = len([""")
def test_custom_reprcompare(self, monkeypatch): def test_custom_reprcompare(self, monkeypatch):
def my_reprcompare(op, left, right): def my_reprcompare(op, left, right):
return "42" return "42"
monkeypatch.setattr(util, "_reprcompare", my_reprcompare) monkeypatch.setattr(util, "_reprcompare", my_reprcompare)
def f(): def f():
assert 42 < 3 assert 42 < 3
assert getmsg(f) == "assert 42" assert getmsg(f) == "assert 42"
def my_reprcompare(op, left, right): def my_reprcompare(op, left, right):
return "%s %s %s" % (left, op, right) return "%s %s %s" % (left, op, right)
monkeypatch.setattr(util, "_reprcompare", my_reprcompare) monkeypatch.setattr(util, "_reprcompare", my_reprcompare)
def f(): def f():
assert 1 < 3 < 5 <= 4 < 7 assert 1 < 3 < 5 <= 4 < 7
assert getmsg(f) == "assert 5 <= 4" assert getmsg(f) == "assert 5 <= 4"
def test_assert_raising_nonzero_in_comparison(self): def test_assert_raising_nonzero_in_comparison(self):
def f(): def f():
class A(object): class A(object):
def __nonzero__(self): def __nonzero__(self):
raise ValueError(42) raise ValueError(42)
def __lt__(self, other): def __lt__(self, other):
return A() return A()
def __repr__(self): def __repr__(self):
return "<MY42 object>" return "<MY42 object>"
def myany(x): def myany(x):
return False return False
assert myany(A() < 0) assert myany(A() < 0)
assert "<MY42 object> < 0" in getmsg(f) assert "<MY42 object> < 0" in getmsg(f)
def test_formatchar(self): def test_formatchar(self):
def f(): def f():
assert "%test" == "test" assert "%test" == "test"
assert getmsg(f).startswith("assert '%test' == 'test'") assert getmsg(f).startswith("assert '%test' == 'test'")
def test_custom_repr(self): def test_custom_repr(self):
@ -414,8 +505,10 @@ class TestAssertionRewrite:
def __repr__(self): def __repr__(self):
return "\n{ \n~ \n}" return "\n{ \n~ \n}"
f = Foo() f = Foo()
assert 0 == f.a assert 0 == f.a
assert r"where 1 = \n{ \n~ \n}.a" in util._format_lines([getmsg(f)])[0] assert r"where 1 = \n{ \n~ \n}.a" in util._format_lines([getmsg(f)])[0]
@ -527,8 +620,10 @@ def test_rewritten():
def test_rewrite_warning(self, pytestconfig, monkeypatch): def test_rewrite_warning(self, pytestconfig, monkeypatch):
hook = AssertionRewritingHook(pytestconfig) hook = AssertionRewritingHook(pytestconfig)
warnings = [] warnings = []
def mywarn(code, msg): def mywarn(code, msg):
warnings.append((code, msg)) warnings.append((code, msg))
monkeypatch.setattr(hook.config, 'warn', mywarn) monkeypatch.setattr(hook.config, 'warn', mywarn)
hook.mark_rewrite('_pytest') hook.mark_rewrite('_pytest')
assert '_pytest' in warnings[0][1] assert '_pytest' in warnings[0][1]
@ -642,10 +737,12 @@ class TestAssertionRewriteHookDetails(object):
source_path = tmpdir.ensure("source.py") source_path = tmpdir.ensure("source.py")
pycpath = tmpdir.join("pyc").strpath pycpath = tmpdir.join("pyc").strpath
assert _write_pyc(state, [1], source_path.stat(), pycpath) assert _write_pyc(state, [1], source_path.stat(), pycpath)
def open(*args): def open(*args):
e = IOError() e = IOError()
e.errno = 10 e.errno = 10
raise e raise e
monkeypatch.setattr(b, "open", open) monkeypatch.setattr(b, "open", open)
assert not _write_pyc(state, [1], source_path.stat(), pycpath) assert not _write_pyc(state, [1], source_path.stat(), pycpath)

View File

@ -150,11 +150,13 @@ class TestCollectFS:
class TestCollectPluginHookRelay: class TestCollectPluginHookRelay:
def test_pytest_collect_file(self, testdir): def test_pytest_collect_file(self, testdir):
wascalled = [] wascalled = []
class Plugin: class Plugin:
def pytest_collect_file(self, path, parent): def pytest_collect_file(self, path, parent):
if not path.basename.startswith("."): if not path.basename.startswith("."):
# Ignore hidden files, e.g. .testmondata. # Ignore hidden files, e.g. .testmondata.
wascalled.append(path) wascalled.append(path)
testdir.makefile(".abc", "xyz") testdir.makefile(".abc", "xyz")
pytest.main([testdir.tmpdir], plugins=[Plugin()]) pytest.main([testdir.tmpdir], plugins=[Plugin()])
assert len(wascalled) == 1 assert len(wascalled) == 1
@ -162,15 +164,18 @@ class TestCollectPluginHookRelay:
def test_pytest_collect_directory(self, testdir): def test_pytest_collect_directory(self, testdir):
wascalled = [] wascalled = []
class Plugin: class Plugin:
def pytest_collect_directory(self, path, parent): def pytest_collect_directory(self, path, parent):
wascalled.append(path.basename) wascalled.append(path.basename)
testdir.mkdir("hello") testdir.mkdir("hello")
testdir.mkdir("world") testdir.mkdir("world")
pytest.main(testdir.tmpdir, plugins=[Plugin()]) pytest.main(testdir.tmpdir, plugins=[Plugin()])
assert "hello" in wascalled assert "hello" in wascalled
assert "world" in wascalled assert "world" in wascalled
class TestPrunetraceback: class TestPrunetraceback:
def test_custom_repr_failure(self, testdir): def test_custom_repr_failure(self, testdir):

View File

@ -373,23 +373,31 @@ def test_options_on_small_file_do_not_blow_up(testdir):
['--traceconfig'], ['-v'], ['-v', '-v']): ['--traceconfig'], ['-v'], ['-v', '-v']):
runfiletest(opts + [path]) runfiletest(opts + [path])
def test_preparse_ordering_with_setuptools(testdir, monkeypatch): def test_preparse_ordering_with_setuptools(testdir, monkeypatch):
pkg_resources = pytest.importorskip("pkg_resources") pkg_resources = pytest.importorskip("pkg_resources")
def my_iter(name): def my_iter(name):
assert name == "pytest11" assert name == "pytest11"
class Dist: class Dist:
project_name = 'spam' project_name = 'spam'
version = '1.0' version = '1.0'
def _get_metadata(self, name): def _get_metadata(self, name):
return ['foo.txt,sha256=abc,123'] return ['foo.txt,sha256=abc,123']
class EntryPoint: class EntryPoint:
name = "mytestplugin" name = "mytestplugin"
dist = Dist() dist = Dist()
def load(self): def load(self):
class PseudoPlugin: class PseudoPlugin:
x = 42 x = 42
return PseudoPlugin() return PseudoPlugin()
return iter([EntryPoint()]) return iter([EntryPoint()])
monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter) monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter)
testdir.makeconftest(""" testdir.makeconftest("""
pytest_plugins = "mytestplugin", pytest_plugins = "mytestplugin",
@ -402,18 +410,24 @@ def test_preparse_ordering_with_setuptools(testdir, monkeypatch):
def test_setuptools_importerror_issue1479(testdir, monkeypatch): def test_setuptools_importerror_issue1479(testdir, monkeypatch):
pkg_resources = pytest.importorskip("pkg_resources") pkg_resources = pytest.importorskip("pkg_resources")
def my_iter(name): def my_iter(name):
assert name == "pytest11" assert name == "pytest11"
class Dist: class Dist:
project_name = 'spam' project_name = 'spam'
version = '1.0' version = '1.0'
def _get_metadata(self, name): def _get_metadata(self, name):
return ['foo.txt,sha256=abc,123'] return ['foo.txt,sha256=abc,123']
class EntryPoint: class EntryPoint:
name = "mytestplugin" name = "mytestplugin"
dist = Dist() dist = Dist()
def load(self): def load(self):
raise ImportError("Don't hide me!") raise ImportError("Don't hide me!")
return iter([EntryPoint()]) return iter([EntryPoint()])
monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter) monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter)
@ -423,19 +437,26 @@ def test_setuptools_importerror_issue1479(testdir, monkeypatch):
def test_plugin_preparse_prevents_setuptools_loading(testdir, monkeypatch): def test_plugin_preparse_prevents_setuptools_loading(testdir, monkeypatch):
pkg_resources = pytest.importorskip("pkg_resources") pkg_resources = pytest.importorskip("pkg_resources")
def my_iter(name): def my_iter(name):
assert name == "pytest11" assert name == "pytest11"
class Dist: class Dist:
project_name = 'spam' project_name = 'spam'
version = '1.0' version = '1.0'
def _get_metadata(self, name): def _get_metadata(self, name):
return ['foo.txt,sha256=abc,123'] return ['foo.txt,sha256=abc,123']
class EntryPoint: class EntryPoint:
name = "mytestplugin" name = "mytestplugin"
dist = Dist() dist = Dist()
def load(self): def load(self):
assert 0, "should not arrive here" assert 0, "should not arrive here"
return iter([EntryPoint()]) return iter([EntryPoint()])
monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter) monkeypatch.setattr(pkg_resources, 'iter_entry_points', my_iter)
config = testdir.parseconfig("-p", "no:mytestplugin") config = testdir.parseconfig("-p", "no:mytestplugin")
plugin = config.pluginmanager.getplugin("mytestplugin") plugin = config.pluginmanager.getplugin("mytestplugin")
@ -503,9 +524,11 @@ def test_notify_exception(testdir, capfd):
config.notify_exception(excinfo) config.notify_exception(excinfo)
out, err = capfd.readouterr() out, err = capfd.readouterr()
assert "ValueError" in err assert "ValueError" in err
class A: class A:
def pytest_internalerror(self, excrepr): def pytest_internalerror(self, excrepr):
return True return True
config.pluginmanager.register(A()) config.pluginmanager.register(A())
config.notify_exception(excinfo) config.notify_exception(excinfo)
out, err = capfd.readouterr() out, err = capfd.readouterr()
@ -515,9 +538,11 @@ def test_notify_exception(testdir, capfd):
def test_load_initial_conftest_last_ordering(testdir): def test_load_initial_conftest_last_ordering(testdir):
from _pytest.config import get_config from _pytest.config import get_config
pm = get_config().pluginmanager pm = get_config().pluginmanager
class My: class My:
def pytest_load_initial_conftests(self): def pytest_load_initial_conftests(self):
pass pass
m = My() m = My()
pm.register(m) pm.register(m)
hc = pm.hook.pytest_load_initial_conftests hc = pm.hook.pytest_load_initial_conftests

View File

@ -200,8 +200,10 @@ def test_conftest_import_order(testdir, monkeypatch):
sub = testdir.mkdir("sub") sub = testdir.mkdir("sub")
ct2 = sub.join("conftest.py") ct2 = sub.join("conftest.py")
ct2.write("") ct2.write("")
def impct(p): def impct(p):
return p return p
conftest = PytestPluginManager() conftest = PytestPluginManager()
conftest._confcutdir = testdir.tmpdir conftest._confcutdir = testdir.tmpdir
monkeypatch.setattr(conftest, '_importconftest', impct) monkeypatch.setattr(conftest, '_importconftest', impct)

View File

@ -23,15 +23,19 @@ class TestMark:
def test_pytest_mark_bare(self): def test_pytest_mark_bare(self):
mark = Mark() mark = Mark()
def f(): def f():
pass pass
mark.hello(f) mark.hello(f)
assert f.hello assert f.hello
def test_pytest_mark_keywords(self): def test_pytest_mark_keywords(self):
mark = Mark() mark = Mark()
def f(): def f():
pass pass
mark.world(x=3, y=4)(f) mark.world(x=3, y=4)(f)
assert f.world assert f.world
assert f.world.kwargs['x'] == 3 assert f.world.kwargs['x'] == 3
@ -39,8 +43,10 @@ class TestMark:
def test_apply_multiple_and_merge(self): def test_apply_multiple_and_merge(self):
mark = Mark() mark = Mark()
def f(): def f():
pass pass
mark.world mark.world
mark.world(x=3)(f) mark.world(x=3)(f)
assert f.world.kwargs['x'] == 3 assert f.world.kwargs['x'] == 3
@ -53,33 +59,43 @@ class TestMark:
def test_pytest_mark_positional(self): def test_pytest_mark_positional(self):
mark = Mark() mark = Mark()
def f(): def f():
pass pass
mark.world("hello")(f) mark.world("hello")(f)
assert f.world.args[0] == "hello" assert f.world.args[0] == "hello"
mark.world("world")(f) mark.world("world")(f)
def test_pytest_mark_positional_func_and_keyword(self): def test_pytest_mark_positional_func_and_keyword(self):
mark = Mark() mark = Mark()
def f(): def f():
raise Exception raise Exception
m = mark.world(f, omega="hello") m = mark.world(f, omega="hello")
def g(): def g():
pass pass
assert m(g) == g assert m(g) == g
assert g.world.args[0] is f assert g.world.args[0] is f
assert g.world.kwargs["omega"] == "hello" assert g.world.kwargs["omega"] == "hello"
def test_pytest_mark_reuse(self): def test_pytest_mark_reuse(self):
mark = Mark() mark = Mark()
def f(): def f():
pass pass
w = mark.some w = mark.some
w("hello", reason="123")(f) w("hello", reason="123")(f)
assert f.some.args[0] == "hello" assert f.some.args[0] == "hello"
assert f.some.kwargs['reason'] == "123" assert f.some.kwargs['reason'] == "123"
def g(): def g():
pass pass
w("world", reason2="456")(g) w("world", reason2="456")(g)
assert g.some.args[0] == "world" assert g.some.args[0] == "world"
assert 'reason' not in g.some.kwargs assert 'reason' not in g.some.kwargs
@ -610,11 +626,12 @@ class TestFunctional:
def test_1(parameter): def test_1(parameter):
assert True assert True
""") """)
reprec = testdir.inline_run() reprec = testdir.inline_run()
reprec.assertoutcome(skipped=1) reprec.assertoutcome(skipped=1)
class TestKeywordSelection: class TestKeywordSelection:
def test_select_simple(self, testdir): def test_select_simple(self, testdir):
file_test = testdir.makepyfile(""" file_test = testdir.makepyfile("""
def test_one(): def test_one():
@ -623,6 +640,7 @@ class TestKeywordSelection:
def test_method_one(self): def test_method_one(self):
assert 42 == 43 assert 42 == 43
""") """)
def check(keyword, name): def check(keyword, name):
reprec = testdir.inline_run("-s", "-k", keyword, file_test) reprec = testdir.inline_run("-s", "-k", keyword, file_test)
passed, skipped, failed = reprec.listoutcomes() passed, skipped, failed = reprec.listoutcomes()
@ -709,6 +727,7 @@ class TestKeywordSelection:
p = testdir.makepyfile(""" p = testdir.makepyfile("""
def test_one(): assert 1 def test_one(): assert 1
""") """)
def assert_test_is_not_selected(keyword): def assert_test_is_not_selected(keyword):
reprec = testdir.inline_run("-k", keyword, p) reprec = testdir.inline_run("-k", keyword, p)
passed, skipped, failed = reprec.countoutcomes() passed, skipped, failed = reprec.countoutcomes()

View File

@ -25,18 +25,22 @@ def test_nose_setup(testdir):
def test_setup_func_with_setup_decorator(): def test_setup_func_with_setup_decorator():
from _pytest.nose import call_optional from _pytest.nose import call_optional
l = [] l = []
class A: class A:
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def f(self): def f(self):
l.append(1) l.append(1)
call_optional(A(), "f") call_optional(A(), "f")
assert not l assert not l
def test_setup_func_not_callable(): def test_setup_func_not_callable():
from _pytest.nose import call_optional from _pytest.nose import call_optional
class A: class A:
f = 1 f = 1
call_optional(A(), "f") call_optional(A(), "f")
def test_nose_setup_func(testdir): def test_nose_setup_func(testdir):

View File

@ -138,7 +138,10 @@ class TestParser:
def test_parse_setoption(self, parser): def test_parse_setoption(self, parser):
parser.addoption("--hello", dest="hello", action="store") parser.addoption("--hello", dest="hello", action="store")
parser.addoption("--world", dest="world", default=42) parser.addoption("--world", dest="world", default=42)
class A: pass
class A:
pass
option = A() option = A()
args = parser.parse_setoption(['--hello', 'world'], option) args = parser.parse_setoption(['--hello', 'world'], option)
assert option.hello == "world" assert option.hello == "world"

View File

@ -84,8 +84,10 @@ class TestPaste:
function that connects to bpaste service. function that connects to bpaste service.
""" """
calls = [] calls = []
def mocked(url, data): def mocked(url, data):
calls.append((url, data)) calls.append((url, data))
class DummyFile: class DummyFile:
def read(self): def read(self):
# part of html of a normal response # part of html of a normal response

View File

@ -39,8 +39,10 @@ class TestPDB:
def pdblist(self, request): def pdblist(self, request):
monkeypatch = request.getfixturevalue("monkeypatch") monkeypatch = request.getfixturevalue("monkeypatch")
pdblist = [] pdblist = []
def mypdb(*args): def mypdb(*args):
pdblist.append(args) pdblist.append(args)
plugin = request.config.pluginmanager.getplugin('debugging') plugin = request.config.pluginmanager.getplugin('debugging')
monkeypatch.setattr(plugin, 'post_mortem', mypdb) monkeypatch.setattr(plugin, 'post_mortem', mypdb)
return pdblist return pdblist

View File

@ -83,6 +83,7 @@ class TestPytestPluginInteractions:
def test_configure(self, testdir): def test_configure(self, testdir):
config = testdir.parseconfig() config = testdir.parseconfig()
l = [] l = []
class A: class A:
def pytest_configure(self, config): def pytest_configure(self, config):
l.append(self) l.append(self)
@ -102,13 +103,16 @@ class TestPytestPluginInteractions:
def test_hook_tracing(self): def test_hook_tracing(self):
pytestpm = get_config().pluginmanager # fully initialized with plugins pytestpm = get_config().pluginmanager # fully initialized with plugins
saveindent = [] saveindent = []
class api1: class api1:
def pytest_plugin_registered(self): def pytest_plugin_registered(self):
saveindent.append(pytestpm.trace.root.indent) saveindent.append(pytestpm.trace.root.indent)
class api2: class api2:
def pytest_plugin_registered(self): def pytest_plugin_registered(self):
saveindent.append(pytestpm.trace.root.indent) saveindent.append(pytestpm.trace.root.indent)
raise ValueError() raise ValueError()
l = [] l = []
pytestpm.trace.root.setwriter(l.append) pytestpm.trace.root.setwriter(l.append)
undo = pytestpm.enable_tracing() undo = pytestpm.enable_tracing()

View File

@ -11,6 +11,7 @@ def test_make_hook_recorder(testdir):
assert not recorder.getfailures() assert not recorder.getfailures()
pytest.xfail("internal reportrecorder tests need refactoring") pytest.xfail("internal reportrecorder tests need refactoring")
class rep: class rep:
excinfo = None excinfo = None
passed = False passed = False
@ -80,10 +81,13 @@ def make_holder():
"x" "x"
apimod = type(os)('api') apimod = type(os)('api')
def pytest_xyz(arg): def pytest_xyz(arg):
"x" "x"
def pytest_xyz_noarg(): def pytest_xyz_noarg():
"x" "x"
apimod.pytest_xyz = pytest_xyz apimod.pytest_xyz = pytest_xyz
apimod.pytest_xyz_noarg = pytest_xyz_noarg apimod.pytest_xyz_noarg = pytest_xyz_noarg
return apiclass, apimod return apiclass, apimod

View File

@ -38,9 +38,13 @@ class TestSetupState:
def test_teardown_multiple_one_fails(self, testdir): def test_teardown_multiple_one_fails(self, testdir):
r = [] r = []
def fin1(): r.append('fin1') def fin1(): r.append('fin1')
def fin2(): raise Exception('oops') def fin2(): raise Exception('oops')
def fin3(): r.append('fin3') def fin3(): r.append('fin3')
item = testdir.getitem("def test_func(): pass") item = testdir.getitem("def test_func(): pass")
ss = runner.SetupState() ss = runner.SetupState()
ss.addfinalizer(fin1, item) ss.addfinalizer(fin1, item)
@ -55,7 +59,9 @@ class TestSetupState:
# Ensure the first exception is the one which is re-raised. # Ensure the first exception is the one which is re-raised.
# Ideally both would be reported however. # Ideally both would be reported however.
def fin1(): raise Exception('oops1') def fin1(): raise Exception('oops1')
def fin2(): raise Exception('oops2') def fin2(): raise Exception('oops2')
item = testdir.getitem("def test_func(): pass") item = testdir.getitem("def test_func(): pass")
ss = runner.SetupState() ss = runner.SetupState()
ss.addfinalizer(fin1, item) ss.addfinalizer(fin1, item)
@ -527,8 +533,10 @@ def test_exception_printing_skip():
def test_importorskip(monkeypatch): def test_importorskip(monkeypatch):
importorskip = pytest.importorskip importorskip = pytest.importorskip
def f(): def f():
importorskip("asdlkj") importorskip("asdlkj")
try: try:
sys = importorskip("sys") # noqa sys = importorskip("sys") # noqa
assert sys == py.std.sys assert sys == py.std.sys
@ -643,11 +651,13 @@ def test_makereport_getsource_dynamic_code(testdir, monkeypatch):
"""Test that exception in dynamically generated code doesn't break getting the source line.""" """Test that exception in dynamically generated code doesn't break getting the source line."""
import inspect import inspect
original_findsource = inspect.findsource original_findsource = inspect.findsource
def findsource(obj, *args, **kwargs): def findsource(obj, *args, **kwargs):
# Can be triggered by dynamically created functions # Can be triggered by dynamically created functions
if obj.__name__ == 'foo': if obj.__name__ == 'foo':
raise IndexError() raise IndexError()
return original_findsource(obj, *args, **kwargs) return original_findsource(obj, *args, **kwargs)
monkeypatch.setattr(inspect, 'findsource', findsource) monkeypatch.setattr(inspect, 'findsource', findsource)
testdir.makepyfile(""" testdir.makepyfile("""

View File

@ -175,3 +175,4 @@ norecursedirs = .tox ja .hg cx_freeze_source
[flake8] [flake8]
ignore =E401,E225,E261,E128,E124,E301,E302,E121,E303,W391,E501,E231,E126,E701,E265,E241,E251,E226,E101,W191,E131,E203,E122,E123,E271,E712,E222,E127,E125,E221,W292,E111,E113,E293,E262,W293,E129,E702,E201,E272,E202,E704,E731,E402 ignore =E401,E225,E261,E128,E124,E301,E302,E121,E303,W391,E501,E231,E126,E701,E265,E241,E251,E226,E101,W191,E131,E203,E122,E123,E271,E712,E222,E127,E125,E221,W292,E111,E113,E293,E262,W293,E129,E702,E201,E272,E202,E704,E731,E402
exclude = _pytest/vendored_packages/pluggy.py