Merge remote-tracking branch 'upstream/features' into jonozzz/features
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -6,18 +6,19 @@ import _pytest._code
|
||||
import py
|
||||
import pytest
|
||||
from test_excinfo import TWMock
|
||||
from six import text_type
|
||||
|
||||
|
||||
def test_ne():
|
||||
code1 = _pytest._code.Code(compile('foo = "bar"', '', 'exec'))
|
||||
code1 = _pytest._code.Code(compile('foo = "bar"', "", "exec"))
|
||||
assert code1 == code1
|
||||
code2 = _pytest._code.Code(compile('foo = "baz"', '', 'exec'))
|
||||
code2 = _pytest._code.Code(compile('foo = "baz"', "", "exec"))
|
||||
assert code2 != code1
|
||||
|
||||
|
||||
def test_code_gives_back_name_for_not_existing_file():
|
||||
name = 'abc-123'
|
||||
co_code = compile("pass\n", name, 'exec')
|
||||
name = "abc-123"
|
||||
co_code = compile("pass\n", name, "exec")
|
||||
assert co_code.co_filename == name
|
||||
code = _pytest._code.Code(co_code)
|
||||
assert str(code.path) == name
|
||||
@@ -27,10 +28,12 @@ def test_code_gives_back_name_for_not_existing_file():
|
||||
def test_code_with_class():
|
||||
class A(object):
|
||||
pass
|
||||
|
||||
pytest.raises(TypeError, "_pytest._code.Code(A)")
|
||||
|
||||
|
||||
if True:
|
||||
|
||||
def x():
|
||||
pass
|
||||
|
||||
@@ -38,7 +41,7 @@ if True:
|
||||
def test_code_fullsource():
|
||||
code = _pytest._code.Code(x)
|
||||
full = code.fullsource
|
||||
assert 'test_code_fullsource()' in str(full)
|
||||
assert "test_code_fullsource()" in str(full)
|
||||
|
||||
|
||||
def test_code_source():
|
||||
@@ -52,6 +55,7 @@ def test_code_source():
|
||||
def test_frame_getsourcelineno_myself():
|
||||
def func():
|
||||
return sys._getframe(0)
|
||||
|
||||
f = func()
|
||||
f = _pytest._code.Frame(f)
|
||||
source, lineno = f.code.fullsource, f.lineno
|
||||
@@ -61,6 +65,7 @@ def test_frame_getsourcelineno_myself():
|
||||
def test_getstatement_empty_fullsource():
|
||||
def func():
|
||||
return sys._getframe(0)
|
||||
|
||||
f = func()
|
||||
f = _pytest._code.Frame(f)
|
||||
prop = f.code.__class__.fullsource
|
||||
@@ -78,7 +83,7 @@ def test_code_from_func():
|
||||
|
||||
|
||||
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():
|
||||
raise Exception(value)
|
||||
@@ -86,69 +91,75 @@ def test_unicode_handling():
|
||||
excinfo = pytest.raises(Exception, f)
|
||||
str(excinfo)
|
||||
if sys.version_info[0] < 3:
|
||||
unicode(excinfo)
|
||||
text_type(excinfo)
|
||||
|
||||
|
||||
@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():
|
||||
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():
|
||||
raise SyntaxError('invalid syntax', (None, 1, 3, value))
|
||||
raise SyntaxError("invalid syntax", (None, 1, 3, value))
|
||||
|
||||
excinfo = pytest.raises(Exception, f)
|
||||
str(excinfo)
|
||||
if sys.version_info[0] < 3:
|
||||
unicode(excinfo)
|
||||
text_type(excinfo)
|
||||
|
||||
|
||||
def test_code_getargs():
|
||||
def f1(x):
|
||||
pass
|
||||
|
||||
c1 = _pytest._code.Code(f1)
|
||||
assert c1.getargs(var=True) == ('x',)
|
||||
assert c1.getargs(var=True) == ("x",)
|
||||
|
||||
def f2(x, *y):
|
||||
pass
|
||||
|
||||
c2 = _pytest._code.Code(f2)
|
||||
assert c2.getargs(var=True) == ('x', 'y')
|
||||
assert c2.getargs(var=True) == ("x", "y")
|
||||
|
||||
def f3(x, **z):
|
||||
pass
|
||||
|
||||
c3 = _pytest._code.Code(f3)
|
||||
assert c3.getargs(var=True) == ('x', 'z')
|
||||
assert c3.getargs(var=True) == ("x", "z")
|
||||
|
||||
def f4(x, *y, **z):
|
||||
pass
|
||||
|
||||
c4 = _pytest._code.Code(f4)
|
||||
assert c4.getargs(var=True) == ('x', 'y', 'z')
|
||||
assert c4.getargs(var=True) == ("x", "y", "z")
|
||||
|
||||
|
||||
def test_frame_getargs():
|
||||
def f1(x):
|
||||
return sys._getframe(0)
|
||||
fr1 = _pytest._code.Frame(f1('a'))
|
||||
assert fr1.getargs(var=True) == [('x', 'a')]
|
||||
|
||||
fr1 = _pytest._code.Frame(f1("a"))
|
||||
assert fr1.getargs(var=True) == [("x", "a")]
|
||||
|
||||
def f2(x, *y):
|
||||
return sys._getframe(0)
|
||||
fr2 = _pytest._code.Frame(f2('a', 'b', 'c'))
|
||||
assert fr2.getargs(var=True) == [('x', 'a'), ('y', ('b', 'c'))]
|
||||
|
||||
fr2 = _pytest._code.Frame(f2("a", "b", "c"))
|
||||
assert fr2.getargs(var=True) == [("x", "a"), ("y", ("b", "c"))]
|
||||
|
||||
def f3(x, **z):
|
||||
return sys._getframe(0)
|
||||
fr3 = _pytest._code.Frame(f3('a', b='c'))
|
||||
assert fr3.getargs(var=True) == [('x', 'a'), ('z', {'b': 'c'})]
|
||||
|
||||
fr3 = _pytest._code.Frame(f3("a", b="c"))
|
||||
assert fr3.getargs(var=True) == [("x", "a"), ("z", {"b": "c"})]
|
||||
|
||||
def f4(x, *y, **z):
|
||||
return sys._getframe(0)
|
||||
fr4 = _pytest._code.Frame(f4('a', 'b', c='d'))
|
||||
assert fr4.getargs(var=True) == [('x', 'a'), ('y', ('b',)),
|
||||
('z', {'c': 'd'})]
|
||||
|
||||
fr4 = _pytest._code.Frame(f4("a", "b", c="d"))
|
||||
assert fr4.getargs(var=True) == [("x", "a"), ("y", ("b",)), ("z", {"c": "d"})]
|
||||
|
||||
|
||||
class TestExceptionInfo(object):
|
||||
|
||||
def test_bad_getsource(self):
|
||||
try:
|
||||
if False:
|
||||
@@ -161,7 +172,6 @@ class TestExceptionInfo(object):
|
||||
|
||||
|
||||
class TestTracebackEntry(object):
|
||||
|
||||
def test_getsource(self):
|
||||
try:
|
||||
if False:
|
||||
@@ -173,24 +183,20 @@ class TestTracebackEntry(object):
|
||||
entry = exci.traceback[0]
|
||||
source = entry.getsource()
|
||||
assert len(source) == 6
|
||||
assert 'assert False' in source[5]
|
||||
assert "assert False" in source[5]
|
||||
|
||||
|
||||
class TestReprFuncArgs(object):
|
||||
|
||||
def test_not_raise_exception_with_mixed_encoding(self):
|
||||
from _pytest._code.code import ReprFuncArgs
|
||||
|
||||
tw = TWMock()
|
||||
|
||||
args = [
|
||||
('unicode_string', u"São Paulo"),
|
||||
('utf8_string', 'S\xc3\xa3o Paulo'),
|
||||
]
|
||||
args = [("unicode_string", u"São Paulo"), ("utf8_string", "S\xc3\xa3o Paulo")]
|
||||
|
||||
r = ReprFuncArgs(args)
|
||||
r.toterminal(tw)
|
||||
if sys.version_info[0] >= 3:
|
||||
assert tw.lines[0] == 'unicode_string = São Paulo, utf8_string = São Paulo'
|
||||
assert tw.lines[0] == "unicode_string = São Paulo, utf8_string = São Paulo"
|
||||
else:
|
||||
assert tw.lines[0] == 'unicode_string = São Paulo, utf8_string = São Paulo'
|
||||
assert tw.lines[0] == "unicode_string = São Paulo, utf8_string = São Paulo"
|
||||
|
||||
@@ -11,7 +11,9 @@ from _pytest._code.code import (
|
||||
ExceptionInfo,
|
||||
FormattedExcinfo,
|
||||
ReprExceptionInfo,
|
||||
ExceptionChainRepr)
|
||||
ExceptionChainRepr,
|
||||
)
|
||||
from six.moves import queue
|
||||
|
||||
from test_source import astonly
|
||||
|
||||
@@ -22,8 +24,6 @@ except ImportError:
|
||||
else:
|
||||
invalidate_import_caches = getattr(importlib, "invalidate_caches", None)
|
||||
|
||||
queue = py.builtin._tryimport('queue', 'Queue')
|
||||
|
||||
failsonjython = pytest.mark.xfail("sys.platform.startswith('java')")
|
||||
|
||||
pytest_version_info = tuple(map(int, pytest.__version__.split(".")[:3]))
|
||||
@@ -75,9 +75,11 @@ def test_excinfo_getstatement():
|
||||
f()
|
||||
except ValueError:
|
||||
excinfo = _pytest._code.ExceptionInfo()
|
||||
linenumbers = [_pytest._code.getrawcode(f).co_firstlineno - 1 + 4,
|
||||
_pytest._code.getrawcode(f).co_firstlineno - 1 + 1,
|
||||
_pytest._code.getrawcode(g).co_firstlineno - 1 + 1, ]
|
||||
linenumbers = [
|
||||
_pytest._code.getrawcode(f).co_firstlineno - 1 + 4,
|
||||
_pytest._code.getrawcode(f).co_firstlineno - 1 + 1,
|
||||
_pytest._code.getrawcode(g).co_firstlineno - 1 + 1,
|
||||
]
|
||||
values = list(excinfo.traceback)
|
||||
foundlinenumbers = [x.lineno for x in values]
|
||||
assert foundlinenumbers == linenumbers
|
||||
@@ -85,6 +87,7 @@ def test_excinfo_getstatement():
|
||||
# print "%s:%d %s" %(x.path.relto(root), x.lineno, x.statement)
|
||||
# xxx
|
||||
|
||||
|
||||
# testchain for getentries test below
|
||||
|
||||
|
||||
@@ -119,7 +122,7 @@ class TestTraceback_f_g_h(object):
|
||||
entries = list(tb)
|
||||
assert len(tb) == 4 # maybe fragile test
|
||||
assert len(entries) == 4 # maybe fragile test
|
||||
names = ['f', 'g', 'h']
|
||||
names = ["f", "g", "h"]
|
||||
for entry in entries:
|
||||
try:
|
||||
names.remove(entry.frame.code.name)
|
||||
@@ -136,14 +139,16 @@ class TestTraceback_f_g_h(object):
|
||||
@astonly
|
||||
@failsonjython
|
||||
def test_traceback_entry_getsource_in_construct(self):
|
||||
source = _pytest._code.Source("""\
|
||||
source = _pytest._code.Source(
|
||||
"""\
|
||||
def xyz():
|
||||
try:
|
||||
raise ValueError
|
||||
except somenoname:
|
||||
pass
|
||||
xyz()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
try:
|
||||
exec(source.compile())
|
||||
except NameError:
|
||||
@@ -168,7 +173,7 @@ class TestTraceback_f_g_h(object):
|
||||
basedir = py.path.local(pytest.__file__).dirpath()
|
||||
newtraceback = excinfo.traceback.cut(excludepath=basedir)
|
||||
for x in newtraceback:
|
||||
if hasattr(x, 'path'):
|
||||
if hasattr(x, "path"):
|
||||
assert not py.path.local(x.path).relto(basedir)
|
||||
assert newtraceback[-1].frame.code.path == p
|
||||
|
||||
@@ -177,12 +182,15 @@ class TestTraceback_f_g_h(object):
|
||||
ntraceback = traceback.filter()
|
||||
assert len(ntraceback) == len(traceback) - 1
|
||||
|
||||
@pytest.mark.parametrize('tracebackhide, matching', [
|
||||
(lambda info: True, True),
|
||||
(lambda info: False, False),
|
||||
(operator.methodcaller('errisinstance', ValueError), True),
|
||||
(operator.methodcaller('errisinstance', IndexError), False),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"tracebackhide, matching",
|
||||
[
|
||||
(lambda info: True, True),
|
||||
(lambda info: False, False),
|
||||
(operator.methodcaller("errisinstance", ValueError), True),
|
||||
(operator.methodcaller("errisinstance", IndexError), False),
|
||||
],
|
||||
)
|
||||
def test_traceback_filter_selective(self, tracebackhide, matching):
|
||||
def f():
|
||||
#
|
||||
@@ -203,8 +211,8 @@ class TestTraceback_f_g_h(object):
|
||||
excinfo = pytest.raises(ValueError, h)
|
||||
traceback = excinfo.traceback
|
||||
ntraceback = traceback.filter()
|
||||
print('old: {0!r}'.format(traceback))
|
||||
print('new: {0!r}'.format(ntraceback))
|
||||
print("old: {!r}".format(traceback))
|
||||
print("new: {!r}".format(ntraceback))
|
||||
|
||||
if matching:
|
||||
assert len(ntraceback) == len(traceback) - 2
|
||||
@@ -217,6 +225,7 @@ class TestTraceback_f_g_h(object):
|
||||
if n < 10:
|
||||
n += 1
|
||||
f(n)
|
||||
|
||||
excinfo = pytest.raises(RuntimeError, f, 8)
|
||||
traceback = excinfo.traceback
|
||||
recindex = traceback.recursionindex()
|
||||
@@ -239,6 +248,7 @@ class TestTraceback_f_g_h(object):
|
||||
|
||||
def reraise_me():
|
||||
import sys
|
||||
|
||||
exc, val, tb = sys.exc_info()
|
||||
py.builtin._reraise(exc, val, tb)
|
||||
|
||||
@@ -255,15 +265,16 @@ class TestTraceback_f_g_h(object):
|
||||
|
||||
def test_traceback_messy_recursion(self):
|
||||
# XXX: simplified locally testable version
|
||||
decorator = pytest.importorskip('decorator').decorator
|
||||
decorator = pytest.importorskip("decorator").decorator
|
||||
|
||||
def log(f, *k, **kw):
|
||||
print('%s %s' % (k, kw))
|
||||
print("%s %s" % (k, kw))
|
||||
f(*k, **kw)
|
||||
|
||||
log = decorator(log)
|
||||
|
||||
def fail():
|
||||
raise ValueError('')
|
||||
raise ValueError("")
|
||||
|
||||
fail = log(log(fail))
|
||||
|
||||
@@ -291,7 +302,7 @@ class TestTraceback_f_g_h(object):
|
||||
co = _pytest._code.Code(h)
|
||||
assert entry.frame.code.path == co.path
|
||||
assert entry.lineno == co.firstlineno + 1
|
||||
assert entry.frame.code.name == 'h'
|
||||
assert entry.frame.code.name == "h"
|
||||
|
||||
def test_traceback_getcrashentry_empty(self):
|
||||
def g():
|
||||
@@ -308,16 +319,15 @@ class TestTraceback_f_g_h(object):
|
||||
co = _pytest._code.Code(g)
|
||||
assert entry.frame.code.path == co.path
|
||||
assert entry.lineno == co.firstlineno + 2
|
||||
assert entry.frame.code.name == 'g'
|
||||
assert entry.frame.code.name == "g"
|
||||
|
||||
|
||||
def test_excinfo_exconly():
|
||||
excinfo = pytest.raises(ValueError, h)
|
||||
assert excinfo.exconly().startswith('ValueError')
|
||||
excinfo = pytest.raises(ValueError,
|
||||
"raise ValueError('hello\\nworld')")
|
||||
assert excinfo.exconly().startswith("ValueError")
|
||||
excinfo = pytest.raises(ValueError, "raise ValueError('hello\\nworld')")
|
||||
msg = excinfo.exconly(tryshort=True)
|
||||
assert msg.startswith('ValueError')
|
||||
assert msg.startswith("ValueError")
|
||||
assert msg.endswith("world")
|
||||
|
||||
|
||||
@@ -351,19 +361,18 @@ def test_excinfo_no_sourcecode():
|
||||
|
||||
def test_excinfo_no_python_sourcecode(tmpdir):
|
||||
# XXX: simplified locally testable version
|
||||
tmpdir.join('test.txt').write("{{ h()}}:")
|
||||
tmpdir.join("test.txt").write("{{ h()}}:")
|
||||
|
||||
jinja2 = pytest.importorskip('jinja2')
|
||||
jinja2 = pytest.importorskip("jinja2")
|
||||
loader = jinja2.FileSystemLoader(str(tmpdir))
|
||||
env = jinja2.Environment(loader=loader)
|
||||
template = env.get_template('test.txt')
|
||||
excinfo = pytest.raises(ValueError,
|
||||
template.render, h=h)
|
||||
template = env.get_template("test.txt")
|
||||
excinfo = pytest.raises(ValueError, template.render, h=h)
|
||||
for item in excinfo.traceback:
|
||||
print(item) # XXX: for some reason jinja.Template.render is printed in full
|
||||
item.source # shouldnt fail
|
||||
if item.path.basename == 'test.txt':
|
||||
assert str(item.source) == '{{ h()}}:'
|
||||
if item.path.basename == "test.txt":
|
||||
assert str(item.source) == "{{ h()}}:"
|
||||
|
||||
|
||||
def test_entrysource_Queue_example():
|
||||
@@ -393,26 +402,25 @@ def test_codepath_Queue_example():
|
||||
def test_match_succeeds():
|
||||
with pytest.raises(ZeroDivisionError) as excinfo:
|
||||
0 // 0
|
||||
excinfo.match(r'.*zero.*')
|
||||
excinfo.match(r".*zero.*")
|
||||
|
||||
|
||||
def test_match_raises_error(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def test_division_zero():
|
||||
with pytest.raises(ZeroDivisionError) as excinfo:
|
||||
0 / 0
|
||||
excinfo.match(r'[123]+')
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
assert result.ret != 0
|
||||
result.stdout.fnmatch_lines([
|
||||
"*AssertionError*Pattern*[123]*not found*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*AssertionError*Pattern*[123]*not found*"])
|
||||
|
||||
|
||||
class TestFormattedExcinfo(object):
|
||||
|
||||
@pytest.fixture
|
||||
def importasmod(self, request):
|
||||
def importasmod(source):
|
||||
@@ -424,6 +432,7 @@ class TestFormattedExcinfo(object):
|
||||
if invalidate_import_caches is not None:
|
||||
invalidate_import_caches()
|
||||
return modpath.pyimport()
|
||||
|
||||
return importasmod
|
||||
|
||||
def excinfo_from_exec(self, source):
|
||||
@@ -438,10 +447,12 @@ class TestFormattedExcinfo(object):
|
||||
|
||||
def test_repr_source(self):
|
||||
pr = FormattedExcinfo()
|
||||
source = _pytest._code.Source("""
|
||||
source = _pytest._code.Source(
|
||||
"""
|
||||
def f(x):
|
||||
pass
|
||||
""").strip()
|
||||
"""
|
||||
).strip()
|
||||
pr.flow_marker = "|"
|
||||
lines = pr.get_source(source, 0)
|
||||
assert len(lines) == 2
|
||||
@@ -451,19 +462,17 @@ class TestFormattedExcinfo(object):
|
||||
def test_repr_source_excinfo(self):
|
||||
""" check if indentation is right """
|
||||
pr = FormattedExcinfo()
|
||||
excinfo = self.excinfo_from_exec("""
|
||||
excinfo = self.excinfo_from_exec(
|
||||
"""
|
||||
def f():
|
||||
assert 0
|
||||
f()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
pr = FormattedExcinfo()
|
||||
source = pr._getentrysource(excinfo.traceback[-1])
|
||||
lines = pr.get_source(source, 1, excinfo)
|
||||
assert lines == [
|
||||
' def f():',
|
||||
'> assert 0',
|
||||
'E AssertionError'
|
||||
]
|
||||
assert lines == [" def f():", "> assert 0", "E AssertionError"]
|
||||
|
||||
def test_repr_source_not_existing(self):
|
||||
pr = FormattedExcinfo()
|
||||
@@ -479,10 +488,14 @@ class TestFormattedExcinfo(object):
|
||||
|
||||
def test_repr_many_line_source_not_existing(self):
|
||||
pr = FormattedExcinfo()
|
||||
co = compile("""
|
||||
co = compile(
|
||||
"""
|
||||
a = 1
|
||||
raise ValueError()
|
||||
""", "", "exec")
|
||||
""",
|
||||
"",
|
||||
"exec",
|
||||
)
|
||||
try:
|
||||
exec(co)
|
||||
except ValueError:
|
||||
@@ -497,9 +510,9 @@ raise ValueError()
|
||||
|
||||
class FakeCode(object):
|
||||
class raw(object):
|
||||
co_filename = '?'
|
||||
co_filename = "?"
|
||||
|
||||
path = '?'
|
||||
path = "?"
|
||||
firstlineno = 5
|
||||
|
||||
def fullsource(self):
|
||||
@@ -558,19 +571,21 @@ raise ValueError()
|
||||
|
||||
def test_repr_local(self):
|
||||
p = FormattedExcinfo(showlocals=True)
|
||||
loc = {'y': 5, 'z': 7, 'x': 3, '@x': 2, '__builtins__': {}}
|
||||
loc = {"y": 5, "z": 7, "x": 3, "@x": 2, "__builtins__": {}}
|
||||
reprlocals = p.repr_locals(loc)
|
||||
assert reprlocals.lines
|
||||
assert reprlocals.lines[0] == '__builtins__ = <builtins>'
|
||||
assert reprlocals.lines[1] == 'x = 3'
|
||||
assert reprlocals.lines[2] == 'y = 5'
|
||||
assert reprlocals.lines[3] == 'z = 7'
|
||||
assert reprlocals.lines[0] == "__builtins__ = <builtins>"
|
||||
assert reprlocals.lines[1] == "x = 3"
|
||||
assert reprlocals.lines[2] == "y = 5"
|
||||
assert reprlocals.lines[3] == "z = 7"
|
||||
|
||||
def test_repr_tracebackentry_lines(self, importasmod):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def func1():
|
||||
raise ValueError("hello\\nworld")
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.func1)
|
||||
excinfo.traceback = excinfo.traceback.filter()
|
||||
p = FormattedExcinfo()
|
||||
@@ -578,17 +593,17 @@ raise ValueError()
|
||||
|
||||
# test as intermittent entry
|
||||
lines = reprtb.lines
|
||||
assert lines[0] == ' def func1():'
|
||||
assert lines[0] == " def func1():"
|
||||
assert lines[1] == '> raise ValueError("hello\\nworld")'
|
||||
|
||||
# test as last entry
|
||||
p = FormattedExcinfo(showlocals=True)
|
||||
repr_entry = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
|
||||
lines = repr_entry.lines
|
||||
assert lines[0] == ' def func1():'
|
||||
assert lines[0] == " def func1():"
|
||||
assert lines[1] == '> raise ValueError("hello\\nworld")'
|
||||
assert lines[2] == 'E ValueError: hello'
|
||||
assert lines[3] == 'E world'
|
||||
assert lines[2] == "E ValueError: hello"
|
||||
assert lines[3] == "E world"
|
||||
assert not lines[4:]
|
||||
|
||||
loc = repr_entry.reprlocals is not None
|
||||
@@ -598,42 +613,46 @@ raise ValueError()
|
||||
# assert loc.message == "ValueError: hello"
|
||||
|
||||
def test_repr_tracebackentry_lines2(self, importasmod):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def func1(m, x, y, z):
|
||||
raise ValueError("hello\\nworld")
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.func1, "m" * 90, 5, 13, "z" * 120)
|
||||
excinfo.traceback = excinfo.traceback.filter()
|
||||
entry = excinfo.traceback[-1]
|
||||
p = FormattedExcinfo(funcargs=True)
|
||||
reprfuncargs = p.repr_args(entry)
|
||||
assert reprfuncargs.args[0] == ('m', repr("m" * 90))
|
||||
assert reprfuncargs.args[1] == ('x', '5')
|
||||
assert reprfuncargs.args[2] == ('y', '13')
|
||||
assert reprfuncargs.args[3] == ('z', repr("z" * 120))
|
||||
assert reprfuncargs.args[0] == ("m", repr("m" * 90))
|
||||
assert reprfuncargs.args[1] == ("x", "5")
|
||||
assert reprfuncargs.args[2] == ("y", "13")
|
||||
assert reprfuncargs.args[3] == ("z", repr("z" * 120))
|
||||
|
||||
p = FormattedExcinfo(funcargs=True)
|
||||
repr_entry = p.repr_traceback_entry(entry)
|
||||
assert repr_entry.reprfuncargs.args == reprfuncargs.args
|
||||
tw = TWMock()
|
||||
repr_entry.toterminal(tw)
|
||||
assert tw.lines[0] == "m = " + repr('m' * 90)
|
||||
assert tw.lines[0] == "m = " + repr("m" * 90)
|
||||
assert tw.lines[1] == "x = 5, y = 13"
|
||||
assert tw.lines[2] == "z = " + repr('z' * 120)
|
||||
assert tw.lines[2] == "z = " + repr("z" * 120)
|
||||
|
||||
def test_repr_tracebackentry_lines_var_kw_args(self, importasmod):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def func1(x, *y, **z):
|
||||
raise ValueError("hello\\nworld")
|
||||
""")
|
||||
excinfo = pytest.raises(ValueError, mod.func1, 'a', 'b', c='d')
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.func1, "a", "b", c="d")
|
||||
excinfo.traceback = excinfo.traceback.filter()
|
||||
entry = excinfo.traceback[-1]
|
||||
p = FormattedExcinfo(funcargs=True)
|
||||
reprfuncargs = p.repr_args(entry)
|
||||
assert reprfuncargs.args[0] == ('x', repr('a'))
|
||||
assert reprfuncargs.args[1] == ('y', repr(('b',)))
|
||||
assert reprfuncargs.args[2] == ('z', repr({'c': 'd'}))
|
||||
assert reprfuncargs.args[0] == ("x", repr("a"))
|
||||
assert reprfuncargs.args[1] == ("y", repr(("b",)))
|
||||
assert reprfuncargs.args[2] == ("z", repr({"c": "d"}))
|
||||
|
||||
p = FormattedExcinfo(funcargs=True)
|
||||
repr_entry = p.repr_traceback_entry(entry)
|
||||
@@ -643,18 +662,20 @@ raise ValueError()
|
||||
assert tw.lines[0] == "x = 'a', y = ('b',), z = {'c': 'd'}"
|
||||
|
||||
def test_repr_tracebackentry_short(self, importasmod):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def func1():
|
||||
raise ValueError("hello")
|
||||
def entry():
|
||||
func1()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.entry)
|
||||
p = FormattedExcinfo(style="short")
|
||||
reprtb = p.repr_traceback_entry(excinfo.traceback[-2])
|
||||
lines = reprtb.lines
|
||||
basename = py.path.local(mod.__file__).basename
|
||||
assert lines[0] == ' func1()'
|
||||
assert lines[0] == " func1()"
|
||||
assert basename in str(reprtb.reprfileloc.path)
|
||||
assert reprtb.reprfileloc.lineno == 5
|
||||
|
||||
@@ -663,17 +684,19 @@ raise ValueError()
|
||||
reprtb = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
|
||||
lines = reprtb.lines
|
||||
assert lines[0] == ' raise ValueError("hello")'
|
||||
assert lines[1] == 'E ValueError: hello'
|
||||
assert lines[1] == "E ValueError: hello"
|
||||
assert basename in str(reprtb.reprfileloc.path)
|
||||
assert reprtb.reprfileloc.lineno == 3
|
||||
|
||||
def test_repr_tracebackentry_no(self, importasmod):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def func1():
|
||||
raise ValueError("hello")
|
||||
def entry():
|
||||
func1()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.entry)
|
||||
p = FormattedExcinfo(style="no")
|
||||
p.repr_traceback_entry(excinfo.traceback[-2])
|
||||
@@ -681,16 +704,18 @@ raise ValueError()
|
||||
p = FormattedExcinfo(style="no")
|
||||
reprentry = p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
|
||||
lines = reprentry.lines
|
||||
assert lines[0] == 'E ValueError: hello'
|
||||
assert lines[0] == "E ValueError: hello"
|
||||
assert not lines[1:]
|
||||
|
||||
def test_repr_traceback_tbfilter(self, importasmod):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def f(x):
|
||||
raise ValueError(x)
|
||||
def entry():
|
||||
f(0)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.entry)
|
||||
p = FormattedExcinfo(tbfilter=True)
|
||||
reprtb = p.repr_traceback(excinfo)
|
||||
@@ -700,15 +725,18 @@ raise ValueError()
|
||||
assert len(reprtb.reprentries) == 3
|
||||
|
||||
def test_traceback_short_no_source(self, importasmod, monkeypatch):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def func1():
|
||||
raise ValueError("hello")
|
||||
def entry():
|
||||
func1()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.entry)
|
||||
from _pytest._code.code import Code
|
||||
monkeypatch.setattr(Code, 'path', 'bogus')
|
||||
|
||||
monkeypatch.setattr(Code, "path", "bogus")
|
||||
excinfo.traceback[0].frame.code.path = "bogus"
|
||||
p = FormattedExcinfo(style="short")
|
||||
reprtb = p.repr_traceback_entry(excinfo.traceback[-2])
|
||||
@@ -717,18 +745,20 @@ raise ValueError()
|
||||
last_reprtb = last_p.repr_traceback_entry(excinfo.traceback[-1], excinfo)
|
||||
last_lines = last_reprtb.lines
|
||||
monkeypatch.undo()
|
||||
assert lines[0] == ' func1()'
|
||||
assert lines[0] == " func1()"
|
||||
|
||||
assert last_lines[0] == ' raise ValueError("hello")'
|
||||
assert last_lines[1] == 'E ValueError: hello'
|
||||
assert last_lines[1] == "E ValueError: hello"
|
||||
|
||||
def test_repr_traceback_and_excinfo(self, importasmod):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def f(x):
|
||||
raise ValueError(x)
|
||||
def entry():
|
||||
f(0)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.entry)
|
||||
|
||||
for style in ("long", "short"):
|
||||
@@ -747,12 +777,14 @@ raise ValueError()
|
||||
assert repr.reprcrash.message == "ValueError: 0"
|
||||
|
||||
def test_repr_traceback_with_invalid_cwd(self, importasmod, monkeypatch):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def f(x):
|
||||
raise ValueError(x)
|
||||
def entry():
|
||||
f(0)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.entry)
|
||||
|
||||
p = FormattedExcinfo()
|
||||
@@ -760,15 +792,17 @@ raise ValueError()
|
||||
def raiseos():
|
||||
raise OSError(2)
|
||||
|
||||
monkeypatch.setattr(os, 'getcwd', raiseos)
|
||||
monkeypatch.setattr(os, "getcwd", raiseos)
|
||||
assert p._makepath(__file__) == __file__
|
||||
p.repr_traceback(excinfo)
|
||||
|
||||
def test_repr_excinfo_addouterr(self, importasmod):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def entry():
|
||||
raise ValueError()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.entry)
|
||||
repr = excinfo.getrepr()
|
||||
repr.addsection("title", "content")
|
||||
@@ -778,10 +812,12 @@ raise ValueError()
|
||||
assert twmock.lines[-2] == ("-", "title")
|
||||
|
||||
def test_repr_excinfo_reprcrash(self, importasmod):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def entry():
|
||||
raise ValueError()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.entry)
|
||||
repr = excinfo.getrepr()
|
||||
assert repr.reprcrash.path.endswith("mod.py")
|
||||
@@ -790,14 +826,16 @@ raise ValueError()
|
||||
assert str(repr.reprcrash).endswith("mod.py:3: ValueError")
|
||||
|
||||
def test_repr_traceback_recursion(self, importasmod):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def rec2(x):
|
||||
return rec1(x+1)
|
||||
def rec1(x):
|
||||
return rec2(x-1)
|
||||
def entry():
|
||||
rec1(42)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(RuntimeError, mod.entry)
|
||||
|
||||
for style in ("short", "long", "no"):
|
||||
@@ -807,12 +845,14 @@ raise ValueError()
|
||||
assert str(reprtb)
|
||||
|
||||
def test_reprexcinfo_getrepr(self, importasmod):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def f(x):
|
||||
raise ValueError(x)
|
||||
def entry():
|
||||
f(0)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.entry)
|
||||
|
||||
for style in ("short", "long", "no"):
|
||||
@@ -837,12 +877,14 @@ raise ValueError()
|
||||
assert x == py.builtin._totext("я", "utf-8")
|
||||
|
||||
def test_toterminal_long(self, importasmod):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def g(x):
|
||||
raise ValueError(x)
|
||||
def f():
|
||||
g(3)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.f)
|
||||
excinfo.traceback = excinfo.traceback.filter()
|
||||
repr = excinfo.getrepr()
|
||||
@@ -867,14 +909,16 @@ raise ValueError()
|
||||
assert tw.lines[12] == ":3: ValueError"
|
||||
|
||||
def test_toterminal_long_missing_source(self, importasmod, tmpdir):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def g(x):
|
||||
raise ValueError(x)
|
||||
def f():
|
||||
g(3)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.f)
|
||||
tmpdir.join('mod.py').remove()
|
||||
tmpdir.join("mod.py").remove()
|
||||
excinfo.traceback = excinfo.traceback.filter()
|
||||
repr = excinfo.getrepr()
|
||||
tw = TWMock()
|
||||
@@ -896,14 +940,16 @@ raise ValueError()
|
||||
assert tw.lines[10] == ":3: ValueError"
|
||||
|
||||
def test_toterminal_long_incomplete_source(self, importasmod, tmpdir):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def g(x):
|
||||
raise ValueError(x)
|
||||
def f():
|
||||
g(3)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.f)
|
||||
tmpdir.join('mod.py').write('asdf')
|
||||
tmpdir.join("mod.py").write("asdf")
|
||||
excinfo.traceback = excinfo.traceback.filter()
|
||||
repr = excinfo.getrepr()
|
||||
tw = TWMock()
|
||||
@@ -925,10 +971,12 @@ raise ValueError()
|
||||
assert tw.lines[10] == ":3: ValueError"
|
||||
|
||||
def test_toterminal_long_filenames(self, importasmod):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def f():
|
||||
raise ValueError()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.f)
|
||||
tw = TWMock()
|
||||
path = py.path.local(mod.__file__)
|
||||
@@ -951,20 +999,30 @@ raise ValueError()
|
||||
finally:
|
||||
old.chdir()
|
||||
|
||||
@pytest.mark.parametrize('reproptions', [
|
||||
{'style': style, 'showlocals': showlocals,
|
||||
'funcargs': funcargs, 'tbfilter': tbfilter
|
||||
} for style in ("long", "short", "no")
|
||||
for showlocals in (True, False)
|
||||
for tbfilter in (True, False)
|
||||
for funcargs in (True, False)])
|
||||
@pytest.mark.parametrize(
|
||||
"reproptions",
|
||||
[
|
||||
{
|
||||
"style": style,
|
||||
"showlocals": showlocals,
|
||||
"funcargs": funcargs,
|
||||
"tbfilter": tbfilter,
|
||||
}
|
||||
for style in ("long", "short", "no")
|
||||
for showlocals in (True, False)
|
||||
for tbfilter in (True, False)
|
||||
for funcargs in (True, False)
|
||||
],
|
||||
)
|
||||
def test_format_excinfo(self, importasmod, reproptions):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def g(x):
|
||||
raise ValueError(x)
|
||||
def f():
|
||||
g(3)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.f)
|
||||
tw = py.io.TerminalWriter(stringio=True)
|
||||
repr = excinfo.getrepr(**reproptions)
|
||||
@@ -972,7 +1030,8 @@ raise ValueError()
|
||||
assert tw.stringio.getvalue()
|
||||
|
||||
def test_traceback_repr_style(self, importasmod):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def f():
|
||||
g()
|
||||
def g():
|
||||
@@ -981,7 +1040,8 @@ raise ValueError()
|
||||
i()
|
||||
def i():
|
||||
raise ValueError()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.f)
|
||||
excinfo.traceback = excinfo.traceback.filter()
|
||||
excinfo.traceback[1].set_repr_style("short")
|
||||
@@ -1017,7 +1077,8 @@ raise ValueError()
|
||||
|
||||
@pytest.mark.skipif("sys.version_info[0] < 3")
|
||||
def test_exc_chain_repr(self, importasmod):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
class Err(Exception):
|
||||
pass
|
||||
def f():
|
||||
@@ -1032,7 +1093,8 @@ raise ValueError()
|
||||
|
||||
def h():
|
||||
raise AttributeError()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(AttributeError, mod.f)
|
||||
r = excinfo.getrepr(style="long")
|
||||
tw = TWMock()
|
||||
@@ -1045,8 +1107,8 @@ raise ValueError()
|
||||
assert tw.lines[3] == "> g()"
|
||||
assert tw.lines[4] == ""
|
||||
line = tw.get_write_msg(5)
|
||||
assert line.endswith('mod.py')
|
||||
assert tw.lines[6] == ':6: '
|
||||
assert line.endswith("mod.py")
|
||||
assert tw.lines[6] == ":6: "
|
||||
assert tw.lines[7] == ("_ ", None)
|
||||
assert tw.lines[8] == ""
|
||||
assert tw.lines[9] == " def g():"
|
||||
@@ -1054,10 +1116,13 @@ raise ValueError()
|
||||
assert tw.lines[11] == "E ValueError"
|
||||
assert tw.lines[12] == ""
|
||||
line = tw.get_write_msg(13)
|
||||
assert line.endswith('mod.py')
|
||||
assert tw.lines[14] == ':12: ValueError'
|
||||
assert line.endswith("mod.py")
|
||||
assert tw.lines[14] == ":12: ValueError"
|
||||
assert tw.lines[15] == ""
|
||||
assert tw.lines[16] == "The above exception was the direct cause of the following exception:"
|
||||
assert (
|
||||
tw.lines[16]
|
||||
== "The above exception was the direct cause of the following exception:"
|
||||
)
|
||||
assert tw.lines[17] == ""
|
||||
assert tw.lines[18] == " def f():"
|
||||
assert tw.lines[19] == " try:"
|
||||
@@ -1067,10 +1132,13 @@ raise ValueError()
|
||||
assert tw.lines[23] == "E test_exc_chain_repr0.mod.Err"
|
||||
assert tw.lines[24] == ""
|
||||
line = tw.get_write_msg(25)
|
||||
assert line.endswith('mod.py')
|
||||
assert line.endswith("mod.py")
|
||||
assert tw.lines[26] == ":8: Err"
|
||||
assert tw.lines[27] == ""
|
||||
assert tw.lines[28] == "During handling of the above exception, another exception occurred:"
|
||||
assert (
|
||||
tw.lines[28]
|
||||
== "During handling of the above exception, another exception occurred:"
|
||||
)
|
||||
assert tw.lines[29] == ""
|
||||
assert tw.lines[30] == " def f():"
|
||||
assert tw.lines[31] == " try:"
|
||||
@@ -1081,21 +1149,22 @@ raise ValueError()
|
||||
assert tw.lines[36] == "> h()"
|
||||
assert tw.lines[37] == ""
|
||||
line = tw.get_write_msg(38)
|
||||
assert line.endswith('mod.py')
|
||||
assert line.endswith("mod.py")
|
||||
assert tw.lines[39] == ":10: "
|
||||
assert tw.lines[40] == ('_ ', None)
|
||||
assert tw.lines[40] == ("_ ", None)
|
||||
assert tw.lines[41] == ""
|
||||
assert tw.lines[42] == " def h():"
|
||||
assert tw.lines[43] == "> raise AttributeError()"
|
||||
assert tw.lines[44] == "E AttributeError"
|
||||
assert tw.lines[45] == ""
|
||||
line = tw.get_write_msg(46)
|
||||
assert line.endswith('mod.py')
|
||||
assert line.endswith("mod.py")
|
||||
assert tw.lines[47] == ":15: AttributeError"
|
||||
|
||||
@pytest.mark.skipif("sys.version_info[0] < 3")
|
||||
def test_exc_repr_with_raise_from_none_chain_suppression(self, importasmod):
|
||||
mod = importasmod("""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def f():
|
||||
try:
|
||||
g()
|
||||
@@ -1103,7 +1172,8 @@ raise ValueError()
|
||||
raise AttributeError() from None
|
||||
def g():
|
||||
raise ValueError()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(AttributeError, mod.f)
|
||||
r = excinfo.getrepr(style="long")
|
||||
tw = TWMock()
|
||||
@@ -1119,15 +1189,24 @@ raise ValueError()
|
||||
assert tw.lines[6] == "E AttributeError"
|
||||
assert tw.lines[7] == ""
|
||||
line = tw.get_write_msg(8)
|
||||
assert line.endswith('mod.py')
|
||||
assert line.endswith("mod.py")
|
||||
assert tw.lines[9] == ":6: AttributeError"
|
||||
assert len(tw.lines) == 10
|
||||
|
||||
@pytest.mark.skipif("sys.version_info[0] < 3")
|
||||
@pytest.mark.parametrize('reason, description', [
|
||||
('cause', 'The above exception was the direct cause of the following exception:'),
|
||||
('context', 'During handling of the above exception, another exception occurred:'),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"reason, description",
|
||||
[
|
||||
(
|
||||
"cause",
|
||||
"The above exception was the direct cause of the following exception:",
|
||||
),
|
||||
(
|
||||
"context",
|
||||
"During handling of the above exception, another exception occurred:",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_exc_chain_repr_without_traceback(self, importasmod, reason, description):
|
||||
"""
|
||||
Handle representation of exception chains where one of the exceptions doesn't have a
|
||||
@@ -1135,8 +1214,10 @@ raise ValueError()
|
||||
module (#1984).
|
||||
"""
|
||||
from _pytest.pytester import LineMatcher
|
||||
exc_handling_code = ' from e' if reason == 'cause' else ''
|
||||
mod = importasmod("""
|
||||
|
||||
exc_handling_code = " from e" if reason == "cause" else ""
|
||||
mod = importasmod(
|
||||
"""
|
||||
def f():
|
||||
try:
|
||||
g()
|
||||
@@ -1144,13 +1225,16 @@ raise ValueError()
|
||||
raise RuntimeError('runtime problem'){exc_handling_code}
|
||||
def g():
|
||||
raise ValueError('invalid value')
|
||||
""".format(exc_handling_code=exc_handling_code))
|
||||
""".format(
|
||||
exc_handling_code=exc_handling_code
|
||||
)
|
||||
)
|
||||
|
||||
with pytest.raises(RuntimeError) as excinfo:
|
||||
mod.f()
|
||||
|
||||
# emulate the issue described in #1984
|
||||
attr = '__%s__' % reason
|
||||
attr = "__%s__" % reason
|
||||
getattr(excinfo.value, attr).__traceback__ = None
|
||||
|
||||
r = excinfo.getrepr()
|
||||
@@ -1159,19 +1243,21 @@ raise ValueError()
|
||||
r.toterminal(tw)
|
||||
|
||||
matcher = LineMatcher(tw.stringio.getvalue().splitlines())
|
||||
matcher.fnmatch_lines([
|
||||
"ValueError: invalid value",
|
||||
description,
|
||||
"* except Exception as e:",
|
||||
"> * raise RuntimeError('runtime problem')" + exc_handling_code,
|
||||
"E *RuntimeError: runtime problem",
|
||||
])
|
||||
matcher.fnmatch_lines(
|
||||
[
|
||||
"ValueError: invalid value",
|
||||
description,
|
||||
"* except Exception as e:",
|
||||
"> * raise RuntimeError('runtime problem')" + exc_handling_code,
|
||||
"E *RuntimeError: runtime problem",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("style", ["short", "long"])
|
||||
@pytest.mark.parametrize("encoding", [None, "utf8", "utf16"])
|
||||
def test_repr_traceback_with_unicode(style, encoding):
|
||||
msg = u'☹'
|
||||
msg = u"☹"
|
||||
if encoding is not None:
|
||||
msg = msg.encode(encoding)
|
||||
try:
|
||||
@@ -1184,28 +1270,32 @@ def test_repr_traceback_with_unicode(style, encoding):
|
||||
|
||||
|
||||
def test_cwd_deleted(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test(tmpdir):
|
||||
tmpdir.chdir()
|
||||
tmpdir.remove()
|
||||
assert False
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(['* 1 failed in *'])
|
||||
assert 'INTERNALERROR' not in result.stdout.str() + result.stderr.str()
|
||||
result.stdout.fnmatch_lines(["* 1 failed in *"])
|
||||
assert "INTERNALERROR" not in result.stdout.str() + result.stderr.str()
|
||||
|
||||
|
||||
def test_exception_repr_extraction_error_on_recursion():
|
||||
"""
|
||||
Ensure we can properly detect a recursion error even
|
||||
if some locals raise error on comparision (#2459).
|
||||
if some locals raise error on comparison (#2459).
|
||||
"""
|
||||
class numpy_like(object):
|
||||
|
||||
class numpy_like(object):
|
||||
def __eq__(self, other):
|
||||
if type(other) is numpy_like:
|
||||
raise ValueError('The truth value of an array '
|
||||
'with more than one element is ambiguous.')
|
||||
raise ValueError(
|
||||
"The truth value of an array "
|
||||
"with more than one element is ambiguous."
|
||||
)
|
||||
|
||||
def a(x):
|
||||
return b(numpy_like())
|
||||
@@ -1218,14 +1308,17 @@ def test_exception_repr_extraction_error_on_recursion():
|
||||
except: # noqa
|
||||
from _pytest._code.code import ExceptionInfo
|
||||
from _pytest.pytester import LineMatcher
|
||||
|
||||
exc_info = ExceptionInfo()
|
||||
|
||||
matcher = LineMatcher(str(exc_info.getrepr()).splitlines())
|
||||
matcher.fnmatch_lines([
|
||||
'!!! Recursion error detected, but an error occurred locating the origin of recursion.',
|
||||
'*The following exception happened*',
|
||||
'*ValueError: The truth value of an array*',
|
||||
])
|
||||
matcher.fnmatch_lines(
|
||||
[
|
||||
"!!! Recursion error detected, but an error occurred locating the origin of recursion.",
|
||||
"*The following exception happened*",
|
||||
"*ValueError: The truth value of an array*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_no_recursion_index_on_recursion_error():
|
||||
@@ -1234,14 +1327,16 @@ def test_no_recursion_index_on_recursion_error():
|
||||
during a recursion error (#2486).
|
||||
"""
|
||||
try:
|
||||
|
||||
class RecursionDepthError(object):
|
||||
def __getattr__(self, attr):
|
||||
return getattr(self, '_' + attr)
|
||||
return getattr(self, "_" + attr)
|
||||
|
||||
RecursionDepthError().trigger
|
||||
except: # noqa
|
||||
from _pytest._code.code import ExceptionInfo
|
||||
|
||||
exc_info = ExceptionInfo()
|
||||
assert 'maximum recursion' in str(exc_info.getrepr())
|
||||
assert "maximum recursion" in str(exc_info.getrepr())
|
||||
else:
|
||||
assert 0
|
||||
|
||||
@@ -23,14 +23,20 @@ def test_source_str_function():
|
||||
x = Source(" 3")
|
||||
assert str(x) == "3"
|
||||
|
||||
x = Source("""
|
||||
x = Source(
|
||||
"""
|
||||
3
|
||||
""", rstrip=False)
|
||||
""",
|
||||
rstrip=False,
|
||||
)
|
||||
assert str(x) == "\n3\n "
|
||||
|
||||
x = Source("""
|
||||
x = Source(
|
||||
"""
|
||||
3
|
||||
""", rstrip=True)
|
||||
""",
|
||||
rstrip=True,
|
||||
)
|
||||
assert str(x) == "\n3"
|
||||
|
||||
|
||||
@@ -41,70 +47,78 @@ def test_unicode():
|
||||
return
|
||||
x = Source(unicode("4"))
|
||||
assert str(x) == "4"
|
||||
co = _pytest._code.compile(unicode('u"\xc3\xa5"', 'utf8'), mode='eval')
|
||||
co = _pytest._code.compile(unicode('u"\xc3\xa5"', "utf8"), mode="eval")
|
||||
val = eval(co)
|
||||
assert isinstance(val, unicode)
|
||||
|
||||
|
||||
def test_source_from_function():
|
||||
source = _pytest._code.Source(test_source_str_function)
|
||||
assert str(source).startswith('def test_source_str_function():')
|
||||
assert str(source).startswith("def test_source_str_function():")
|
||||
|
||||
|
||||
def test_source_from_method():
|
||||
class TestClass(object):
|
||||
def test_method(self):
|
||||
pass
|
||||
|
||||
source = _pytest._code.Source(TestClass().test_method)
|
||||
assert source.lines == ["def test_method(self):",
|
||||
" pass"]
|
||||
assert source.lines == ["def test_method(self):", " pass"]
|
||||
|
||||
|
||||
def test_source_from_lines():
|
||||
lines = ["a \n", "b\n", "c"]
|
||||
source = _pytest._code.Source(lines)
|
||||
assert source.lines == ['a ', 'b', 'c']
|
||||
assert source.lines == ["a ", "b", "c"]
|
||||
|
||||
|
||||
def test_source_from_inner_function():
|
||||
def f():
|
||||
pass
|
||||
|
||||
source = _pytest._code.Source(f, deindent=False)
|
||||
assert str(source).startswith(' def f():')
|
||||
assert str(source).startswith(" def f():")
|
||||
source = _pytest._code.Source(f)
|
||||
assert str(source).startswith('def f():')
|
||||
assert str(source).startswith("def f():")
|
||||
|
||||
|
||||
def test_source_putaround_simple():
|
||||
source = Source("raise ValueError")
|
||||
source = source.putaround(
|
||||
"try:", """\
|
||||
"try:",
|
||||
"""\
|
||||
except ValueError:
|
||||
x = 42
|
||||
else:
|
||||
x = 23""")
|
||||
assert str(source) == """\
|
||||
x = 23""",
|
||||
)
|
||||
assert (
|
||||
str(source)
|
||||
== """\
|
||||
try:
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
x = 42
|
||||
else:
|
||||
x = 23"""
|
||||
)
|
||||
|
||||
|
||||
def test_source_putaround():
|
||||
source = Source()
|
||||
source = source.putaround("""
|
||||
source = source.putaround(
|
||||
"""
|
||||
if 1:
|
||||
x=1
|
||||
""")
|
||||
"""
|
||||
)
|
||||
assert str(source).strip() == "if 1:\n x=1"
|
||||
|
||||
|
||||
def test_source_strips():
|
||||
source = Source("")
|
||||
assert source == Source()
|
||||
assert str(source) == ''
|
||||
assert str(source) == ""
|
||||
assert source.strip() == source
|
||||
|
||||
|
||||
@@ -116,10 +130,10 @@ def test_source_strip_multiline():
|
||||
|
||||
|
||||
def test_syntaxerror_rerepresentation():
|
||||
ex = pytest.raises(SyntaxError, _pytest._code.compile, 'xyz xyz')
|
||||
ex = pytest.raises(SyntaxError, _pytest._code.compile, "xyz xyz")
|
||||
assert ex.value.lineno == 1
|
||||
assert ex.value.offset in (4, 7) # XXX pypy/jython versus cpython?
|
||||
assert ex.value.text.strip(), 'x x'
|
||||
assert ex.value.text.strip(), "x x"
|
||||
|
||||
|
||||
def test_isparseable():
|
||||
@@ -132,12 +146,14 @@ def test_isparseable():
|
||||
|
||||
|
||||
class TestAccesses(object):
|
||||
source = Source("""\
|
||||
source = Source(
|
||||
"""\
|
||||
def f(x):
|
||||
pass
|
||||
def g(x):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
def test_getrange(self):
|
||||
x = self.source[0:2]
|
||||
@@ -158,18 +174,20 @@ class TestAccesses(object):
|
||||
|
||||
|
||||
class TestSourceParsingAndCompiling(object):
|
||||
source = Source("""\
|
||||
source = Source(
|
||||
"""\
|
||||
def f(x):
|
||||
assert (x ==
|
||||
3 +
|
||||
4)
|
||||
""").strip()
|
||||
"""
|
||||
).strip()
|
||||
|
||||
def test_compile(self):
|
||||
co = _pytest._code.compile("x=3")
|
||||
d = {}
|
||||
exec(co, d)
|
||||
assert d['x'] == 3
|
||||
assert d["x"] == 3
|
||||
|
||||
def test_compile_and_getsource_simple(self):
|
||||
co = _pytest._code.compile("x=3")
|
||||
@@ -180,18 +198,23 @@ class TestSourceParsingAndCompiling(object):
|
||||
def test_compile_and_getsource_through_same_function(self):
|
||||
def gensource(source):
|
||||
return _pytest._code.compile(source)
|
||||
co1 = gensource("""
|
||||
|
||||
co1 = gensource(
|
||||
"""
|
||||
def f():
|
||||
raise KeyError()
|
||||
""")
|
||||
co2 = gensource("""
|
||||
"""
|
||||
)
|
||||
co2 = gensource(
|
||||
"""
|
||||
def f():
|
||||
raise ValueError()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
source1 = inspect.getsource(co1)
|
||||
assert 'KeyError' in source1
|
||||
assert "KeyError" in source1
|
||||
source2 = inspect.getsource(co2)
|
||||
assert 'ValueError' in source2
|
||||
assert "ValueError" in source2
|
||||
|
||||
def test_getstatement(self):
|
||||
# print str(self.source)
|
||||
@@ -199,13 +222,15 @@ class TestSourceParsingAndCompiling(object):
|
||||
for i in range(1, 4):
|
||||
# print "trying start in line %r" % self.source[i]
|
||||
s = self.source.getstatement(i)
|
||||
#x = s.deindent()
|
||||
# x = s.deindent()
|
||||
assert str(s) == ass
|
||||
|
||||
def test_getstatementrange_triple_quoted(self):
|
||||
# print str(self.source)
|
||||
source = Source("""hello('''
|
||||
''')""")
|
||||
source = Source(
|
||||
"""hello('''
|
||||
''')"""
|
||||
)
|
||||
s = source.getstatement(0)
|
||||
assert s == str(source)
|
||||
s = source.getstatement(1)
|
||||
@@ -213,7 +238,8 @@ class TestSourceParsingAndCompiling(object):
|
||||
|
||||
@astonly
|
||||
def test_getstatementrange_within_constructs(self):
|
||||
source = Source("""\
|
||||
source = Source(
|
||||
"""\
|
||||
try:
|
||||
try:
|
||||
raise ValueError
|
||||
@@ -221,7 +247,8 @@ class TestSourceParsingAndCompiling(object):
|
||||
pass
|
||||
finally:
|
||||
42
|
||||
""")
|
||||
"""
|
||||
)
|
||||
assert len(source) == 7
|
||||
# check all lineno's that could occur in a traceback
|
||||
# assert source.getstatementrange(0) == (0, 7)
|
||||
@@ -233,19 +260,22 @@ class TestSourceParsingAndCompiling(object):
|
||||
assert source.getstatementrange(6) == (6, 7)
|
||||
|
||||
def test_getstatementrange_bug(self):
|
||||
source = Source("""\
|
||||
source = Source(
|
||||
"""\
|
||||
try:
|
||||
x = (
|
||||
y +
|
||||
z)
|
||||
except:
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
assert len(source) == 6
|
||||
assert source.getstatementrange(2) == (1, 4)
|
||||
|
||||
def test_getstatementrange_bug2(self):
|
||||
source = Source("""\
|
||||
source = Source(
|
||||
"""\
|
||||
assert (
|
||||
33
|
||||
==
|
||||
@@ -255,19 +285,22 @@ class TestSourceParsingAndCompiling(object):
|
||||
),
|
||||
]
|
||||
)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
assert len(source) == 9
|
||||
assert source.getstatementrange(5) == (0, 9)
|
||||
|
||||
def test_getstatementrange_ast_issue58(self):
|
||||
source = Source("""\
|
||||
source = Source(
|
||||
"""\
|
||||
|
||||
def test_some():
|
||||
for a in [a for a in
|
||||
CAUSE_ERROR]: pass
|
||||
|
||||
x = 3
|
||||
""")
|
||||
"""
|
||||
)
|
||||
assert getstatement(2, source).lines == source.lines[2:3]
|
||||
assert getstatement(3, source).lines == source.lines[3:4]
|
||||
|
||||
@@ -282,6 +315,7 @@ class TestSourceParsingAndCompiling(object):
|
||||
|
||||
def test_compile_to_ast(self):
|
||||
import ast
|
||||
|
||||
source = Source("x = 4")
|
||||
mod = source.compile(flag=ast.PyCF_ONLY_AST)
|
||||
assert isinstance(mod, ast.Module)
|
||||
@@ -295,9 +329,9 @@ class TestSourceParsingAndCompiling(object):
|
||||
frame = excinfo.traceback[-1].frame
|
||||
stmt = frame.code.fullsource.getstatement(frame.lineno)
|
||||
# print "block", str(block)
|
||||
assert str(stmt).strip().startswith('assert')
|
||||
assert str(stmt).strip().startswith("assert")
|
||||
|
||||
@pytest.mark.parametrize('name', ['', None, 'my'])
|
||||
@pytest.mark.parametrize("name", ["", None, "my"])
|
||||
def test_compilefuncs_and_path_sanity(self, name):
|
||||
def check(comp, name):
|
||||
co = comp(self.source, name)
|
||||
@@ -316,7 +350,7 @@ class TestSourceParsingAndCompiling(object):
|
||||
check(comp, name)
|
||||
|
||||
def test_offsetless_synerr(self):
|
||||
pytest.raises(SyntaxError, _pytest._code.compile, "lambda a,a: 0", mode='eval')
|
||||
pytest.raises(SyntaxError, _pytest._code.compile, "lambda a,a: 0", mode="eval")
|
||||
|
||||
|
||||
def test_getstartingblock_singleline():
|
||||
@@ -325,24 +359,29 @@ def test_getstartingblock_singleline():
|
||||
frame = sys._getframe(1)
|
||||
self.source = _pytest._code.Frame(frame).statement
|
||||
|
||||
x = A('x', 'y')
|
||||
x = A("x", "y")
|
||||
|
||||
values = [i for i in x.source.lines if i.strip()]
|
||||
assert len(values) == 1
|
||||
|
||||
|
||||
def test_getline_finally():
|
||||
def c(): pass
|
||||
excinfo = pytest.raises(TypeError, """
|
||||
def c():
|
||||
pass
|
||||
|
||||
excinfo = pytest.raises(
|
||||
TypeError,
|
||||
"""
|
||||
teardown = None
|
||||
try:
|
||||
c(1)
|
||||
finally:
|
||||
if teardown:
|
||||
teardown()
|
||||
""")
|
||||
""",
|
||||
)
|
||||
source = excinfo.traceback[-1].statement
|
||||
assert str(source).strip() == 'c(1)'
|
||||
assert str(source).strip() == "c(1)"
|
||||
|
||||
|
||||
def test_getfuncsource_dynamic():
|
||||
@@ -354,28 +393,34 @@ def test_getfuncsource_dynamic():
|
||||
"""
|
||||
co = _pytest._code.compile(source)
|
||||
py.builtin.exec_(co, globals())
|
||||
assert str(_pytest._code.Source(f)).strip() == 'def f():\n raise ValueError'
|
||||
assert str(_pytest._code.Source(g)).strip() == 'def g(): pass'
|
||||
assert str(_pytest._code.Source(f)).strip() == "def f():\n raise ValueError"
|
||||
assert str(_pytest._code.Source(g)).strip() == "def g(): pass"
|
||||
|
||||
|
||||
def test_getfuncsource_with_multine_string():
|
||||
def f():
|
||||
c = '''while True:
|
||||
c = """while True:
|
||||
pass
|
||||
'''
|
||||
assert str(_pytest._code.Source(f)).strip() == "def f():\n c = '''while True:\n pass\n'''"
|
||||
"""
|
||||
|
||||
assert (
|
||||
str(_pytest._code.Source(f)).strip()
|
||||
== 'def f():\n c = """while True:\n pass\n"""'
|
||||
)
|
||||
|
||||
|
||||
def test_deindent():
|
||||
from _pytest._code.source import deindent as deindent
|
||||
assert deindent(['\tfoo', '\tbar', ]) == ['foo', 'bar']
|
||||
|
||||
assert deindent(["\tfoo", "\tbar"]) == ["foo", "bar"]
|
||||
|
||||
def f():
|
||||
c = '''while True:
|
||||
c = """while True:
|
||||
pass
|
||||
'''
|
||||
"""
|
||||
|
||||
lines = deindent(inspect.getsource(f).splitlines())
|
||||
assert lines == ["def f():", " c = '''while True:", " pass", "'''"]
|
||||
assert lines == ["def f():", ' c = """while True:', " pass", '"""']
|
||||
|
||||
source = """
|
||||
def f():
|
||||
@@ -383,17 +428,19 @@ def test_deindent():
|
||||
pass
|
||||
"""
|
||||
lines = deindent(source.splitlines())
|
||||
assert lines == ['', 'def f():', ' def g():', ' pass', ' ']
|
||||
assert lines == ["", "def f():", " def g():", " pass", " "]
|
||||
|
||||
|
||||
def test_source_of_class_at_eof_without_newline(tmpdir):
|
||||
# this test fails because the implicit inspect.getsource(A) below
|
||||
# does not return the "x = 1" last line.
|
||||
source = _pytest._code.Source('''
|
||||
source = _pytest._code.Source(
|
||||
"""
|
||||
class A(object):
|
||||
def method(self):
|
||||
x = 1
|
||||
''')
|
||||
"""
|
||||
)
|
||||
path = tmpdir.join("a.py")
|
||||
path.write(source)
|
||||
s2 = _pytest._code.Source(tmpdir.join("a.py").pyimport().A)
|
||||
@@ -401,12 +448,14 @@ def test_source_of_class_at_eof_without_newline(tmpdir):
|
||||
|
||||
|
||||
if True:
|
||||
|
||||
def x():
|
||||
pass
|
||||
|
||||
|
||||
def test_getsource_fallback():
|
||||
from _pytest._code.source import getsource
|
||||
|
||||
expected = """def x():
|
||||
pass"""
|
||||
src = getsource(x)
|
||||
@@ -415,6 +464,7 @@ def test_getsource_fallback():
|
||||
|
||||
def test_idem_compile_and_getsource():
|
||||
from _pytest._code.source import getsource
|
||||
|
||||
expected = "def x(): pass"
|
||||
co = _pytest._code.compile(expected)
|
||||
src = getsource(co)
|
||||
@@ -423,25 +473,29 @@ def test_idem_compile_and_getsource():
|
||||
|
||||
def test_findsource_fallback():
|
||||
from _pytest._code.source import findsource
|
||||
|
||||
src, lineno = findsource(x)
|
||||
assert 'test_findsource_simple' in str(src)
|
||||
assert src[lineno] == ' def x():'
|
||||
assert "test_findsource_simple" in str(src)
|
||||
assert src[lineno] == " def x():"
|
||||
|
||||
|
||||
def test_findsource():
|
||||
from _pytest._code.source import findsource
|
||||
co = _pytest._code.compile("""if 1:
|
||||
|
||||
co = _pytest._code.compile(
|
||||
"""if 1:
|
||||
def x():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
src, lineno = findsource(co)
|
||||
assert 'if 1:' in str(src)
|
||||
assert "if 1:" in str(src)
|
||||
|
||||
d = {}
|
||||
eval(co, d)
|
||||
src, lineno = findsource(d['x'])
|
||||
assert 'if 1:' in str(src)
|
||||
src, lineno = findsource(d["x"])
|
||||
assert "if 1:" in str(src)
|
||||
assert src[lineno] == " def x():"
|
||||
|
||||
|
||||
@@ -469,6 +523,7 @@ def test_getfslineno():
|
||||
|
||||
class B(object):
|
||||
pass
|
||||
|
||||
B.__name__ = "B2"
|
||||
assert getfslineno(B)[1] == -1
|
||||
|
||||
@@ -476,6 +531,7 @@ def test_getfslineno():
|
||||
def test_code_of_object_instance_with_call():
|
||||
class A(object):
|
||||
pass
|
||||
|
||||
pytest.raises(TypeError, lambda: _pytest._code.Source(A()))
|
||||
|
||||
class WithCall(object):
|
||||
@@ -483,16 +539,18 @@ def test_code_of_object_instance_with_call():
|
||||
pass
|
||||
|
||||
code = _pytest._code.Code(WithCall())
|
||||
assert 'pass' in str(code.source())
|
||||
assert "pass" in str(code.source())
|
||||
|
||||
class Hello(object):
|
||||
def __call__(self):
|
||||
pass
|
||||
|
||||
pytest.raises(TypeError, lambda: _pytest._code.Code(Hello))
|
||||
|
||||
|
||||
def getstatement(lineno, source):
|
||||
from _pytest._code.source import getstatementrange_ast
|
||||
|
||||
source = _pytest._code.Source(source, deindent=False)
|
||||
ast, start, end = getstatementrange_ast(lineno, source)
|
||||
return source[start:end]
|
||||
@@ -505,9 +563,14 @@ def test_oneline():
|
||||
|
||||
def test_comment_and_no_newline_at_end():
|
||||
from _pytest._code.source import getstatementrange_ast
|
||||
source = Source(['def test_basic_complex():',
|
||||
' assert 1 == 2',
|
||||
'# vim: filetype=pyopencl:fdm=marker'])
|
||||
|
||||
source = Source(
|
||||
[
|
||||
"def test_basic_complex():",
|
||||
" assert 1 == 2",
|
||||
"# vim: filetype=pyopencl:fdm=marker",
|
||||
]
|
||||
)
|
||||
ast, start, end = getstatementrange_ast(1, source)
|
||||
assert end == 2
|
||||
|
||||
@@ -517,8 +580,7 @@ def test_oneline_and_comment():
|
||||
assert str(source) == "raise ValueError"
|
||||
|
||||
|
||||
@pytest.mark.xfail(hasattr(sys, "pypy_version_info"),
|
||||
reason='does not work on pypy')
|
||||
@pytest.mark.xfail(hasattr(sys, "pypy_version_info"), reason="does not work on pypy")
|
||||
def test_comments():
|
||||
source = '''def test():
|
||||
"comment 1"
|
||||
@@ -533,20 +595,22 @@ comment 4
|
||||
"""
|
||||
'''
|
||||
for line in range(2, 6):
|
||||
assert str(getstatement(line, source)) == ' x = 1'
|
||||
assert str(getstatement(line, source)) == " x = 1"
|
||||
for line in range(6, 10):
|
||||
assert str(getstatement(line, source)) == ' assert False'
|
||||
assert str(getstatement(line, source)) == " assert False"
|
||||
assert str(getstatement(10, source)) == '"""'
|
||||
|
||||
|
||||
def test_comment_in_statement():
|
||||
source = '''test(foo=1,
|
||||
source = """test(foo=1,
|
||||
# comment 1
|
||||
bar=2)
|
||||
'''
|
||||
"""
|
||||
for line in range(1, 3):
|
||||
assert str(getstatement(line, source)) == \
|
||||
'test(foo=1,\n # comment 1\n bar=2)'
|
||||
assert (
|
||||
str(getstatement(line, source))
|
||||
== "test(foo=1,\n # comment 1\n bar=2)"
|
||||
)
|
||||
|
||||
|
||||
def test_single_line_else():
|
||||
@@ -560,19 +624,24 @@ def test_single_line_finally():
|
||||
|
||||
|
||||
def test_issue55():
|
||||
source = ('def round_trip(dinp):\n assert 1 == dinp\n'
|
||||
'def test_rt():\n round_trip("""\n""")\n')
|
||||
source = (
|
||||
"def round_trip(dinp):\n assert 1 == dinp\n"
|
||||
'def test_rt():\n round_trip("""\n""")\n'
|
||||
)
|
||||
s = getstatement(3, source)
|
||||
assert str(s) == ' round_trip("""\n""")'
|
||||
|
||||
|
||||
def XXXtest_multiline():
|
||||
source = getstatement(0, """\
|
||||
source = getstatement(
|
||||
0,
|
||||
"""\
|
||||
raise ValueError(
|
||||
23
|
||||
)
|
||||
x = 3
|
||||
""")
|
||||
""",
|
||||
)
|
||||
assert str(source) == "raise ValueError(\n 23\n)"
|
||||
|
||||
|
||||
|
||||
@@ -12,15 +12,17 @@ def test_getstartingblock_multiline():
|
||||
see hhatto/autopep8#307). It was considered better to just move this single test to its own
|
||||
file and exclude it from autopep8 than try to complicate things.
|
||||
"""
|
||||
|
||||
class A(object):
|
||||
def __init__(self, *args):
|
||||
frame = sys._getframe(1)
|
||||
self.source = _pytest._code.Frame(frame).statement
|
||||
|
||||
# fmt: off
|
||||
x = A('x',
|
||||
'y'
|
||||
,
|
||||
'z')
|
||||
|
||||
# fmt: on
|
||||
values = [i for i in x.source.lines if i.strip()]
|
||||
assert len(values) == 4
|
||||
|
||||
@@ -3,7 +3,8 @@ import pytest
|
||||
|
||||
|
||||
def test_yield_tests_deprecation(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def func1(arg, arg2):
|
||||
assert arg == arg2
|
||||
def test_gen():
|
||||
@@ -12,54 +13,74 @@ def test_yield_tests_deprecation(testdir):
|
||||
def test_gen2():
|
||||
for k in range(10):
|
||||
yield func1, 1, 1
|
||||
""")
|
||||
result = testdir.runpytest('-ra')
|
||||
result.stdout.fnmatch_lines([
|
||||
'*yield tests are deprecated, and scheduled to be removed in pytest 4.0*',
|
||||
'*2 passed*',
|
||||
])
|
||||
assert result.stdout.str().count('yield tests are deprecated') == 2
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("-ra")
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*yield tests are deprecated, and scheduled to be removed in pytest 4.0*",
|
||||
"*2 passed*",
|
||||
]
|
||||
)
|
||||
assert result.stdout.str().count("yield tests are deprecated") == 2
|
||||
|
||||
|
||||
def test_funcarg_prefix_deprecation(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def pytest_funcarg__value():
|
||||
return 10
|
||||
|
||||
def test_funcarg_prefix(value):
|
||||
assert value == 10
|
||||
""")
|
||||
result = testdir.runpytest('-ra')
|
||||
result.stdout.fnmatch_lines([
|
||||
('*pytest_funcarg__value: '
|
||||
'declaring fixtures using "pytest_funcarg__" prefix is deprecated '
|
||||
'and scheduled to be removed in pytest 4.0. '
|
||||
'Please remove the prefix and use the @pytest.fixture decorator instead.'),
|
||||
'*1 passed*',
|
||||
])
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("-ra")
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
(
|
||||
"*pytest_funcarg__value: "
|
||||
'declaring fixtures using "pytest_funcarg__" prefix is deprecated '
|
||||
"and scheduled to be removed in pytest 4.0. "
|
||||
"Please remove the prefix and use the @pytest.fixture decorator instead."
|
||||
),
|
||||
"*1 passed*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_pytest_setup_cfg_deprecated(testdir):
|
||||
testdir.makefile('.cfg', setup='''
|
||||
testdir.makefile(
|
||||
".cfg",
|
||||
setup="""
|
||||
[pytest]
|
||||
addopts = --verbose
|
||||
''')
|
||||
""",
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(['*pytest*section in setup.cfg files is deprecated*use*tool:pytest*instead*'])
|
||||
result.stdout.fnmatch_lines(
|
||||
["*pytest*section in setup.cfg files is deprecated*use*tool:pytest*instead*"]
|
||||
)
|
||||
|
||||
|
||||
def test_pytest_custom_cfg_deprecated(testdir):
|
||||
testdir.makefile('.cfg', custom='''
|
||||
testdir.makefile(
|
||||
".cfg",
|
||||
custom="""
|
||||
[pytest]
|
||||
addopts = --verbose
|
||||
''')
|
||||
""",
|
||||
)
|
||||
result = testdir.runpytest("-c", "custom.cfg")
|
||||
result.stdout.fnmatch_lines(['*pytest*section in custom.cfg files is deprecated*use*tool:pytest*instead*'])
|
||||
result.stdout.fnmatch_lines(
|
||||
["*pytest*section in custom.cfg files is deprecated*use*tool:pytest*instead*"]
|
||||
)
|
||||
|
||||
|
||||
def test_str_args_deprecated(tmpdir, testdir):
|
||||
"""Deprecate passing strings to pytest.main(). Scheduled for removal in pytest-4.0."""
|
||||
from _pytest.main import EXIT_NOTESTSCOLLECTED
|
||||
|
||||
warnings = []
|
||||
|
||||
class Collect(object):
|
||||
@@ -67,46 +88,53 @@ def test_str_args_deprecated(tmpdir, testdir):
|
||||
warnings.append(message)
|
||||
|
||||
ret = pytest.main("%s -x" % tmpdir, plugins=[Collect()])
|
||||
msg = ('passing a string to pytest.main() is deprecated, '
|
||||
'pass a list of arguments instead.')
|
||||
msg = (
|
||||
"passing a string to pytest.main() is deprecated, "
|
||||
"pass a list of arguments instead."
|
||||
)
|
||||
assert msg in warnings
|
||||
assert ret == EXIT_NOTESTSCOLLECTED
|
||||
|
||||
|
||||
def test_getfuncargvalue_is_deprecated(request):
|
||||
pytest.deprecated_call(request.getfuncargvalue, 'tmpdir')
|
||||
pytest.deprecated_call(request.getfuncargvalue, "tmpdir")
|
||||
|
||||
|
||||
def test_resultlog_is_deprecated(testdir):
|
||||
result = testdir.runpytest('--help')
|
||||
result.stdout.fnmatch_lines(['*DEPRECATED path for machine-readable result log*'])
|
||||
result = testdir.runpytest("--help")
|
||||
result.stdout.fnmatch_lines(["*DEPRECATED path for machine-readable result log*"])
|
||||
|
||||
testdir.makepyfile('''
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test():
|
||||
pass
|
||||
''')
|
||||
result = testdir.runpytest('--result-log=%s' % testdir.tmpdir.join('result.log'))
|
||||
result.stdout.fnmatch_lines([
|
||||
'*--result-log is deprecated and scheduled for removal in pytest 4.0*',
|
||||
'*See https://docs.pytest.org/*/usage.html#creating-resultlog-format-files for more information*',
|
||||
])
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("--result-log=%s" % testdir.tmpdir.join("result.log"))
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*--result-log is deprecated and scheduled for removal in pytest 4.0*",
|
||||
"*See https://docs.pytest.org/*/usage.html#creating-resultlog-format-files for more information*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.filterwarnings('always:Metafunc.addcall is deprecated')
|
||||
@pytest.mark.filterwarnings("always:Metafunc.addcall is deprecated")
|
||||
def test_metafunc_addcall_deprecated(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def pytest_generate_tests(metafunc):
|
||||
metafunc.addcall({'i': 1})
|
||||
metafunc.addcall({'i': 2})
|
||||
def test_func(i):
|
||||
pass
|
||||
""")
|
||||
res = testdir.runpytest('-s')
|
||||
"""
|
||||
)
|
||||
res = testdir.runpytest("-s")
|
||||
assert res.ret == 0
|
||||
res.stdout.fnmatch_lines([
|
||||
"*Metafunc.addcall is deprecated*",
|
||||
"*2 passed, 2 warnings*",
|
||||
])
|
||||
res.stdout.fnmatch_lines(
|
||||
["*Metafunc.addcall is deprecated*", "*2 passed, 2 warnings*"]
|
||||
)
|
||||
|
||||
|
||||
def test_terminal_reporter_writer_attr(pytestconfig):
|
||||
@@ -115,89 +143,123 @@ def test_terminal_reporter_writer_attr(pytestconfig):
|
||||
"""
|
||||
try:
|
||||
import xdist # noqa
|
||||
pytest.skip('xdist workers disable the terminal reporter plugin')
|
||||
|
||||
pytest.skip("xdist workers disable the terminal reporter plugin")
|
||||
except ImportError:
|
||||
pass
|
||||
terminal_reporter = pytestconfig.pluginmanager.get_plugin('terminalreporter')
|
||||
terminal_reporter = pytestconfig.pluginmanager.get_plugin("terminalreporter")
|
||||
assert terminal_reporter.writer is terminal_reporter._tw
|
||||
|
||||
|
||||
@pytest.mark.parametrize('plugin', ['catchlog', 'capturelog'])
|
||||
@pytest.mark.parametrize("plugin", ["catchlog", "capturelog"])
|
||||
def test_pytest_catchlog_deprecated(testdir, plugin):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_func(pytestconfig):
|
||||
pytestconfig.pluginmanager.register(None, 'pytest_{0}')
|
||||
""".format(plugin))
|
||||
pytestconfig.pluginmanager.register(None, 'pytest_{}')
|
||||
""".format(
|
||||
plugin
|
||||
)
|
||||
)
|
||||
res = testdir.runpytest()
|
||||
assert res.ret == 0
|
||||
res.stdout.fnmatch_lines([
|
||||
"*pytest-*log plugin has been merged into the core*",
|
||||
"*1 passed, 1 warnings*",
|
||||
])
|
||||
res.stdout.fnmatch_lines(
|
||||
["*pytest-*log plugin has been merged into the core*", "*1 passed, 1 warnings*"]
|
||||
)
|
||||
|
||||
|
||||
def test_pytest_plugins_in_non_top_level_conftest_deprecated(testdir):
|
||||
from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
|
||||
|
||||
subdirectory = testdir.tmpdir.join("subdirectory")
|
||||
subdirectory.mkdir()
|
||||
# create the inner conftest with makeconftest and then move it to the subdirectory
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
pytest_plugins=['capture']
|
||||
""")
|
||||
"""
|
||||
)
|
||||
testdir.tmpdir.join("conftest.py").move(subdirectory.join("conftest.py"))
|
||||
# make the top level conftest
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import warnings
|
||||
warnings.filterwarnings('always', category=DeprecationWarning)
|
||||
""")
|
||||
testdir.makepyfile("""
|
||||
"""
|
||||
)
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_func():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
res = testdir.runpytest_subprocess()
|
||||
assert res.ret == 0
|
||||
res.stderr.fnmatch_lines('*' + str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0])
|
||||
res.stderr.fnmatch_lines(
|
||||
"*" + str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0]
|
||||
)
|
||||
|
||||
|
||||
def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_top_level_conftest(testdir):
|
||||
def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_top_level_conftest(
|
||||
testdir
|
||||
):
|
||||
from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
|
||||
subdirectory = testdir.tmpdir.join('subdirectory')
|
||||
|
||||
subdirectory = testdir.tmpdir.join("subdirectory")
|
||||
subdirectory.mkdir()
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import warnings
|
||||
warnings.filterwarnings('always', category=DeprecationWarning)
|
||||
pytest_plugins=['capture']
|
||||
""")
|
||||
"""
|
||||
)
|
||||
testdir.tmpdir.join("conftest.py").move(subdirectory.join("conftest.py"))
|
||||
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_func():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
res = testdir.runpytest_subprocess()
|
||||
assert res.ret == 0
|
||||
res.stderr.fnmatch_lines('*' + str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0])
|
||||
res.stderr.fnmatch_lines(
|
||||
"*" + str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0]
|
||||
)
|
||||
|
||||
|
||||
def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_false_positives(testdir):
|
||||
def test_pytest_plugins_in_non_top_level_conftest_deprecated_no_false_positives(
|
||||
testdir
|
||||
):
|
||||
from _pytest.deprecated import PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST
|
||||
subdirectory = testdir.tmpdir.join('subdirectory')
|
||||
|
||||
subdirectory = testdir.tmpdir.join("subdirectory")
|
||||
subdirectory.mkdir()
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
testdir.tmpdir.join("conftest.py").move(subdirectory.join("conftest.py"))
|
||||
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import warnings
|
||||
warnings.filterwarnings('always', category=DeprecationWarning)
|
||||
pytest_plugins=['capture']
|
||||
""")
|
||||
testdir.makepyfile("""
|
||||
"""
|
||||
)
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_func():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
res = testdir.runpytest_subprocess()
|
||||
assert res.ret == 0
|
||||
assert str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0] not in res.stderr.str()
|
||||
assert (
|
||||
str(PYTEST_PLUGINS_FROM_NON_TOP_LEVEL_CONFTEST).splitlines()[0]
|
||||
not in res.stderr.str()
|
||||
)
|
||||
|
||||
9
testing/example_scripts/README.rst
Normal file
9
testing/example_scripts/README.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
Example test scripts
|
||||
=====================
|
||||
|
||||
|
||||
The files in this folder are not direct tests, but rather example test suites that demonstrate certain issues/behaviours.
|
||||
|
||||
In the future we will move part of the content of the acceptance tests here in order to have directly testable code instead of writing out things and then running them in nested pytest sessions/subprocesses.
|
||||
|
||||
This will aid debugging and comprehension.
|
||||
4
testing/example_scripts/conftest_usageerror/conftest.py
Normal file
4
testing/example_scripts/conftest_usageerror/conftest.py
Normal file
@@ -0,0 +1,4 @@
|
||||
def pytest_configure(config):
|
||||
import pytest
|
||||
|
||||
raise pytest.UsageError("hello")
|
||||
@@ -0,0 +1,14 @@
|
||||
import pytest
|
||||
|
||||
|
||||
class MyFile(pytest.File):
|
||||
def collect(self):
|
||||
return [MyItem("hello", parent=self)]
|
||||
|
||||
|
||||
def pytest_collect_file(path, parent):
|
||||
return MyFile(path, parent)
|
||||
|
||||
|
||||
class MyItem(pytest.Item):
|
||||
pass
|
||||
@@ -0,0 +1,2 @@
|
||||
def test_hello():
|
||||
pass
|
||||
51
testing/example_scripts/issue_519.py
Normal file
51
testing/example_scripts/issue_519.py
Normal file
@@ -0,0 +1,51 @@
|
||||
|
||||
import pytest
|
||||
import pprint
|
||||
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
if "arg1" in metafunc.fixturenames:
|
||||
metafunc.parametrize("arg1", ["arg1v1", "arg1v2"], scope="module")
|
||||
|
||||
if "arg2" in metafunc.fixturenames:
|
||||
metafunc.parametrize("arg2", ["arg2v1", "arg2v2"], scope="function")
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def checked_order():
|
||||
order = []
|
||||
|
||||
yield order
|
||||
pprint.pprint(order)
|
||||
assert order == [
|
||||
("testing/example_scripts/issue_519.py", "fix1", "arg1v1"),
|
||||
("test_one[arg1v1-arg2v1]", "fix2", "arg2v1"),
|
||||
("test_two[arg1v1-arg2v1]", "fix2", "arg2v1"),
|
||||
("test_one[arg1v1-arg2v2]", "fix2", "arg2v2"),
|
||||
("test_two[arg1v1-arg2v2]", "fix2", "arg2v2"),
|
||||
("testing/example_scripts/issue_519.py", "fix1", "arg1v2"),
|
||||
("test_one[arg1v2-arg2v1]", "fix2", "arg2v1"),
|
||||
("test_two[arg1v2-arg2v1]", "fix2", "arg2v1"),
|
||||
("test_one[arg1v2-arg2v2]", "fix2", "arg2v2"),
|
||||
("test_two[arg1v2-arg2v2]", "fix2", "arg2v2"),
|
||||
]
|
||||
|
||||
|
||||
@pytest.yield_fixture(scope="module")
|
||||
def fix1(request, arg1, checked_order):
|
||||
checked_order.append((request.node.name, "fix1", arg1))
|
||||
yield "fix1-" + arg1
|
||||
|
||||
|
||||
@pytest.yield_fixture(scope="function")
|
||||
def fix2(request, fix1, arg2, checked_order):
|
||||
checked_order.append((request.node.name, "fix2", arg2))
|
||||
yield "fix2-" + arg2 + fix1
|
||||
|
||||
|
||||
def test_one(fix2):
|
||||
pass
|
||||
|
||||
|
||||
def test_two(fix2):
|
||||
pass
|
||||
3
testing/examples/test_issue519.py
Normal file
3
testing/examples/test_issue519.py
Normal file
@@ -0,0 +1,3 @@
|
||||
def test_510(testdir):
|
||||
testdir.copy_example("issue_519.py")
|
||||
testdir.runpytest("issue_519.py")
|
||||
2
testing/freeze/.gitignore
vendored
2
testing/freeze/.gitignore
vendored
@@ -1,3 +1,3 @@
|
||||
build/
|
||||
dist/
|
||||
*.spec
|
||||
*.spec
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
"""
|
||||
Generates an executable with pytest runner embedded using PyInstaller.
|
||||
"""
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
import pytest
|
||||
import subprocess
|
||||
|
||||
hidden = []
|
||||
for x in pytest.freeze_includes():
|
||||
hidden.extend(['--hidden-import', x])
|
||||
args = ['pyinstaller', '--noconfirm'] + hidden + ['runtests_script.py']
|
||||
subprocess.check_call(' '.join(args), shell=True)
|
||||
hidden.extend(["--hidden-import", x])
|
||||
args = ["pyinstaller", "--noconfirm"] + hidden + ["runtests_script.py"]
|
||||
subprocess.check_call(" ".join(args), shell=True)
|
||||
|
||||
@@ -3,7 +3,8 @@ This is the script that is actually frozen into an executable: simply executes
|
||||
py.test main().
|
||||
"""
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
import pytest
|
||||
|
||||
sys.exit(pytest.main())
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
|
||||
def test_upper():
|
||||
assert 'foo'.upper() == 'FOO'
|
||||
assert "foo".upper() == "FOO"
|
||||
|
||||
|
||||
def test_lower():
|
||||
assert 'FOO'.lower() == 'foo'
|
||||
assert "FOO".lower() == "foo"
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
Called by tox.ini: uses the generated executable to run the tests in ./tests/
|
||||
directory.
|
||||
"""
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
import os
|
||||
import sys
|
||||
|
||||
executable = os.path.join(os.getcwd(), 'dist', 'runtests_script', 'runtests_script')
|
||||
if sys.platform.startswith('win'):
|
||||
executable += '.exe'
|
||||
sys.exit(os.system('%s tests' % executable))
|
||||
executable = os.path.join(os.getcwd(), "dist", "runtests_script", "runtests_script")
|
||||
if sys.platform.startswith("win"):
|
||||
executable += ".exe"
|
||||
sys.exit(os.system("%s tests" % executable))
|
||||
|
||||
@@ -4,32 +4,33 @@ import logging
|
||||
import pytest
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
sublogger = logging.getLogger(__name__ + '.baz')
|
||||
sublogger = logging.getLogger(__name__ + ".baz")
|
||||
|
||||
|
||||
def test_fixture_help(testdir):
|
||||
result = testdir.runpytest('--fixtures')
|
||||
result.stdout.fnmatch_lines(['*caplog*'])
|
||||
result = testdir.runpytest("--fixtures")
|
||||
result.stdout.fnmatch_lines(["*caplog*"])
|
||||
|
||||
|
||||
def test_change_level(caplog):
|
||||
caplog.set_level(logging.INFO)
|
||||
logger.debug('handler DEBUG level')
|
||||
logger.info('handler INFO level')
|
||||
logger.debug("handler DEBUG level")
|
||||
logger.info("handler INFO level")
|
||||
|
||||
caplog.set_level(logging.CRITICAL, logger=sublogger.name)
|
||||
sublogger.warning('logger WARNING level')
|
||||
sublogger.critical('logger CRITICAL level')
|
||||
sublogger.warning("logger WARNING level")
|
||||
sublogger.critical("logger CRITICAL level")
|
||||
|
||||
assert 'DEBUG' not in caplog.text
|
||||
assert 'INFO' in caplog.text
|
||||
assert 'WARNING' not in caplog.text
|
||||
assert 'CRITICAL' in caplog.text
|
||||
assert "DEBUG" not in caplog.text
|
||||
assert "INFO" in caplog.text
|
||||
assert "WARNING" not in caplog.text
|
||||
assert "CRITICAL" in caplog.text
|
||||
|
||||
|
||||
def test_change_level_undo(testdir):
|
||||
"""Ensure that 'set_level' is undone after the end of the test"""
|
||||
testdir.makepyfile('''
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import logging
|
||||
|
||||
def test1(caplog):
|
||||
@@ -42,58 +43,75 @@ def test_change_level_undo(testdir):
|
||||
# using + operator here so fnmatch_lines doesn't match the code in the traceback
|
||||
logging.info('log from ' + 'test2')
|
||||
assert 0
|
||||
''')
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest_subprocess()
|
||||
result.stdout.fnmatch_lines([
|
||||
'*log from test1*',
|
||||
'*2 failed in *',
|
||||
])
|
||||
assert 'log from test2' not in result.stdout.str()
|
||||
result.stdout.fnmatch_lines(["*log from test1*", "*2 failed in *"])
|
||||
assert "log from test2" not in result.stdout.str()
|
||||
|
||||
|
||||
def test_with_statement(caplog):
|
||||
with caplog.at_level(logging.INFO):
|
||||
logger.debug('handler DEBUG level')
|
||||
logger.info('handler INFO level')
|
||||
logger.debug("handler DEBUG level")
|
||||
logger.info("handler INFO level")
|
||||
|
||||
with caplog.at_level(logging.CRITICAL, logger=sublogger.name):
|
||||
sublogger.warning('logger WARNING level')
|
||||
sublogger.critical('logger CRITICAL level')
|
||||
sublogger.warning("logger WARNING level")
|
||||
sublogger.critical("logger CRITICAL level")
|
||||
|
||||
assert 'DEBUG' not in caplog.text
|
||||
assert 'INFO' in caplog.text
|
||||
assert 'WARNING' not in caplog.text
|
||||
assert 'CRITICAL' in caplog.text
|
||||
assert "DEBUG" not in caplog.text
|
||||
assert "INFO" in caplog.text
|
||||
assert "WARNING" not in caplog.text
|
||||
assert "CRITICAL" in caplog.text
|
||||
|
||||
|
||||
def test_log_access(caplog):
|
||||
caplog.set_level(logging.INFO)
|
||||
logger.info('boo %s', 'arg')
|
||||
assert caplog.records[0].levelname == 'INFO'
|
||||
assert caplog.records[0].msg == 'boo %s'
|
||||
assert 'boo arg' in caplog.text
|
||||
logger.info("boo %s", "arg")
|
||||
assert caplog.records[0].levelname == "INFO"
|
||||
assert caplog.records[0].msg == "boo %s"
|
||||
assert "boo arg" in caplog.text
|
||||
|
||||
|
||||
def test_messages(caplog):
|
||||
caplog.set_level(logging.INFO)
|
||||
logger.info("boo %s", "arg")
|
||||
logger.info("bar %s\nbaz %s", "arg1", "arg2")
|
||||
assert "boo arg" == caplog.messages[0]
|
||||
assert "bar arg1\nbaz arg2" == caplog.messages[1]
|
||||
assert caplog.text.count("\n") > len(caplog.messages)
|
||||
assert len(caplog.text.splitlines()) > len(caplog.messages)
|
||||
|
||||
try:
|
||||
raise Exception("test")
|
||||
except Exception:
|
||||
logger.exception("oops")
|
||||
|
||||
assert "oops" in caplog.text
|
||||
assert "oops" in caplog.messages[-1]
|
||||
# Tracebacks are stored in the record and not added until the formatter or handler.
|
||||
assert "Exception" in caplog.text
|
||||
assert "Exception" not in caplog.messages[-1]
|
||||
|
||||
|
||||
def test_record_tuples(caplog):
|
||||
caplog.set_level(logging.INFO)
|
||||
logger.info('boo %s', 'arg')
|
||||
logger.info("boo %s", "arg")
|
||||
|
||||
assert caplog.record_tuples == [
|
||||
(__name__, logging.INFO, 'boo arg'),
|
||||
]
|
||||
assert caplog.record_tuples == [(__name__, logging.INFO, "boo arg")]
|
||||
|
||||
|
||||
def test_unicode(caplog):
|
||||
caplog.set_level(logging.INFO)
|
||||
logger.info(u'bū')
|
||||
assert caplog.records[0].levelname == 'INFO'
|
||||
assert caplog.records[0].msg == u'bū'
|
||||
assert u'bū' in caplog.text
|
||||
logger.info(u"bū")
|
||||
assert caplog.records[0].levelname == "INFO"
|
||||
assert caplog.records[0].msg == u"bū"
|
||||
assert u"bū" in caplog.text
|
||||
|
||||
|
||||
def test_clear(caplog):
|
||||
caplog.set_level(logging.INFO)
|
||||
logger.info(u'bū')
|
||||
logger.info(u"bū")
|
||||
assert len(caplog.records)
|
||||
assert caplog.text
|
||||
caplog.clear()
|
||||
@@ -103,20 +121,20 @@ def test_clear(caplog):
|
||||
|
||||
@pytest.fixture
|
||||
def logging_during_setup_and_teardown(caplog):
|
||||
caplog.set_level('INFO')
|
||||
logger.info('a_setup_log')
|
||||
caplog.set_level("INFO")
|
||||
logger.info("a_setup_log")
|
||||
yield
|
||||
logger.info('a_teardown_log')
|
||||
assert [x.message for x in caplog.get_records('teardown')] == ['a_teardown_log']
|
||||
logger.info("a_teardown_log")
|
||||
assert [x.message for x in caplog.get_records("teardown")] == ["a_teardown_log"]
|
||||
|
||||
|
||||
def test_caplog_captures_for_all_stages(caplog, logging_during_setup_and_teardown):
|
||||
assert not caplog.records
|
||||
assert not caplog.get_records('call')
|
||||
logger.info('a_call_log')
|
||||
assert [x.message for x in caplog.get_records('call')] == ['a_call_log']
|
||||
assert not caplog.get_records("call")
|
||||
logger.info("a_call_log")
|
||||
assert [x.message for x in caplog.get_records("call")] == ["a_call_log"]
|
||||
|
||||
assert [x.message for x in caplog.get_records('setup')] == ['a_setup_log']
|
||||
assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"]
|
||||
|
||||
# This reachers into private API, don't use this type of thing in real tests!
|
||||
assert set(caplog._item.catch_log_handlers.keys()) == {'setup', 'call'}
|
||||
assert set(caplog._item.catch_log_handlers.keys()) == {"setup", "call"}
|
||||
|
||||
@@ -5,11 +5,17 @@ from _pytest.logging import ColoredLevelFormatter
|
||||
|
||||
|
||||
def test_coloredlogformatter():
|
||||
logfmt = '%(filename)-25s %(lineno)4d %(levelname)-8s %(message)s'
|
||||
logfmt = "%(filename)-25s %(lineno)4d %(levelname)-8s %(message)s"
|
||||
|
||||
record = logging.LogRecord(
|
||||
name='dummy', level=logging.INFO, pathname='dummypath', lineno=10,
|
||||
msg='Test Message', args=(), exc_info=False)
|
||||
name="dummy",
|
||||
level=logging.INFO,
|
||||
pathname="dummypath",
|
||||
lineno=10,
|
||||
msg="Test Message",
|
||||
args=(),
|
||||
exc_info=False,
|
||||
)
|
||||
|
||||
class ColorConfig(object):
|
||||
class option(object):
|
||||
@@ -19,11 +25,11 @@ def test_coloredlogformatter():
|
||||
tw.hasmarkup = True
|
||||
formatter = ColoredLevelFormatter(tw, logfmt)
|
||||
output = formatter.format(record)
|
||||
assert output == ('dummypath 10 '
|
||||
'\x1b[32mINFO \x1b[0m Test Message')
|
||||
assert output == (
|
||||
"dummypath 10 " "\x1b[32mINFO \x1b[0m Test Message"
|
||||
)
|
||||
|
||||
tw.hasmarkup = False
|
||||
formatter = ColoredLevelFormatter(tw, logfmt)
|
||||
output = formatter.format(record)
|
||||
assert output == ('dummypath 10 '
|
||||
'INFO Test Message')
|
||||
assert output == ("dummypath 10 " "INFO Test Message")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,40 +8,69 @@ from pytest import approx
|
||||
from operator import eq, ne
|
||||
from decimal import Decimal
|
||||
from fractions import Fraction
|
||||
inf, nan = float('inf'), float('nan')
|
||||
|
||||
inf, nan = float("inf"), float("nan")
|
||||
|
||||
|
||||
class MyDocTestRunner(doctest.DocTestRunner):
|
||||
|
||||
def __init__(self):
|
||||
doctest.DocTestRunner.__init__(self)
|
||||
|
||||
def report_failure(self, out, test, example, got):
|
||||
raise AssertionError("'{}' evaluates to '{}', not '{}'".format(
|
||||
example.source.strip(), got.strip(), example.want.strip()))
|
||||
raise AssertionError(
|
||||
"'{}' evaluates to '{}', not '{}'".format(
|
||||
example.source.strip(), got.strip(), example.want.strip()
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class TestApprox(object):
|
||||
@pytest.fixture
|
||||
def plus_minus(self):
|
||||
return u"\u00b1" if sys.version_info[0] > 2 else u"+-"
|
||||
|
||||
def test_repr_string(self):
|
||||
plus_minus = u'\u00b1' if sys.version_info[0] > 2 else u'+-'
|
||||
tol1, tol2, infr = '1.0e-06', '2.0e-06', 'inf'
|
||||
assert repr(approx(1.0)) == '1.0 {pm} {tol1}'.format(pm=plus_minus, tol1=tol1)
|
||||
assert repr(approx([1.0, 2.0])) == 'approx([1.0 {pm} {tol1}, 2.0 {pm} {tol2}])'.format(
|
||||
pm=plus_minus, tol1=tol1, tol2=tol2)
|
||||
assert repr(approx((1.0, 2.0))) == 'approx((1.0 {pm} {tol1}, 2.0 {pm} {tol2}))'.format(
|
||||
pm=plus_minus, tol1=tol1, tol2=tol2)
|
||||
assert repr(approx(inf)) == 'inf'
|
||||
assert repr(approx(1.0, rel=nan)) == '1.0 {pm} ???'.format(pm=plus_minus)
|
||||
assert repr(approx(1.0, rel=inf)) == '1.0 {pm} {infr}'.format(pm=plus_minus, infr=infr)
|
||||
assert repr(approx(1.0j, rel=inf)) == '1j'
|
||||
def test_repr_string(self, plus_minus):
|
||||
tol1, tol2, infr = "1.0e-06", "2.0e-06", "inf"
|
||||
assert repr(approx(1.0)) == "1.0 {pm} {tol1}".format(pm=plus_minus, tol1=tol1)
|
||||
assert repr(
|
||||
approx([1.0, 2.0])
|
||||
) == "approx([1.0 {pm} {tol1}, 2.0 {pm} {tol2}])".format(
|
||||
pm=plus_minus, tol1=tol1, tol2=tol2
|
||||
)
|
||||
assert repr(
|
||||
approx((1.0, 2.0))
|
||||
) == "approx((1.0 {pm} {tol1}, 2.0 {pm} {tol2}))".format(
|
||||
pm=plus_minus, tol1=tol1, tol2=tol2
|
||||
)
|
||||
assert repr(approx(inf)) == "inf"
|
||||
assert repr(approx(1.0, rel=nan)) == "1.0 {pm} ???".format(pm=plus_minus)
|
||||
assert repr(approx(1.0, rel=inf)) == "1.0 {pm} {infr}".format(
|
||||
pm=plus_minus, infr=infr
|
||||
)
|
||||
assert repr(approx(1.0j, rel=inf)) == "1j"
|
||||
|
||||
# Dictionaries aren't ordered, so we need to check both orders.
|
||||
assert repr(approx({'a': 1.0, 'b': 2.0})) in (
|
||||
"approx({{'a': 1.0 {pm} {tol1}, 'b': 2.0 {pm} {tol2}}})".format(pm=plus_minus, tol1=tol1, tol2=tol2),
|
||||
"approx({{'b': 2.0 {pm} {tol2}, 'a': 1.0 {pm} {tol1}}})".format(pm=plus_minus, tol1=tol1, tol2=tol2),
|
||||
assert repr(approx({"a": 1.0, "b": 2.0})) in (
|
||||
"approx({{'a': 1.0 {pm} {tol1}, 'b': 2.0 {pm} {tol2}}})".format(
|
||||
pm=plus_minus, tol1=tol1, tol2=tol2
|
||||
),
|
||||
"approx({{'b': 2.0 {pm} {tol2}, 'a': 1.0 {pm} {tol1}}})".format(
|
||||
pm=plus_minus, tol1=tol1, tol2=tol2
|
||||
),
|
||||
)
|
||||
|
||||
def test_repr_0d_array(self, plus_minus):
|
||||
np = pytest.importorskip("numpy")
|
||||
np_array = np.array(5.)
|
||||
assert approx(np_array) == 5.0
|
||||
string_expected = "approx([5.0 {} 5.0e-06])".format(plus_minus)
|
||||
|
||||
assert repr(approx(np_array)) == string_expected
|
||||
|
||||
np_array = np.array([5.])
|
||||
assert approx(np_array) == 5.0
|
||||
assert repr(approx(np_array)) == string_expected
|
||||
|
||||
def test_operator_overloading(self):
|
||||
assert 1 == approx(1, rel=1e-6, abs=1e-12)
|
||||
assert not (1 != approx(1, rel=1e-6, abs=1e-12))
|
||||
@@ -56,25 +85,19 @@ class TestApprox(object):
|
||||
(12345, 12345.0),
|
||||
(0.0, -0.0),
|
||||
(345678, 345678),
|
||||
(Decimal('1.0001'), Decimal('1.0001')),
|
||||
(Decimal("1.0001"), Decimal("1.0001")),
|
||||
(Fraction(1, 3), Fraction(-1, -3)),
|
||||
]
|
||||
for a, x in examples:
|
||||
assert a == approx(x)
|
||||
|
||||
def test_opposite_sign(self):
|
||||
examples = [
|
||||
(eq, 1e-100, -1e-100),
|
||||
(ne, 1e100, -1e100),
|
||||
]
|
||||
examples = [(eq, 1e-100, -1e-100), (ne, 1e100, -1e100)]
|
||||
for op, a, x in examples:
|
||||
assert op(a, approx(x))
|
||||
|
||||
def test_zero_tolerance(self):
|
||||
within_1e10 = [
|
||||
(1.1e-100, 1e-100),
|
||||
(-1.1e-100, -1e-100),
|
||||
]
|
||||
within_1e10 = [(1.1e-100, 1e-100), (-1.1e-100, -1e-100)]
|
||||
for a, x in within_1e10:
|
||||
assert x == approx(x, rel=0.0, abs=0.0)
|
||||
assert a != approx(x, rel=0.0, abs=0.0)
|
||||
@@ -98,12 +121,7 @@ class TestApprox(object):
|
||||
|
||||
def test_inf_tolerance(self):
|
||||
# Everything should be equal if the tolerance is infinite.
|
||||
large_diffs = [
|
||||
(1, 1000),
|
||||
(1e-50, 1e50),
|
||||
(-1.0, -1e300),
|
||||
(0.0, 10),
|
||||
]
|
||||
large_diffs = [(1, 1000), (1e-50, 1e50), (-1.0, -1e300), (0.0, 10)]
|
||||
for a, x in large_diffs:
|
||||
assert a != approx(x, rel=0.0, abs=0.0)
|
||||
assert a == approx(x, rel=inf, abs=0.0)
|
||||
@@ -113,20 +131,13 @@ class TestApprox(object):
|
||||
def test_inf_tolerance_expecting_zero(self):
|
||||
# If the relative tolerance is zero but the expected value is infinite,
|
||||
# the actual tolerance is a NaN, which should be an error.
|
||||
illegal_kwargs = [
|
||||
dict(rel=inf, abs=0.0),
|
||||
dict(rel=inf, abs=inf),
|
||||
]
|
||||
illegal_kwargs = [dict(rel=inf, abs=0.0), dict(rel=inf, abs=inf)]
|
||||
for kwargs in illegal_kwargs:
|
||||
with pytest.raises(ValueError):
|
||||
1 == approx(0, **kwargs)
|
||||
|
||||
def test_nan_tolerance(self):
|
||||
illegal_kwargs = [
|
||||
dict(rel=nan),
|
||||
dict(abs=nan),
|
||||
dict(rel=nan, abs=nan),
|
||||
]
|
||||
illegal_kwargs = [dict(rel=nan), dict(abs=nan), dict(rel=nan, abs=nan)]
|
||||
for kwargs in illegal_kwargs:
|
||||
with pytest.raises(ValueError):
|
||||
1.1 == approx(1, **kwargs)
|
||||
@@ -148,8 +159,8 @@ class TestApprox(object):
|
||||
(eq, 1e0 + 1e-6, 1e0),
|
||||
(ne, 1e0 + 2e-6, 1e0),
|
||||
# Absolute tolerance used.
|
||||
(eq, 1e-100, + 1e-106),
|
||||
(eq, 1e-100, + 2e-106),
|
||||
(eq, 1e-100, +1e-106),
|
||||
(eq, 1e-100, +2e-106),
|
||||
(eq, 1e-100, 0),
|
||||
]
|
||||
for op, a, x in examples:
|
||||
@@ -172,21 +183,13 @@ class TestApprox(object):
|
||||
assert 1e-8 + 1e-16 != approx(1e-8, rel=5e-9, abs=5e-17)
|
||||
|
||||
def test_relative_tolerance(self):
|
||||
within_1e8_rel = [
|
||||
(1e8 + 1e0, 1e8),
|
||||
(1e0 + 1e-8, 1e0),
|
||||
(1e-8 + 1e-16, 1e-8),
|
||||
]
|
||||
within_1e8_rel = [(1e8 + 1e0, 1e8), (1e0 + 1e-8, 1e0), (1e-8 + 1e-16, 1e-8)]
|
||||
for a, x in within_1e8_rel:
|
||||
assert a == approx(x, rel=5e-8, abs=0.0)
|
||||
assert a != approx(x, rel=5e-9, abs=0.0)
|
||||
|
||||
def test_absolute_tolerance(self):
|
||||
within_1e8_abs = [
|
||||
(1e8 + 9e-9, 1e8),
|
||||
(1e0 + 9e-9, 1e0),
|
||||
(1e-8 + 9e-9, 1e-8),
|
||||
]
|
||||
within_1e8_abs = [(1e8 + 9e-9, 1e8), (1e0 + 9e-9, 1e0), (1e-8 + 9e-9, 1e-8)]
|
||||
for a, x in within_1e8_abs:
|
||||
assert a == approx(x, rel=0, abs=5e-8)
|
||||
assert a != approx(x, rel=0, abs=5e-9)
|
||||
@@ -233,10 +236,7 @@ class TestApprox(object):
|
||||
assert op(a, approx(x, nan_ok=True))
|
||||
|
||||
def test_int(self):
|
||||
within_1e6 = [
|
||||
(1000001, 1000000),
|
||||
(-1000001, -1000000),
|
||||
]
|
||||
within_1e6 = [(1000001, 1000000), (-1000001, -1000000)]
|
||||
for a, x in within_1e6:
|
||||
assert a == approx(x, rel=5e-6, abs=0)
|
||||
assert a != approx(x, rel=5e-7, abs=0)
|
||||
@@ -245,15 +245,15 @@ class TestApprox(object):
|
||||
|
||||
def test_decimal(self):
|
||||
within_1e6 = [
|
||||
(Decimal('1.000001'), Decimal('1.0')),
|
||||
(Decimal('-1.000001'), Decimal('-1.0')),
|
||||
(Decimal("1.000001"), Decimal("1.0")),
|
||||
(Decimal("-1.000001"), Decimal("-1.0")),
|
||||
]
|
||||
for a, x in within_1e6:
|
||||
assert a == approx(x)
|
||||
assert a == approx(x, rel=Decimal('5e-6'), abs=0)
|
||||
assert a != approx(x, rel=Decimal('5e-7'), abs=0)
|
||||
assert approx(x, rel=Decimal('5e-6'), abs=0) == a
|
||||
assert approx(x, rel=Decimal('5e-7'), abs=0) != a
|
||||
assert a == approx(x, rel=Decimal("5e-6"), abs=0)
|
||||
assert a != approx(x, rel=Decimal("5e-7"), abs=0)
|
||||
assert approx(x, rel=Decimal("5e-6"), abs=0) == a
|
||||
assert approx(x, rel=Decimal("5e-7"), abs=0) != a
|
||||
|
||||
def test_fraction(self):
|
||||
within_1e6 = [
|
||||
@@ -308,10 +308,10 @@ class TestApprox(object):
|
||||
assert (1, 2) != approx((1, 2, 3))
|
||||
|
||||
def test_dict(self):
|
||||
actual = {'a': 1 + 1e-7, 'b': 2 + 1e-8}
|
||||
actual = {"a": 1 + 1e-7, "b": 2 + 1e-8}
|
||||
# Dictionaries became ordered in python3.6, so switch up the order here
|
||||
# to make sure it doesn't matter.
|
||||
expected = {'b': 2, 'a': 1}
|
||||
expected = {"b": 2, "a": 1}
|
||||
|
||||
# Return false if any element is outside the tolerance.
|
||||
assert actual == approx(expected, rel=5e-7, abs=0)
|
||||
@@ -320,12 +320,12 @@ class TestApprox(object):
|
||||
assert approx(expected, rel=5e-8, abs=0) != actual
|
||||
|
||||
def test_dict_wrong_len(self):
|
||||
assert {'a': 1, 'b': 2} != approx({'a': 1})
|
||||
assert {'a': 1, 'b': 2} != approx({'a': 1, 'c': 2})
|
||||
assert {'a': 1, 'b': 2} != approx({'a': 1, 'b': 2, 'c': 3})
|
||||
assert {"a": 1, "b": 2} != approx({"a": 1})
|
||||
assert {"a": 1, "b": 2} != approx({"a": 1, "c": 2})
|
||||
assert {"a": 1, "b": 2} != approx({"a": 1, "b": 2, "c": 3})
|
||||
|
||||
def test_numpy_array(self):
|
||||
np = pytest.importorskip('numpy')
|
||||
np = pytest.importorskip("numpy")
|
||||
|
||||
actual = np.array([1 + 1e-7, 2 + 1e-8])
|
||||
expected = np.array([1, 2])
|
||||
@@ -343,7 +343,7 @@ class TestApprox(object):
|
||||
assert actual != approx(list(expected), rel=5e-8, abs=0)
|
||||
|
||||
def test_numpy_array_wrong_shape(self):
|
||||
np = pytest.importorskip('numpy')
|
||||
np = pytest.importorskip("numpy")
|
||||
|
||||
a12 = np.array([[1, 2]])
|
||||
a21 = np.array([[1], [2]])
|
||||
@@ -354,10 +354,7 @@ class TestApprox(object):
|
||||
def test_doctests(self):
|
||||
parser = doctest.DocTestParser()
|
||||
test = parser.get_doctest(
|
||||
approx.__doc__,
|
||||
{'approx': approx},
|
||||
approx.__name__,
|
||||
None, None,
|
||||
approx.__doc__, {"approx": approx}, approx.__name__, None, None
|
||||
)
|
||||
runner = MyDocTestRunner()
|
||||
runner.run(test)
|
||||
@@ -367,24 +364,28 @@ class TestApprox(object):
|
||||
Comparing approx instances inside lists should not produce an error in the detailed diff.
|
||||
Integration test for issue #2111.
|
||||
"""
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def test_foo():
|
||||
assert [3] == [pytest.approx(4)]
|
||||
""")
|
||||
expected = '4.0e-06'
|
||||
"""
|
||||
)
|
||||
expected = "4.0e-06"
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
'*At index 0 diff: 3 != 4 * {0}'.format(expected),
|
||||
'=* 1 failed in *=',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
["*At index 0 diff: 3 != 4 * {}".format(expected), "=* 1 failed in *="]
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize('op', [
|
||||
pytest.param(operator.le, id='<='),
|
||||
pytest.param(operator.lt, id='<'),
|
||||
pytest.param(operator.ge, id='>='),
|
||||
pytest.param(operator.gt, id='>'),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"op",
|
||||
[
|
||||
pytest.param(operator.le, id="<="),
|
||||
pytest.param(operator.lt, id="<"),
|
||||
pytest.param(operator.ge, id=">="),
|
||||
pytest.param(operator.gt, id=">"),
|
||||
],
|
||||
)
|
||||
def test_comparison_operator_type_error(self, op):
|
||||
"""
|
||||
pytest.approx should raise TypeError for operators other than == and != (#2003).
|
||||
@@ -393,7 +394,7 @@ class TestApprox(object):
|
||||
op(1, approx(1, rel=1e-6, abs=1e-12))
|
||||
|
||||
def test_numpy_array_with_scalar(self):
|
||||
np = pytest.importorskip('numpy')
|
||||
np = pytest.importorskip("numpy")
|
||||
|
||||
actual = np.array([1 + 1e-7, 1 - 1e-8])
|
||||
expected = 1.0
|
||||
@@ -404,7 +405,7 @@ class TestApprox(object):
|
||||
assert approx(expected, rel=5e-8, abs=0) != actual
|
||||
|
||||
def test_numpy_scalar_with_array(self):
|
||||
np = pytest.importorskip('numpy')
|
||||
np = pytest.importorskip("numpy")
|
||||
|
||||
actual = 1.0
|
||||
expected = np.array([1 + 1e-7, 1 - 1e-8])
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,8 @@ from _pytest import runner
|
||||
|
||||
class TestOEJSKITSpecials(object):
|
||||
def test_funcarg_non_pycollectobj(self, testdir): # rough jstests usage
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import pytest
|
||||
def pytest_pycollect_makeitem(collector, name, obj):
|
||||
if name == "MyClass":
|
||||
@@ -13,25 +14,29 @@ class TestOEJSKITSpecials(object):
|
||||
class MyCollector(pytest.Collector):
|
||||
def reportinfo(self):
|
||||
return self.fspath, 3, "xyz"
|
||||
""")
|
||||
modcol = testdir.getmodulecol("""
|
||||
"""
|
||||
)
|
||||
modcol = testdir.getmodulecol(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def arg1(request):
|
||||
return 42
|
||||
class MyClass(object):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
# this hook finds funcarg factories
|
||||
rep = runner.collect_one_node(collector=modcol)
|
||||
clscol = rep.result[0]
|
||||
clscol.obj = lambda arg1: None
|
||||
clscol.funcargs = {}
|
||||
pytest._fillfuncargs(clscol)
|
||||
assert clscol.funcargs['arg1'] == 42
|
||||
assert clscol.funcargs["arg1"] == 42
|
||||
|
||||
def test_autouse_fixture(self, testdir): # rough jstests usage
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import pytest
|
||||
def pytest_pycollect_makeitem(collector, name, obj):
|
||||
if name == "MyClass":
|
||||
@@ -39,8 +44,10 @@ class TestOEJSKITSpecials(object):
|
||||
class MyCollector(pytest.Collector):
|
||||
def reportinfo(self):
|
||||
return self.fspath, 3, "xyz"
|
||||
""")
|
||||
modcol = testdir.getmodulecol("""
|
||||
"""
|
||||
)
|
||||
modcol = testdir.getmodulecol(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.fixture(autouse=True)
|
||||
def hello():
|
||||
@@ -50,7 +57,8 @@ class TestOEJSKITSpecials(object):
|
||||
return 42
|
||||
class MyClass(object):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
# this hook finds funcarg factories
|
||||
rep = runner.collect_one_node(modcol)
|
||||
clscol = rep.result[0]
|
||||
@@ -72,6 +80,7 @@ def test_wrapped_getfslineno():
|
||||
@wrap
|
||||
def wrapped_func(x, y, z):
|
||||
pass
|
||||
|
||||
fs, lineno = python.getfslineno(wrapped_func)
|
||||
fs2, lineno2 = python.getfslineno(wrap)
|
||||
assert lineno > lineno2, "getfslineno does not unwrap correctly"
|
||||
@@ -82,7 +91,6 @@ class TestMockDecoration(object):
|
||||
from _pytest.compat import getfuncargnames
|
||||
|
||||
def wrap(f):
|
||||
|
||||
def func():
|
||||
pass
|
||||
|
||||
@@ -96,12 +104,16 @@ class TestMockDecoration(object):
|
||||
values = getfuncargnames(f)
|
||||
assert values == ("x",)
|
||||
|
||||
@pytest.mark.xfail(
|
||||
strict=False, reason="getfuncargnames breaks if mock is imported"
|
||||
)
|
||||
def test_wrapped_getfuncargnames_patching(self):
|
||||
from _pytest.compat import getfuncargnames
|
||||
|
||||
def wrap(f):
|
||||
def func():
|
||||
pass
|
||||
|
||||
func.__wrapped__ = f
|
||||
func.patchings = ["qwe"]
|
||||
return func
|
||||
@@ -115,7 +127,8 @@ class TestMockDecoration(object):
|
||||
|
||||
def test_unittest_mock(self, testdir):
|
||||
pytest.importorskip("unittest.mock")
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import unittest.mock
|
||||
class T(unittest.TestCase):
|
||||
@unittest.mock.patch("os.path.abspath")
|
||||
@@ -123,13 +136,15 @@ class TestMockDecoration(object):
|
||||
import os
|
||||
os.path.abspath("hello")
|
||||
abspath.assert_any_call("hello")
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=1)
|
||||
|
||||
def test_unittest_mock_and_fixture(self, testdir):
|
||||
pytest.importorskip("unittest.mock")
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import os.path
|
||||
import unittest.mock
|
||||
import pytest
|
||||
@@ -143,14 +158,16 @@ class TestMockDecoration(object):
|
||||
def test_hello(inject_me):
|
||||
import os
|
||||
os.path.abspath("hello")
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=1)
|
||||
|
||||
def test_unittest_mock_and_pypi_mock(self, testdir):
|
||||
pytest.importorskip("unittest.mock")
|
||||
pytest.importorskip("mock", "1.0.1")
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import mock
|
||||
import unittest.mock
|
||||
class TestBoth(object):
|
||||
@@ -165,13 +182,15 @@ class TestMockDecoration(object):
|
||||
import os
|
||||
os.path.abspath("hello")
|
||||
abspath.assert_any_call("hello")
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=2)
|
||||
|
||||
def test_mock(self, testdir):
|
||||
pytest.importorskip("mock", "1.0.1")
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import os
|
||||
import unittest
|
||||
import mock
|
||||
@@ -191,17 +210,20 @@ class TestMockDecoration(object):
|
||||
os.path.normpath(os.path.abspath("hello"))
|
||||
normpath.assert_any_call("this")
|
||||
assert os.path.basename("123") == "mock_basename"
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=2)
|
||||
calls = reprec.getcalls("pytest_runtest_logreport")
|
||||
funcnames = [call.report.location[2] for call in calls
|
||||
if call.report.when == "call"]
|
||||
funcnames = [
|
||||
call.report.location[2] for call in calls if call.report.when == "call"
|
||||
]
|
||||
assert funcnames == ["T.test_hello", "test_someting"]
|
||||
|
||||
def test_mock_sorting(self, testdir):
|
||||
pytest.importorskip("mock", "1.0.1")
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import os
|
||||
import mock
|
||||
|
||||
@@ -214,7 +236,8 @@ class TestMockDecoration(object):
|
||||
@mock.patch("os.path.abspath")
|
||||
def test_three(abspath):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
calls = reprec.getreports("pytest_runtest_logreport")
|
||||
calls = [x for x in calls if x.when == "call"]
|
||||
@@ -223,7 +246,8 @@ class TestMockDecoration(object):
|
||||
|
||||
def test_mock_double_patch_issue473(self, testdir):
|
||||
pytest.importorskip("mock", "1.0.1")
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
from mock import patch
|
||||
from pytest import mark
|
||||
|
||||
@@ -233,20 +257,24 @@ class TestMockDecoration(object):
|
||||
class TestSimple(object):
|
||||
def test_simple_thing(self, mock_path, mock_getcwd):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=1)
|
||||
|
||||
|
||||
class TestReRunTests(object):
|
||||
def test_rerun(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
from _pytest.runner import runtestprotocol
|
||||
def pytest_runtest_protocol(item, nextitem):
|
||||
runtestprotocol(item, log=False, nextitem=nextitem)
|
||||
runtestprotocol(item, log=True, nextitem=nextitem)
|
||||
""")
|
||||
testdir.makepyfile("""
|
||||
"""
|
||||
)
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
count = 0
|
||||
req = None
|
||||
@@ -259,36 +287,45 @@ class TestReRunTests(object):
|
||||
count += 1
|
||||
def test_fix(fix):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("-s")
|
||||
result.stdout.fnmatch_lines("""
|
||||
result.stdout.fnmatch_lines(
|
||||
"""
|
||||
*fix count 0*
|
||||
*fix count 1*
|
||||
""")
|
||||
result.stdout.fnmatch_lines("""
|
||||
"""
|
||||
)
|
||||
result.stdout.fnmatch_lines(
|
||||
"""
|
||||
*2 passed*
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def test_pytestconfig_is_session_scoped():
|
||||
from _pytest.fixtures import pytestconfig
|
||||
|
||||
assert pytestconfig._pytestfixturefunction.scope == "session"
|
||||
|
||||
|
||||
class TestNoselikeTestAttribute(object):
|
||||
def test_module_with_global_test(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
__test__ = False
|
||||
def test_hello():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
assert not reprec.getfailedcollections()
|
||||
calls = reprec.getreports("pytest_runtest_logreport")
|
||||
assert not calls
|
||||
|
||||
def test_class_and_method(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
__test__ = True
|
||||
def test_func():
|
||||
pass
|
||||
@@ -298,14 +335,16 @@ class TestNoselikeTestAttribute(object):
|
||||
__test__ = False
|
||||
def test_method(self):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
assert not reprec.getfailedcollections()
|
||||
calls = reprec.getreports("pytest_runtest_logreport")
|
||||
assert not calls
|
||||
|
||||
def test_unittest_class(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
class TC(unittest.TestCase):
|
||||
def test_1(self):
|
||||
@@ -314,7 +353,8 @@ class TestNoselikeTestAttribute(object):
|
||||
__test__ = False
|
||||
def test_2(self):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
assert not reprec.getfailedcollections()
|
||||
call = reprec.getcalls("pytest_collection_modifyitems")[0]
|
||||
@@ -328,7 +368,8 @@ class TestNoselikeTestAttribute(object):
|
||||
RPC wrapper), we shouldn't assume this meant "__test__ = True".
|
||||
"""
|
||||
# https://github.com/pytest-dev/pytest/issues/1204
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
class MetaModel(type):
|
||||
|
||||
def __getattr__(cls, key):
|
||||
@@ -344,7 +385,8 @@ class TestNoselikeTestAttribute(object):
|
||||
|
||||
def test_blah(self):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
assert not reprec.getfailedcollections()
|
||||
call = reprec.getcalls("pytest_collection_modifyitems")[0]
|
||||
@@ -353,9 +395,9 @@ class TestNoselikeTestAttribute(object):
|
||||
|
||||
@pytest.mark.issue351
|
||||
class TestParameterize(object):
|
||||
|
||||
def test_idfn_marker(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
|
||||
def idfn(param):
|
||||
@@ -369,15 +411,14 @@ class TestParameterize(object):
|
||||
@pytest.mark.parametrize('a,b', [(0, 2), (1, 2)], ids=idfn)
|
||||
def test_params(a, b):
|
||||
pass
|
||||
""")
|
||||
res = testdir.runpytest('--collect-only')
|
||||
res.stdout.fnmatch_lines([
|
||||
"*spam-2*",
|
||||
"*ham-2*",
|
||||
])
|
||||
"""
|
||||
)
|
||||
res = testdir.runpytest("--collect-only")
|
||||
res.stdout.fnmatch_lines(["*spam-2*", "*ham-2*"])
|
||||
|
||||
def test_idfn_fixture(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
|
||||
def idfn(param):
|
||||
@@ -398,9 +439,7 @@ class TestParameterize(object):
|
||||
|
||||
def test_params(a, b):
|
||||
pass
|
||||
""")
|
||||
res = testdir.runpytest('--collect-only')
|
||||
res.stdout.fnmatch_lines([
|
||||
"*spam-2*",
|
||||
"*ham-2*",
|
||||
])
|
||||
"""
|
||||
)
|
||||
res = testdir.runpytest("--collect-only")
|
||||
res.stdout.fnmatch_lines(["*spam-2*", "*ham-2*"])
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,19 +18,21 @@ class TestRaises(object):
|
||||
pytest.raises(SyntaxError, "qwe qwe qwe")
|
||||
|
||||
def test_raises_function(self):
|
||||
pytest.raises(ValueError, int, 'hello')
|
||||
pytest.raises(ValueError, int, "hello")
|
||||
|
||||
def test_raises_callable_no_exception(self):
|
||||
class A(object):
|
||||
def __call__(self):
|
||||
pass
|
||||
|
||||
try:
|
||||
pytest.raises(ValueError, A())
|
||||
except pytest.raises.Exception:
|
||||
pass
|
||||
|
||||
def test_raises_as_contextmanager(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
from __future__ import with_statement
|
||||
import py, pytest
|
||||
import _pytest._code
|
||||
@@ -52,30 +54,29 @@ class TestRaises(object):
|
||||
with pytest.raises(ZeroDivisionError):
|
||||
with pytest.raises(ValueError):
|
||||
1/0
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
'*3 passed*',
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*3 passed*"])
|
||||
|
||||
def test_noclass(self):
|
||||
with pytest.raises(TypeError):
|
||||
pytest.raises('wrong', lambda: None)
|
||||
pytest.raises("wrong", lambda: None)
|
||||
|
||||
def test_invalid_arguments_to_raises(self):
|
||||
with pytest.raises(TypeError, match='unknown'):
|
||||
with pytest.raises(TypeError, unknown='bogus'):
|
||||
with pytest.raises(TypeError, match="unknown"):
|
||||
with pytest.raises(TypeError, unknown="bogus"):
|
||||
raise ValueError()
|
||||
|
||||
def test_tuple(self):
|
||||
with pytest.raises((KeyError, ValueError)):
|
||||
raise KeyError('oops')
|
||||
raise KeyError("oops")
|
||||
|
||||
def test_no_raise_message(self):
|
||||
try:
|
||||
pytest.raises(ValueError, int, '0')
|
||||
pytest.raises(ValueError, int, "0")
|
||||
except pytest.raises.Exception as e:
|
||||
assert e.msg == "DID NOT RAISE {0}".format(repr(ValueError))
|
||||
assert e.msg == "DID NOT RAISE {}".format(repr(ValueError))
|
||||
else:
|
||||
assert False, "Expected pytest.raises.Exception"
|
||||
|
||||
@@ -83,7 +84,7 @@ class TestRaises(object):
|
||||
with pytest.raises(ValueError):
|
||||
pass
|
||||
except pytest.raises.Exception as e:
|
||||
assert e.msg == "DID NOT RAISE {0}".format(repr(ValueError))
|
||||
assert e.msg == "DID NOT RAISE {}".format(repr(ValueError))
|
||||
else:
|
||||
assert False, "Expected pytest.raises.Exception"
|
||||
|
||||
@@ -97,7 +98,7 @@ class TestRaises(object):
|
||||
else:
|
||||
assert False, "Expected pytest.raises.Exception"
|
||||
|
||||
@pytest.mark.parametrize('method', ['function', 'with'])
|
||||
@pytest.mark.parametrize("method", ["function", "with"])
|
||||
def test_raises_cyclic_reference(self, method):
|
||||
"""
|
||||
Ensure pytest.raises does not leave a reference cycle (#1965).
|
||||
@@ -109,7 +110,7 @@ class TestRaises(object):
|
||||
raise ValueError
|
||||
|
||||
t = T()
|
||||
if method == 'function':
|
||||
if method == "function":
|
||||
pytest.raises(ValueError, t)
|
||||
else:
|
||||
with pytest.raises(ValueError):
|
||||
@@ -127,17 +128,19 @@ class TestRaises(object):
|
||||
def test_raises_match(self):
|
||||
msg = r"with base \d+"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
int('asdf')
|
||||
int("asdf")
|
||||
|
||||
msg = "with base 10"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
int('asdf')
|
||||
int("asdf")
|
||||
|
||||
msg = "with base 16"
|
||||
expr = r"Pattern '{0}' not found in 'invalid literal for int\(\) with base 10: 'asdf''".format(msg)
|
||||
expr = r"Pattern '{}' not found in 'invalid literal for int\(\) with base 10: 'asdf''".format(
|
||||
msg
|
||||
)
|
||||
with pytest.raises(AssertionError, match=expr):
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
int('asdf', base=10)
|
||||
int("asdf", base=10)
|
||||
|
||||
def test_raises_match_wrong_type(self):
|
||||
"""Raising an exception with the wrong type and match= given.
|
||||
@@ -146,15 +149,15 @@ class TestRaises(object):
|
||||
really relevant if we got a different exception.
|
||||
"""
|
||||
with pytest.raises(ValueError):
|
||||
with pytest.raises(IndexError, match='nomatch'):
|
||||
int('asdf')
|
||||
with pytest.raises(IndexError, match="nomatch"):
|
||||
int("asdf")
|
||||
|
||||
def test_raises_exception_looks_iterable(self):
|
||||
from six import add_metaclass
|
||||
|
||||
class Meta(type(object)):
|
||||
def __getitem__(self, item):
|
||||
return 1/0
|
||||
return 1 / 0
|
||||
|
||||
def __len__(self):
|
||||
return 1
|
||||
@@ -163,5 +166,7 @@ class TestRaises(object):
|
||||
class ClassLooksIterableException(Exception):
|
||||
pass
|
||||
|
||||
with pytest.raises(Failed, match="DID NOT RAISE <class 'raises.ClassLooksIterableException'>"):
|
||||
with pytest.raises(
|
||||
Failed, match="DID NOT RAISE <class 'raises.ClassLooksIterableException'>"
|
||||
):
|
||||
pytest.raises(ClassLooksIterableException, lambda: None)
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture(params=['--setup-only', '--setup-plan', '--setup-show'],
|
||||
scope='module')
|
||||
@pytest.fixture(params=["--setup-only", "--setup-plan", "--setup-show"], scope="module")
|
||||
def mode(request):
|
||||
return request.param
|
||||
|
||||
|
||||
def test_show_only_active_fixtures(testdir, mode):
|
||||
p = testdir.makepyfile('''
|
||||
p = testdir.makepyfile(
|
||||
'''
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def _arg0():
|
||||
@@ -18,21 +18,21 @@ def test_show_only_active_fixtures(testdir, mode):
|
||||
"""arg1 docstring"""
|
||||
def test_arg1(arg1):
|
||||
pass
|
||||
''')
|
||||
'''
|
||||
)
|
||||
|
||||
result = testdir.runpytest(mode, p)
|
||||
assert result.ret == 0
|
||||
|
||||
result.stdout.fnmatch_lines([
|
||||
'*SETUP F arg1*',
|
||||
'*test_arg1 (fixtures used: arg1)*',
|
||||
'*TEARDOWN F arg1*',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
["*SETUP F arg1*", "*test_arg1 (fixtures used: arg1)*", "*TEARDOWN F arg1*"]
|
||||
)
|
||||
assert "_arg0" not in result.stdout.str()
|
||||
|
||||
|
||||
def test_show_different_scopes(testdir, mode):
|
||||
p = testdir.makepyfile('''
|
||||
p = testdir.makepyfile(
|
||||
'''
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def arg_function():
|
||||
@@ -42,50 +42,60 @@ def test_show_different_scopes(testdir, mode):
|
||||
"""session scoped fixture"""
|
||||
def test_arg1(arg_session, arg_function):
|
||||
pass
|
||||
''')
|
||||
'''
|
||||
)
|
||||
|
||||
result = testdir.runpytest(mode, p)
|
||||
assert result.ret == 0
|
||||
|
||||
result.stdout.fnmatch_lines([
|
||||
'SETUP S arg_session*',
|
||||
'*SETUP F arg_function*',
|
||||
'*test_arg1 (fixtures used: arg_function, arg_session)*',
|
||||
'*TEARDOWN F arg_function*',
|
||||
'TEARDOWN S arg_session*',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"SETUP S arg_session*",
|
||||
"*SETUP F arg_function*",
|
||||
"*test_arg1 (fixtures used: arg_function, arg_session)*",
|
||||
"*TEARDOWN F arg_function*",
|
||||
"TEARDOWN S arg_session*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_show_nested_fixtures(testdir, mode):
|
||||
testdir.makeconftest('''
|
||||
testdir.makeconftest(
|
||||
'''
|
||||
import pytest
|
||||
@pytest.fixture(scope='session')
|
||||
def arg_same():
|
||||
"""session scoped fixture"""
|
||||
''')
|
||||
p = testdir.makepyfile('''
|
||||
'''
|
||||
)
|
||||
p = testdir.makepyfile(
|
||||
'''
|
||||
import pytest
|
||||
@pytest.fixture(scope='function')
|
||||
def arg_same(arg_same):
|
||||
"""function scoped fixture"""
|
||||
def test_arg1(arg_same):
|
||||
pass
|
||||
''')
|
||||
'''
|
||||
)
|
||||
|
||||
result = testdir.runpytest(mode, p)
|
||||
assert result.ret == 0
|
||||
|
||||
result.stdout.fnmatch_lines([
|
||||
'SETUP S arg_same*',
|
||||
'*SETUP F arg_same (fixtures used: arg_same)*',
|
||||
'*test_arg1 (fixtures used: arg_same)*',
|
||||
'*TEARDOWN F arg_same*',
|
||||
'TEARDOWN S arg_same*',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"SETUP S arg_same*",
|
||||
"*SETUP F arg_same (fixtures used: arg_same)*",
|
||||
"*test_arg1 (fixtures used: arg_same)*",
|
||||
"*TEARDOWN F arg_same*",
|
||||
"TEARDOWN S arg_same*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_show_fixtures_with_autouse(testdir, mode):
|
||||
p = testdir.makepyfile('''
|
||||
p = testdir.makepyfile(
|
||||
'''
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def arg_function():
|
||||
@@ -95,92 +105,104 @@ def test_show_fixtures_with_autouse(testdir, mode):
|
||||
"""session scoped fixture"""
|
||||
def test_arg1(arg_function):
|
||||
pass
|
||||
''')
|
||||
'''
|
||||
)
|
||||
|
||||
result = testdir.runpytest(mode, p)
|
||||
assert result.ret == 0
|
||||
|
||||
result.stdout.fnmatch_lines([
|
||||
'SETUP S arg_session*',
|
||||
'*SETUP F arg_function*',
|
||||
'*test_arg1 (fixtures used: arg_function, arg_session)*',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"SETUP S arg_session*",
|
||||
"*SETUP F arg_function*",
|
||||
"*test_arg1 (fixtures used: arg_function, arg_session)*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_show_fixtures_with_parameters(testdir, mode):
|
||||
testdir.makeconftest('''
|
||||
testdir.makeconftest(
|
||||
'''
|
||||
import pytest
|
||||
@pytest.fixture(scope='session', params=['foo', 'bar'])
|
||||
def arg_same():
|
||||
"""session scoped fixture"""
|
||||
''')
|
||||
p = testdir.makepyfile('''
|
||||
'''
|
||||
)
|
||||
p = testdir.makepyfile(
|
||||
'''
|
||||
import pytest
|
||||
@pytest.fixture(scope='function')
|
||||
def arg_other(arg_same):
|
||||
"""function scoped fixture"""
|
||||
def test_arg1(arg_other):
|
||||
pass
|
||||
''')
|
||||
'''
|
||||
)
|
||||
|
||||
result = testdir.runpytest(mode, p)
|
||||
assert result.ret == 0
|
||||
|
||||
result.stdout.fnmatch_lines([
|
||||
'SETUP S arg_same?foo?',
|
||||
'TEARDOWN S arg_same?foo?',
|
||||
'SETUP S arg_same?bar?',
|
||||
'TEARDOWN S arg_same?bar?',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"SETUP S arg_same?foo?",
|
||||
"TEARDOWN S arg_same?foo?",
|
||||
"SETUP S arg_same?bar?",
|
||||
"TEARDOWN S arg_same?bar?",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_show_fixtures_with_parameter_ids(testdir, mode):
|
||||
testdir.makeconftest('''
|
||||
testdir.makeconftest(
|
||||
'''
|
||||
import pytest
|
||||
@pytest.fixture(
|
||||
scope='session', params=['foo', 'bar'], ids=['spam', 'ham'])
|
||||
def arg_same():
|
||||
"""session scoped fixture"""
|
||||
''')
|
||||
p = testdir.makepyfile('''
|
||||
'''
|
||||
)
|
||||
p = testdir.makepyfile(
|
||||
'''
|
||||
import pytest
|
||||
@pytest.fixture(scope='function')
|
||||
def arg_other(arg_same):
|
||||
"""function scoped fixture"""
|
||||
def test_arg1(arg_other):
|
||||
pass
|
||||
''')
|
||||
'''
|
||||
)
|
||||
|
||||
result = testdir.runpytest(mode, p)
|
||||
assert result.ret == 0
|
||||
|
||||
result.stdout.fnmatch_lines([
|
||||
'SETUP S arg_same?spam?',
|
||||
'SETUP S arg_same?ham?',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
["SETUP S arg_same?spam?", "SETUP S arg_same?ham?"]
|
||||
)
|
||||
|
||||
|
||||
def test_show_fixtures_with_parameter_ids_function(testdir, mode):
|
||||
p = testdir.makepyfile('''
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.fixture(params=['foo', 'bar'], ids=lambda p: p.upper())
|
||||
def foobar():
|
||||
pass
|
||||
def test_foobar(foobar):
|
||||
pass
|
||||
''')
|
||||
"""
|
||||
)
|
||||
|
||||
result = testdir.runpytest(mode, p)
|
||||
assert result.ret == 0
|
||||
|
||||
result.stdout.fnmatch_lines([
|
||||
'*SETUP F foobar?FOO?',
|
||||
'*SETUP F foobar?BAR?',
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*SETUP F foobar?FOO?", "*SETUP F foobar?BAR?"])
|
||||
|
||||
|
||||
def test_dynamic_fixture_request(testdir):
|
||||
p = testdir.makepyfile('''
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.fixture()
|
||||
def dynamically_requested_fixture():
|
||||
@@ -190,19 +212,23 @@ def test_dynamic_fixture_request(testdir):
|
||||
request.getfixturevalue('dynamically_requested_fixture')
|
||||
def test_dyn(dependent_fixture):
|
||||
pass
|
||||
''')
|
||||
"""
|
||||
)
|
||||
|
||||
result = testdir.runpytest('--setup-only', p)
|
||||
result = testdir.runpytest("--setup-only", p)
|
||||
assert result.ret == 0
|
||||
|
||||
result.stdout.fnmatch_lines([
|
||||
'*SETUP F dynamically_requested_fixture',
|
||||
'*TEARDOWN F dynamically_requested_fixture'
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*SETUP F dynamically_requested_fixture",
|
||||
"*TEARDOWN F dynamically_requested_fixture",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_capturing(testdir):
|
||||
p = testdir.makepyfile('''
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import pytest, sys
|
||||
@pytest.fixture()
|
||||
def one():
|
||||
@@ -213,31 +239,31 @@ def test_capturing(testdir):
|
||||
assert 0
|
||||
def test_capturing(two):
|
||||
pass
|
||||
''')
|
||||
"""
|
||||
)
|
||||
|
||||
result = testdir.runpytest('--setup-only', p)
|
||||
result.stdout.fnmatch_lines([
|
||||
'this should be captured',
|
||||
'this should also be captured'
|
||||
])
|
||||
result = testdir.runpytest("--setup-only", p)
|
||||
result.stdout.fnmatch_lines(
|
||||
["this should be captured", "this should also be captured"]
|
||||
)
|
||||
|
||||
|
||||
def test_show_fixtures_and_execute_test(testdir):
|
||||
""" Verifies that setups are shown and tests are executed. """
|
||||
p = testdir.makepyfile('''
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def arg():
|
||||
assert True
|
||||
def test_arg(arg):
|
||||
assert False
|
||||
''')
|
||||
"""
|
||||
)
|
||||
|
||||
result = testdir.runpytest("--setup-show", p)
|
||||
assert result.ret == 1
|
||||
|
||||
result.stdout.fnmatch_lines([
|
||||
'*SETUP F arg*',
|
||||
'*test_arg (fixtures used: arg)F*',
|
||||
'*TEARDOWN F arg*',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
["*SETUP F arg*", "*test_arg (fixtures used: arg)F*", "*TEARDOWN F arg*"]
|
||||
)
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
def test_show_fixtures_and_test(testdir):
|
||||
""" Verifies that fixtures are not executed. """
|
||||
p = testdir.makepyfile('''
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def arg():
|
||||
assert False
|
||||
def test_arg(arg):
|
||||
assert False
|
||||
''')
|
||||
"""
|
||||
)
|
||||
|
||||
result = testdir.runpytest("--setup-plan", p)
|
||||
assert result.ret == 0
|
||||
|
||||
result.stdout.fnmatch_lines([
|
||||
'*SETUP F arg*',
|
||||
'*test_arg (fixtures used: arg)',
|
||||
'*TEARDOWN F arg*',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
["*SETUP F arg*", "*test_arg (fixtures used: arg)", "*TEARDOWN F arg*"]
|
||||
)
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
|
||||
|
||||
def test_no_items_should_not_show_output(testdir):
|
||||
result = testdir.runpytest('--fixtures-per-test')
|
||||
assert 'fixtures used by' not in result.stdout.str()
|
||||
result = testdir.runpytest("--fixtures-per-test")
|
||||
assert "fixtures used by" not in result.stdout.str()
|
||||
assert result.ret == 0
|
||||
|
||||
|
||||
def test_fixtures_in_module(testdir):
|
||||
p = testdir.makepyfile('''
|
||||
p = testdir.makepyfile(
|
||||
'''
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def _arg0():
|
||||
@@ -18,22 +19,26 @@ def test_fixtures_in_module(testdir):
|
||||
"""arg1 docstring"""
|
||||
def test_arg1(arg1):
|
||||
pass
|
||||
''')
|
||||
'''
|
||||
)
|
||||
|
||||
result = testdir.runpytest("--fixtures-per-test", p)
|
||||
assert result.ret == 0
|
||||
|
||||
result.stdout.fnmatch_lines([
|
||||
'*fixtures used by test_arg1*',
|
||||
'*(test_fixtures_in_module.py:9)*',
|
||||
'arg1',
|
||||
' arg1 docstring',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*fixtures used by test_arg1*",
|
||||
"*(test_fixtures_in_module.py:9)*",
|
||||
"arg1",
|
||||
" arg1 docstring",
|
||||
]
|
||||
)
|
||||
assert "_arg0" not in result.stdout.str()
|
||||
|
||||
|
||||
def test_fixtures_in_conftest(testdir):
|
||||
testdir.makeconftest('''
|
||||
testdir.makeconftest(
|
||||
'''
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def arg1():
|
||||
@@ -46,35 +51,41 @@ def test_fixtures_in_conftest(testdir):
|
||||
"""arg3
|
||||
docstring
|
||||
"""
|
||||
''')
|
||||
p = testdir.makepyfile('''
|
||||
'''
|
||||
)
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
def test_arg2(arg2):
|
||||
pass
|
||||
def test_arg3(arg3):
|
||||
pass
|
||||
''')
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("--fixtures-per-test", p)
|
||||
assert result.ret == 0
|
||||
|
||||
result.stdout.fnmatch_lines([
|
||||
'*fixtures used by test_arg2*',
|
||||
'*(test_fixtures_in_conftest.py:2)*',
|
||||
'arg2',
|
||||
' arg2 docstring',
|
||||
'*fixtures used by test_arg3*',
|
||||
'*(test_fixtures_in_conftest.py:4)*',
|
||||
'arg1',
|
||||
' arg1 docstring',
|
||||
'arg2',
|
||||
' arg2 docstring',
|
||||
'arg3',
|
||||
' arg3',
|
||||
' docstring',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*fixtures used by test_arg2*",
|
||||
"*(test_fixtures_in_conftest.py:2)*",
|
||||
"arg2",
|
||||
" arg2 docstring",
|
||||
"*fixtures used by test_arg3*",
|
||||
"*(test_fixtures_in_conftest.py:4)*",
|
||||
"arg1",
|
||||
" arg1 docstring",
|
||||
"arg2",
|
||||
" arg2 docstring",
|
||||
"arg3",
|
||||
" arg3",
|
||||
" docstring",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_should_show_fixtures_used_by_test(testdir):
|
||||
testdir.makeconftest('''
|
||||
testdir.makeconftest(
|
||||
'''
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def arg1():
|
||||
@@ -82,30 +93,36 @@ def test_should_show_fixtures_used_by_test(testdir):
|
||||
@pytest.fixture
|
||||
def arg2():
|
||||
"""arg2 from conftest"""
|
||||
''')
|
||||
p = testdir.makepyfile('''
|
||||
'''
|
||||
)
|
||||
p = testdir.makepyfile(
|
||||
'''
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def arg1():
|
||||
"""arg1 from testmodule"""
|
||||
def test_args(arg1, arg2):
|
||||
pass
|
||||
''')
|
||||
'''
|
||||
)
|
||||
result = testdir.runpytest("--fixtures-per-test", p)
|
||||
assert result.ret == 0
|
||||
|
||||
result.stdout.fnmatch_lines([
|
||||
'*fixtures used by test_args*',
|
||||
'*(test_should_show_fixtures_used_by_test.py:6)*',
|
||||
'arg1',
|
||||
' arg1 from testmodule',
|
||||
'arg2',
|
||||
' arg2 from conftest',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*fixtures used by test_args*",
|
||||
"*(test_should_show_fixtures_used_by_test.py:6)*",
|
||||
"arg1",
|
||||
" arg1 from testmodule",
|
||||
"arg2",
|
||||
" arg2 from conftest",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_verbose_include_private_fixtures_and_loc(testdir):
|
||||
testdir.makeconftest('''
|
||||
testdir.makeconftest(
|
||||
'''
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def _arg1():
|
||||
@@ -113,46 +130,54 @@ def test_verbose_include_private_fixtures_and_loc(testdir):
|
||||
@pytest.fixture
|
||||
def arg2(_arg1):
|
||||
"""arg2 from conftest"""
|
||||
''')
|
||||
p = testdir.makepyfile('''
|
||||
'''
|
||||
)
|
||||
p = testdir.makepyfile(
|
||||
'''
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def arg3():
|
||||
"""arg3 from testmodule"""
|
||||
def test_args(arg2, arg3):
|
||||
pass
|
||||
''')
|
||||
'''
|
||||
)
|
||||
result = testdir.runpytest("--fixtures-per-test", "-v", p)
|
||||
assert result.ret == 0
|
||||
|
||||
result.stdout.fnmatch_lines([
|
||||
'*fixtures used by test_args*',
|
||||
'*(test_verbose_include_private_fixtures_and_loc.py:6)*',
|
||||
'_arg1 -- conftest.py:3',
|
||||
' _arg1 from conftest',
|
||||
'arg2 -- conftest.py:6',
|
||||
' arg2 from conftest',
|
||||
'arg3 -- test_verbose_include_private_fixtures_and_loc.py:3',
|
||||
' arg3 from testmodule',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*fixtures used by test_args*",
|
||||
"*(test_verbose_include_private_fixtures_and_loc.py:6)*",
|
||||
"_arg1 -- conftest.py:3",
|
||||
" _arg1 from conftest",
|
||||
"arg2 -- conftest.py:6",
|
||||
" arg2 from conftest",
|
||||
"arg3 -- test_verbose_include_private_fixtures_and_loc.py:3",
|
||||
" arg3 from testmodule",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_doctest_items(testdir):
|
||||
testdir.makepyfile('''
|
||||
testdir.makepyfile(
|
||||
'''
|
||||
def foo():
|
||||
"""
|
||||
>>> 1 + 1
|
||||
2
|
||||
"""
|
||||
''')
|
||||
testdir.maketxtfile('''
|
||||
'''
|
||||
)
|
||||
testdir.maketxtfile(
|
||||
"""
|
||||
>>> 1 + 1
|
||||
2
|
||||
''')
|
||||
result = testdir.runpytest("--fixtures-per-test", "--doctest-modules",
|
||||
"--doctest-glob=*.txt", "-v")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest(
|
||||
"--fixtures-per-test", "--doctest-modules", "--doctest-glob=*.txt", "-v"
|
||||
)
|
||||
assert result.ret == 0
|
||||
|
||||
result.stdout.fnmatch_lines([
|
||||
'*collected 2 items*',
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*collected 2 items*"])
|
||||
|
||||
@@ -18,5 +18,5 @@ def test_pycollector_makeitem_is_deprecated():
|
||||
|
||||
collector = PyCollectorMock()
|
||||
with pytest.deprecated_call():
|
||||
collector.makeitem('foo', 'bar')
|
||||
collector.makeitem("foo", "bar")
|
||||
assert collector.called
|
||||
|
||||
@@ -11,12 +11,13 @@ def equal_with_bash(prefix, ffc, fc, out=None):
|
||||
res_bash = set(fc(prefix))
|
||||
retval = set(res) == res_bash
|
||||
if out:
|
||||
out.write('equal_with_bash %s %s\n' % (retval, res))
|
||||
out.write("equal_with_bash %s %s\n" % (retval, res))
|
||||
if not retval:
|
||||
out.write(' python - bash: %s\n' % (set(res) - res_bash))
|
||||
out.write(' bash - python: %s\n' % (res_bash - set(res)))
|
||||
out.write(" python - bash: %s\n" % (set(res) - res_bash))
|
||||
out.write(" bash - python: %s\n" % (res_bash - set(res)))
|
||||
return retval
|
||||
|
||||
|
||||
# copied from argcomplete.completers as import from there
|
||||
# also pulls in argcomplete.__init__ which opens filedescriptor 9
|
||||
# this gives an IOError at the end of testrun
|
||||
@@ -26,10 +27,9 @@ def _wrapcall(*args, **kargs):
|
||||
try:
|
||||
if sys.version_info > (2, 7):
|
||||
return subprocess.check_output(*args, **kargs).decode().splitlines()
|
||||
if 'stdout' in kargs:
|
||||
raise ValueError('stdout argument not allowed, it will be overridden.')
|
||||
process = subprocess.Popen(
|
||||
stdout=subprocess.PIPE, *args, **kargs)
|
||||
if "stdout" in kargs:
|
||||
raise ValueError("stdout argument not allowed, it will be overridden.")
|
||||
process = subprocess.Popen(stdout=subprocess.PIPE, *args, **kargs)
|
||||
output, unused_err = process.communicate()
|
||||
retcode = process.poll()
|
||||
if retcode:
|
||||
@@ -43,37 +43,45 @@ def _wrapcall(*args, **kargs):
|
||||
|
||||
|
||||
class FilesCompleter(object):
|
||||
'File completer class, optionally takes a list of allowed extensions'
|
||||
"File completer class, optionally takes a list of allowed extensions"
|
||||
|
||||
def __init__(self, allowednames=(), directories=True):
|
||||
# Fix if someone passes in a string instead of a list
|
||||
if type(allowednames) is str:
|
||||
allowednames = [allowednames]
|
||||
|
||||
self.allowednames = [x.lstrip('*').lstrip('.') for x in allowednames]
|
||||
self.allowednames = [x.lstrip("*").lstrip(".") for x in allowednames]
|
||||
self.directories = directories
|
||||
|
||||
def __call__(self, prefix, **kwargs):
|
||||
completion = []
|
||||
if self.allowednames:
|
||||
if self.directories:
|
||||
files = _wrapcall(['bash', '-c',
|
||||
"compgen -A directory -- '{p}'".format(p=prefix)])
|
||||
completion += [f + '/' for f in files]
|
||||
files = _wrapcall(
|
||||
["bash", "-c", "compgen -A directory -- '{p}'".format(p=prefix)]
|
||||
)
|
||||
completion += [f + "/" for f in files]
|
||||
for x in self.allowednames:
|
||||
completion += _wrapcall(['bash', '-c',
|
||||
"compgen -A file -X '!*.{0}' -- '{p}'".format(x, p=prefix)])
|
||||
completion += _wrapcall(
|
||||
[
|
||||
"bash",
|
||||
"-c",
|
||||
"compgen -A file -X '!*.{0}' -- '{p}'".format(x, p=prefix),
|
||||
]
|
||||
)
|
||||
else:
|
||||
completion += _wrapcall(['bash', '-c',
|
||||
"compgen -A file -- '{p}'".format(p=prefix)])
|
||||
completion += _wrapcall(
|
||||
["bash", "-c", "compgen -A file -- '{p}'".format(p=prefix)]
|
||||
)
|
||||
|
||||
anticomp = _wrapcall(['bash', '-c',
|
||||
"compgen -A directory -- '{p}'".format(p=prefix)])
|
||||
anticomp = _wrapcall(
|
||||
["bash", "-c", "compgen -A directory -- '{p}'".format(p=prefix)]
|
||||
)
|
||||
|
||||
completion = list(set(completion) - set(anticomp))
|
||||
|
||||
if self.directories:
|
||||
completion += [f + '/' for f in anticomp]
|
||||
completion += [f + "/" for f in anticomp]
|
||||
return completion
|
||||
|
||||
|
||||
@@ -81,9 +89,10 @@ class TestArgComplete(object):
|
||||
@pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
|
||||
def test_compare_with_compgen(self):
|
||||
from _pytest._argcomplete import FastFilesCompleter
|
||||
|
||||
ffc = FastFilesCompleter()
|
||||
fc = FilesCompleter()
|
||||
for x in ['/', '/d', '/data', 'qqq', '']:
|
||||
for x in ["/", "/d", "/data", "qqq", ""]:
|
||||
assert equal_with_bash(x, ffc, fc, out=sys.stdout)
|
||||
|
||||
@pytest.mark.skipif("sys.platform in ('win32', 'darwin')")
|
||||
@@ -92,7 +101,8 @@ class TestArgComplete(object):
|
||||
ls /usr/<TAB>
|
||||
"""
|
||||
from _pytest._argcomplete import FastFilesCompleter
|
||||
|
||||
ffc = FastFilesCompleter()
|
||||
fc = FilesCompleter()
|
||||
for x in '/usr/'.split():
|
||||
for x in "/usr/".split():
|
||||
assert not equal_with_bash(x, ffc, fc, out=sys.stdout)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,11 @@ import pytest
|
||||
|
||||
import _pytest._code
|
||||
from _pytest.assertion import util
|
||||
from _pytest.assertion.rewrite import rewrite_asserts, PYTEST_TAG, AssertionRewritingHook
|
||||
from _pytest.assertion.rewrite import (
|
||||
rewrite_asserts,
|
||||
PYTEST_TAG,
|
||||
AssertionRewritingHook,
|
||||
)
|
||||
from _pytest.main import EXIT_NOTESTSCOLLECTED
|
||||
|
||||
ast = pytest.importorskip("ast")
|
||||
@@ -39,7 +43,7 @@ def rewrite(src):
|
||||
|
||||
def getmsg(f, extra_ns=None, must_pass=False):
|
||||
"""Rewrite the assertions in f, run it, and get the failure message."""
|
||||
src = '\n'.join(_pytest._code.Code(f).source().lines)
|
||||
src = "\n".join(_pytest._code.Code(f).source().lines)
|
||||
mod = rewrite(src)
|
||||
code = compile(mod, "<test>", "exec")
|
||||
ns = {}
|
||||
@@ -61,18 +65,33 @@ def getmsg(f, extra_ns=None, must_pass=False):
|
||||
pytest.fail("function didn't raise at all")
|
||||
|
||||
|
||||
class TestAssertionRewrite(object):
|
||||
def adjust_body_for_new_docstring_in_module_node(m):
|
||||
"""Module docstrings in 3.8 are part of Module node.
|
||||
This was briefly in 3.7 as well but got reverted in beta 5.
|
||||
|
||||
It's not in the body so we remove it so the following body items have
|
||||
the same indexes on all Python versions:
|
||||
|
||||
TODO:
|
||||
|
||||
We have a complicated sys.version_info if in here to ease testing on
|
||||
various Python 3.7 versions, but we should remove the 3.7 check after
|
||||
3.7 is released as stable to make this check more straightforward.
|
||||
"""
|
||||
if sys.version_info < (3, 8) and not (
|
||||
(3, 7) <= sys.version_info <= (3, 7, 0, "beta", 4)
|
||||
):
|
||||
assert len(m.body) > 1
|
||||
assert isinstance(m.body[0], ast.Expr)
|
||||
assert isinstance(m.body[0].value, ast.Str)
|
||||
del m.body[0]
|
||||
|
||||
|
||||
class TestAssertionRewrite(object):
|
||||
def test_place_initial_imports(self):
|
||||
s = """'Doc string'\nother = stuff"""
|
||||
m = rewrite(s)
|
||||
# Module docstrings in 3.7 are part of Module node, it's not in the body
|
||||
# so we remove it so the following body items have the same indexes on
|
||||
# all Python versions
|
||||
if sys.version_info < (3, 7):
|
||||
assert isinstance(m.body[0], ast.Expr)
|
||||
assert isinstance(m.body[0].value, ast.Str)
|
||||
del m.body[0]
|
||||
adjust_body_for_new_docstring_in_module_node(m)
|
||||
for imp in m.body[0:2]:
|
||||
assert isinstance(imp, ast.Import)
|
||||
assert imp.lineno == 2
|
||||
@@ -88,10 +107,7 @@ class TestAssertionRewrite(object):
|
||||
assert isinstance(m.body[3], ast.Expr)
|
||||
s = """'doc string'\nfrom __future__ import with_statement"""
|
||||
m = rewrite(s)
|
||||
if sys.version_info < (3, 7):
|
||||
assert isinstance(m.body[0], ast.Expr)
|
||||
assert isinstance(m.body[0].value, ast.Str)
|
||||
del m.body[0]
|
||||
adjust_body_for_new_docstring_in_module_node(m)
|
||||
assert isinstance(m.body[0], ast.ImportFrom)
|
||||
for imp in m.body[1:3]:
|
||||
assert isinstance(imp, ast.Import)
|
||||
@@ -99,10 +115,7 @@ class TestAssertionRewrite(object):
|
||||
assert imp.col_offset == 0
|
||||
s = """'doc string'\nfrom __future__ import with_statement\nother"""
|
||||
m = rewrite(s)
|
||||
if sys.version_info < (3, 7):
|
||||
assert isinstance(m.body[0], ast.Expr)
|
||||
assert isinstance(m.body[0].value, ast.Str)
|
||||
del m.body[0]
|
||||
adjust_body_for_new_docstring_in_module_node(m)
|
||||
assert isinstance(m.body[0], ast.ImportFrom)
|
||||
for imp in m.body[1:3]:
|
||||
assert isinstance(imp, ast.Import)
|
||||
@@ -120,13 +133,8 @@ class TestAssertionRewrite(object):
|
||||
def test_dont_rewrite(self):
|
||||
s = """'PYTEST_DONT_REWRITE'\nassert 14"""
|
||||
m = rewrite(s)
|
||||
if sys.version_info < (3, 7):
|
||||
assert len(m.body) == 2
|
||||
assert isinstance(m.body[0], ast.Expr)
|
||||
assert isinstance(m.body[0].value, ast.Str)
|
||||
del m.body[0]
|
||||
else:
|
||||
assert len(m.body) == 1
|
||||
adjust_body_for_new_docstring_in_module_node(m)
|
||||
assert len(m.body) == 1
|
||||
assert m.body[0].msg is None
|
||||
|
||||
def test_dont_rewrite_plugin(self, testdir):
|
||||
@@ -142,6 +150,7 @@ class TestAssertionRewrite(object):
|
||||
def test_name(self):
|
||||
def f():
|
||||
assert False
|
||||
|
||||
assert getmsg(f) == "assert False"
|
||||
|
||||
def f():
|
||||
@@ -171,68 +180,71 @@ class TestAssertionRewrite(object):
|
||||
def test_assert_already_has_message(self):
|
||||
def f():
|
||||
assert False, "something bad!"
|
||||
|
||||
assert getmsg(f) == "AssertionError: something bad!\nassert False"
|
||||
|
||||
def test_assertion_message(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_foo():
|
||||
assert 1 == 2, "The failure message"
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
assert result.ret == 1
|
||||
result.stdout.fnmatch_lines([
|
||||
"*AssertionError*The failure message*",
|
||||
"*assert 1 == 2*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
["*AssertionError*The failure message*", "*assert 1 == 2*"]
|
||||
)
|
||||
|
||||
def test_assertion_message_multiline(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_foo():
|
||||
assert 1 == 2, "A multiline\\nfailure message"
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
assert result.ret == 1
|
||||
result.stdout.fnmatch_lines([
|
||||
"*AssertionError*A multiline*",
|
||||
"*failure message*",
|
||||
"*assert 1 == 2*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
["*AssertionError*A multiline*", "*failure message*", "*assert 1 == 2*"]
|
||||
)
|
||||
|
||||
def test_assertion_message_tuple(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_foo():
|
||||
assert 1 == 2, (1, 2)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
assert result.ret == 1
|
||||
result.stdout.fnmatch_lines([
|
||||
"*AssertionError*%s*" % repr((1, 2)),
|
||||
"*assert 1 == 2*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
["*AssertionError*%s*" % repr((1, 2)), "*assert 1 == 2*"]
|
||||
)
|
||||
|
||||
def test_assertion_message_expr(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_foo():
|
||||
assert 1 == 2, 1 + 2
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
assert result.ret == 1
|
||||
result.stdout.fnmatch_lines([
|
||||
"*AssertionError*3*",
|
||||
"*assert 1 == 2*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*AssertionError*3*", "*assert 1 == 2*"])
|
||||
|
||||
def test_assertion_message_escape(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_foo():
|
||||
assert 1 == 2, 'To be escaped: %'
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
assert result.ret == 1
|
||||
result.stdout.fnmatch_lines([
|
||||
"*AssertionError: To be escaped: %",
|
||||
"*assert 1 == 2",
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
["*AssertionError: To be escaped: %", "*assert 1 == 2"]
|
||||
)
|
||||
|
||||
def test_boolop(self):
|
||||
def f():
|
||||
@@ -273,14 +285,20 @@ class TestAssertionRewrite(object):
|
||||
def f():
|
||||
assert x() and x()
|
||||
|
||||
assert getmsg(f, {"x": x}) == """assert (False)
|
||||
assert (
|
||||
getmsg(f, {"x": x})
|
||||
== """assert (False)
|
||||
+ where False = x()"""
|
||||
)
|
||||
|
||||
def f():
|
||||
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()"""
|
||||
)
|
||||
|
||||
def f():
|
||||
assert 1 in {} and 2 in {}
|
||||
@@ -354,6 +372,7 @@ class TestAssertionRewrite(object):
|
||||
|
||||
def f():
|
||||
assert not 5 % 4
|
||||
|
||||
assert getmsg(f) == "assert not (5 % 4)"
|
||||
|
||||
def test_boolop_percent(self):
|
||||
@@ -364,11 +383,13 @@ class TestAssertionRewrite(object):
|
||||
|
||||
def f():
|
||||
assert False or 4 % 2
|
||||
|
||||
assert getmsg(f) == "assert (False or (4 % 2))"
|
||||
|
||||
@pytest.mark.skipif("sys.version_info < (3,5)")
|
||||
def test_at_operator_issue1290(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
class Matrix(object):
|
||||
def __init__(self, num):
|
||||
self.num = num
|
||||
@@ -376,7 +397,8 @@ class TestAssertionRewrite(object):
|
||||
return self.num * other.num
|
||||
|
||||
def test_multmat_operator():
|
||||
assert Matrix(2) @ Matrix(3) == 6""")
|
||||
assert Matrix(2) @ Matrix(3) == 6"""
|
||||
)
|
||||
testdir.runpytest().assert_outcomes(passed=1)
|
||||
|
||||
def test_call(self):
|
||||
@@ -388,46 +410,67 @@ class TestAssertionRewrite(object):
|
||||
def f():
|
||||
assert g()
|
||||
|
||||
assert getmsg(f, ns) == """assert False
|
||||
assert (
|
||||
getmsg(f, ns)
|
||||
== """assert False
|
||||
+ where False = g()"""
|
||||
)
|
||||
|
||||
def f():
|
||||
assert g(1)
|
||||
|
||||
assert getmsg(f, ns) == """assert False
|
||||
assert (
|
||||
getmsg(f, ns)
|
||||
== """assert False
|
||||
+ where False = g(1)"""
|
||||
)
|
||||
|
||||
def f():
|
||||
assert g(1, 2)
|
||||
|
||||
assert getmsg(f, ns) == """assert False
|
||||
assert (
|
||||
getmsg(f, ns)
|
||||
== """assert False
|
||||
+ where False = g(1, 2)"""
|
||||
)
|
||||
|
||||
def f():
|
||||
assert g(1, g=42)
|
||||
|
||||
assert getmsg(f, ns) == """assert False
|
||||
assert (
|
||||
getmsg(f, ns)
|
||||
== """assert False
|
||||
+ where False = g(1, g=42)"""
|
||||
)
|
||||
|
||||
def f():
|
||||
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)"""
|
||||
)
|
||||
|
||||
def f():
|
||||
seq = [1, 2, 3]
|
||||
assert g(*seq)
|
||||
|
||||
assert getmsg(f, ns) == """assert False
|
||||
assert (
|
||||
getmsg(f, ns)
|
||||
== """assert False
|
||||
+ where False = g(*[1, 2, 3])"""
|
||||
)
|
||||
|
||||
def f():
|
||||
x = "a"
|
||||
assert g(**{x: 2})
|
||||
|
||||
assert getmsg(f, ns) == """assert False
|
||||
assert (
|
||||
getmsg(f, ns)
|
||||
== """assert False
|
||||
+ where False = g(**{'a': 2})"""
|
||||
)
|
||||
|
||||
def test_attribute(self):
|
||||
class X(object):
|
||||
@@ -438,18 +481,23 @@ class TestAssertionRewrite(object):
|
||||
def f():
|
||||
assert not x.g # noqa
|
||||
|
||||
assert getmsg(f, ns) == """assert not 3
|
||||
assert (
|
||||
getmsg(f, ns)
|
||||
== """assert not 3
|
||||
+ where 3 = x.g"""
|
||||
)
|
||||
|
||||
def f():
|
||||
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"""
|
||||
)
|
||||
|
||||
def test_comparisons(self):
|
||||
|
||||
def f():
|
||||
a, b = range(2)
|
||||
assert b < a
|
||||
@@ -482,13 +530,14 @@ class TestAssertionRewrite(object):
|
||||
getmsg(f, must_pass=True)
|
||||
|
||||
def test_len(self):
|
||||
|
||||
def f():
|
||||
values = list(range(10))
|
||||
assert len(values) == 11
|
||||
|
||||
assert getmsg(f).startswith("""assert 10 == 11
|
||||
+ where 10 = len([""")
|
||||
assert getmsg(f).startswith(
|
||||
"""assert 10 == 11
|
||||
+ where 10 = len(["""
|
||||
)
|
||||
|
||||
def test_custom_reprcompare(self, monkeypatch):
|
||||
def my_reprcompare(op, left, right):
|
||||
@@ -514,7 +563,6 @@ class TestAssertionRewrite(object):
|
||||
def test_assert_raising_nonzero_in_comparison(self):
|
||||
def f():
|
||||
class A(object):
|
||||
|
||||
def __nonzero__(self):
|
||||
raise ValueError(42)
|
||||
|
||||
@@ -552,21 +600,24 @@ class TestAssertionRewrite(object):
|
||||
|
||||
|
||||
class TestRewriteOnImport(object):
|
||||
|
||||
def test_pycache_is_a_file(self, testdir):
|
||||
testdir.tmpdir.join("__pycache__").write("Hello")
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_rewritten():
|
||||
assert "@py_builtins" in globals()""")
|
||||
assert "@py_builtins" in globals()"""
|
||||
)
|
||||
assert testdir.runpytest().ret == 0
|
||||
|
||||
def test_pycache_is_readonly(self, testdir):
|
||||
cache = testdir.tmpdir.mkdir("__pycache__")
|
||||
old_mode = cache.stat().mode
|
||||
cache.chmod(old_mode ^ stat.S_IWRITE)
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_rewritten():
|
||||
assert "@py_builtins" in globals()""")
|
||||
assert "@py_builtins" in globals()"""
|
||||
)
|
||||
try:
|
||||
assert testdir.runpytest().ret == 0
|
||||
finally:
|
||||
@@ -582,19 +633,26 @@ class TestRewriteOnImport(object):
|
||||
finally:
|
||||
f.close()
|
||||
z.chmod(256)
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import sys
|
||||
sys.path.append(%r)
|
||||
import test_gum.test_lizard""" % (z_fn,))
|
||||
import test_gum.test_lizard"""
|
||||
% (z_fn,)
|
||||
)
|
||||
assert testdir.runpytest().ret == EXIT_NOTESTSCOLLECTED
|
||||
|
||||
def test_readonly(self, testdir):
|
||||
sub = testdir.mkdir("testing")
|
||||
sub.join("test_readonly.py").write(
|
||||
py.builtin._totext("""
|
||||
py.builtin._totext(
|
||||
"""
|
||||
def test_rewritten():
|
||||
assert "@py_builtins" in globals()
|
||||
""").encode("utf-8"), "wb")
|
||||
"""
|
||||
).encode("utf-8"),
|
||||
"wb",
|
||||
)
|
||||
old_mode = sub.stat().mode
|
||||
sub.chmod(320)
|
||||
try:
|
||||
@@ -603,27 +661,33 @@ def test_rewritten():
|
||||
sub.chmod(old_mode)
|
||||
|
||||
def test_dont_write_bytecode(self, testdir, monkeypatch):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import os
|
||||
def test_no_bytecode():
|
||||
assert "__pycache__" in __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")
|
||||
assert testdir.runpytest_subprocess().ret == 0
|
||||
|
||||
def test_orphaned_pyc_file(self, testdir):
|
||||
if sys.version_info < (3, 0) and hasattr(sys, 'pypy_version_info'):
|
||||
if sys.version_info < (3, 0) and hasattr(sys, "pypy_version_info"):
|
||||
pytest.skip("pypy2 doesn't run orphaned pyc files")
|
||||
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import orphan
|
||||
def test_it():
|
||||
assert orphan.value == 17
|
||||
""")
|
||||
testdir.makepyfile(orphan="""
|
||||
"""
|
||||
)
|
||||
testdir.makepyfile(
|
||||
orphan="""
|
||||
value = 17
|
||||
""")
|
||||
"""
|
||||
)
|
||||
py_compile.compile("orphan.py")
|
||||
os.remove("orphan.py")
|
||||
|
||||
@@ -639,14 +703,16 @@ def test_rewritten():
|
||||
|
||||
@pytest.mark.skipif('"__pypy__" in sys.modules')
|
||||
def test_pyc_vs_pyo(self, testdir, monkeypatch):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def test_optimized():
|
||||
"hello"
|
||||
assert test_optimized.__doc__ is None"""
|
||||
)
|
||||
p = py.path.local.make_numbered_dir(prefix="runpytest-", keep=None,
|
||||
rootdir=testdir.tmpdir)
|
||||
)
|
||||
p = py.path.local.make_numbered_dir(
|
||||
prefix="runpytest-", keep=None, rootdir=testdir.tmpdir
|
||||
)
|
||||
tmp = "--basetemp=%s" % p
|
||||
monkeypatch.setenv("PYTHONOPTIMIZE", "2")
|
||||
monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", raising=False)
|
||||
@@ -662,9 +728,11 @@ def test_rewritten():
|
||||
pkg = testdir.tmpdir.join("pkg")
|
||||
pkg.mkdir()
|
||||
pkg.join("__init__.py").ensure()
|
||||
pkg.join("test_blah.py").write("""
|
||||
pkg.join("test_blah.py").write(
|
||||
"""
|
||||
def test_rewritten():
|
||||
assert "@py_builtins" in globals()""")
|
||||
assert "@py_builtins" in globals()"""
|
||||
)
|
||||
assert testdir.runpytest().ret == 0
|
||||
|
||||
def test_translate_newlines(self, testdir):
|
||||
@@ -673,11 +741,13 @@ def test_rewritten():
|
||||
testdir.tmpdir.join("test_newlines.py").write(b, "wb")
|
||||
assert testdir.runpytest().ret == 0
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 4),
|
||||
reason='packages without __init__.py not supported on python 2')
|
||||
@pytest.mark.skipif(
|
||||
sys.version_info < (3, 4),
|
||||
reason="packages without __init__.py not supported on python 2",
|
||||
)
|
||||
def test_package_without__init__py(self, testdir):
|
||||
pkg = testdir.mkdir('a_package_without_init_py')
|
||||
pkg.join('module.py').ensure()
|
||||
pkg = testdir.mkdir("a_package_without_init_py")
|
||||
pkg.join("module.py").ensure()
|
||||
testdir.makepyfile("import a_package_without_init_py.module")
|
||||
assert testdir.runpytest().ret == EXIT_NOTESTSCOLLECTED
|
||||
|
||||
@@ -688,18 +758,22 @@ def test_rewritten():
|
||||
def mywarn(code, msg):
|
||||
warnings.append((code, msg))
|
||||
|
||||
monkeypatch.setattr(hook.config, 'warn', mywarn)
|
||||
hook.mark_rewrite('_pytest')
|
||||
assert '_pytest' in warnings[0][1]
|
||||
monkeypatch.setattr(hook.config, "warn", mywarn)
|
||||
hook.mark_rewrite("_pytest")
|
||||
assert "_pytest" in warnings[0][1]
|
||||
|
||||
def test_rewrite_module_imported_from_conftest(self, testdir):
|
||||
testdir.makeconftest('''
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import test_rewrite_module_imported
|
||||
''')
|
||||
testdir.makepyfile(test_rewrite_module_imported='''
|
||||
"""
|
||||
)
|
||||
testdir.makepyfile(
|
||||
test_rewrite_module_imported="""
|
||||
def test_rewritten():
|
||||
assert "@py_builtins" in globals()
|
||||
''')
|
||||
"""
|
||||
)
|
||||
assert testdir.runpytest_subprocess().ret == 0
|
||||
|
||||
def test_remember_rewritten_modules(self, pytestconfig, testdir, monkeypatch):
|
||||
@@ -708,46 +782,50 @@ def test_rewritten():
|
||||
doesn't give false positives (#2005).
|
||||
"""
|
||||
monkeypatch.syspath_prepend(testdir.tmpdir)
|
||||
testdir.makepyfile(test_remember_rewritten_modules='')
|
||||
testdir.makepyfile(test_remember_rewritten_modules="")
|
||||
warnings = []
|
||||
hook = AssertionRewritingHook(pytestconfig)
|
||||
monkeypatch.setattr(hook.config, 'warn', lambda code, msg: warnings.append(msg))
|
||||
hook.find_module('test_remember_rewritten_modules')
|
||||
hook.load_module('test_remember_rewritten_modules')
|
||||
hook.mark_rewrite('test_remember_rewritten_modules')
|
||||
hook.mark_rewrite('test_remember_rewritten_modules')
|
||||
monkeypatch.setattr(hook.config, "warn", lambda code, msg: warnings.append(msg))
|
||||
hook.find_module("test_remember_rewritten_modules")
|
||||
hook.load_module("test_remember_rewritten_modules")
|
||||
hook.mark_rewrite("test_remember_rewritten_modules")
|
||||
hook.mark_rewrite("test_remember_rewritten_modules")
|
||||
assert warnings == []
|
||||
|
||||
def test_rewrite_warning_using_pytest_plugins(self, testdir):
|
||||
testdir.makepyfile(**{
|
||||
'conftest.py': "pytest_plugins = ['core', 'gui', 'sci']",
|
||||
'core.py': "",
|
||||
'gui.py': "pytest_plugins = ['core', 'sci']",
|
||||
'sci.py': "pytest_plugins = ['core']",
|
||||
'test_rewrite_warning_pytest_plugins.py': "def test(): pass",
|
||||
})
|
||||
testdir.makepyfile(
|
||||
**{
|
||||
"conftest.py": "pytest_plugins = ['core', 'gui', 'sci']",
|
||||
"core.py": "",
|
||||
"gui.py": "pytest_plugins = ['core', 'sci']",
|
||||
"sci.py": "pytest_plugins = ['core']",
|
||||
"test_rewrite_warning_pytest_plugins.py": "def test(): pass",
|
||||
}
|
||||
)
|
||||
testdir.chdir()
|
||||
result = testdir.runpytest_subprocess()
|
||||
result.stdout.fnmatch_lines(['*= 1 passed in *=*'])
|
||||
assert 'pytest-warning summary' not in result.stdout.str()
|
||||
result.stdout.fnmatch_lines(["*= 1 passed in *=*"])
|
||||
assert "pytest-warning summary" not in result.stdout.str()
|
||||
|
||||
def test_rewrite_warning_using_pytest_plugins_env_var(self, testdir, monkeypatch):
|
||||
monkeypatch.setenv('PYTEST_PLUGINS', 'plugin')
|
||||
testdir.makepyfile(**{
|
||||
'plugin.py': "",
|
||||
'test_rewrite_warning_using_pytest_plugins_env_var.py': """
|
||||
monkeypatch.setenv("PYTEST_PLUGINS", "plugin")
|
||||
testdir.makepyfile(
|
||||
**{
|
||||
"plugin.py": "",
|
||||
"test_rewrite_warning_using_pytest_plugins_env_var.py": """
|
||||
import plugin
|
||||
pytest_plugins = ['plugin']
|
||||
def test():
|
||||
pass
|
||||
""",
|
||||
})
|
||||
}
|
||||
)
|
||||
testdir.chdir()
|
||||
result = testdir.runpytest_subprocess()
|
||||
result.stdout.fnmatch_lines(['*= 1 passed in *=*'])
|
||||
assert 'pytest-warning summary' not in result.stdout.str()
|
||||
result.stdout.fnmatch_lines(["*= 1 passed in *=*"])
|
||||
assert "pytest-warning summary" not in result.stdout.str()
|
||||
|
||||
@pytest.mark.skipif(sys.version_info[0] > 2, reason='python 2 only')
|
||||
@pytest.mark.skipif(sys.version_info[0] > 2, reason="python 2 only")
|
||||
def test_rewrite_future_imports(self, testdir):
|
||||
"""Test that rewritten modules don't inherit the __future__ flags
|
||||
from the assertrewrite module.
|
||||
@@ -757,28 +835,31 @@ def test_rewritten():
|
||||
|
||||
The test below will fail if __future__.division is enabled
|
||||
"""
|
||||
testdir.makepyfile('''
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test():
|
||||
x = 1 / 2
|
||||
assert type(x) is int
|
||||
''')
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
assert result.ret == 0
|
||||
|
||||
|
||||
class TestAssertionRewriteHookDetails(object):
|
||||
def test_loader_is_package_false_for_module(self, testdir):
|
||||
testdir.makepyfile(test_fun="""
|
||||
testdir.makepyfile(
|
||||
test_fun="""
|
||||
def test_loader():
|
||||
assert not __loader__.is_package(__name__)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
"* 1 passed*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(["* 1 passed*"])
|
||||
|
||||
def test_loader_is_package_true_for_package(self, testdir):
|
||||
testdir.makepyfile(test_fun="""
|
||||
testdir.makepyfile(
|
||||
test_fun="""
|
||||
def test_loader():
|
||||
assert not __loader__.is_package(__name__)
|
||||
|
||||
@@ -787,12 +868,11 @@ class TestAssertionRewriteHookDetails(object):
|
||||
|
||||
def test_missing():
|
||||
assert not __loader__.is_package('pytest_not_there')
|
||||
""")
|
||||
testdir.mkpydir('fun')
|
||||
"""
|
||||
)
|
||||
testdir.mkpydir("fun")
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
'* 3 passed*',
|
||||
])
|
||||
result.stdout.fnmatch_lines(["* 3 passed*"])
|
||||
|
||||
@pytest.mark.skipif("sys.version_info[0] >= 3")
|
||||
@pytest.mark.xfail("hasattr(sys, 'pypy_translation_info')")
|
||||
@@ -805,35 +885,43 @@ class TestAssertionRewriteHookDetails(object):
|
||||
|
||||
@pytest.mark.skipif("sys.version_info[0] >= 3")
|
||||
def test_detect_coding_cookie(self, testdir):
|
||||
testdir.makepyfile(test_cookie="""
|
||||
testdir.makepyfile(
|
||||
test_cookie="""
|
||||
# -*- coding: utf-8 -*-
|
||||
u"St\xc3\xa4d"
|
||||
def test_rewritten():
|
||||
assert "@py_builtins" in globals()""")
|
||||
assert "@py_builtins" in globals()"""
|
||||
)
|
||||
assert testdir.runpytest().ret == 0
|
||||
|
||||
@pytest.mark.skipif("sys.version_info[0] >= 3")
|
||||
def test_detect_coding_cookie_second_line(self, testdir):
|
||||
testdir.makepyfile(test_cookie="""
|
||||
testdir.makepyfile(
|
||||
test_cookie="""
|
||||
# -*- coding: utf-8 -*-
|
||||
u"St\xc3\xa4d"
|
||||
def test_rewritten():
|
||||
assert "@py_builtins" in globals()""")
|
||||
assert "@py_builtins" in globals()"""
|
||||
)
|
||||
assert testdir.runpytest().ret == 0
|
||||
|
||||
@pytest.mark.skipif("sys.version_info[0] >= 3")
|
||||
def test_detect_coding_cookie_crlf(self, testdir):
|
||||
testdir.makepyfile(test_cookie="""
|
||||
testdir.makepyfile(
|
||||
test_cookie="""
|
||||
# -*- coding: utf-8 -*-
|
||||
u"St\xc3\xa4d"
|
||||
def test_rewritten():
|
||||
assert "@py_builtins" in globals()""")
|
||||
assert "@py_builtins" in globals()"""
|
||||
)
|
||||
assert testdir.runpytest().ret == 0
|
||||
|
||||
def test_sys_meta_path_munged(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_meta_path():
|
||||
import sys; sys.meta_path = []""")
|
||||
import sys; sys.meta_path = []"""
|
||||
)
|
||||
assert testdir.runpytest().ret == 0
|
||||
|
||||
def test_write_pyc(self, testdir, tmpdir, monkeypatch):
|
||||
@@ -841,6 +929,7 @@ class TestAssertionRewriteHookDetails(object):
|
||||
from _pytest.assertion import AssertionState
|
||||
import atomicwrites
|
||||
from contextlib import contextmanager
|
||||
|
||||
config = testdir.parseconfig([])
|
||||
state = AssertionState(config, "rewrite")
|
||||
source_path = tmpdir.ensure("source.py")
|
||||
@@ -848,7 +937,7 @@ class TestAssertionRewriteHookDetails(object):
|
||||
assert _write_pyc(state, [1], source_path.stat(), pycpath)
|
||||
|
||||
@contextmanager
|
||||
def atomic_write_failed(fn, mode='r', overwrite=False):
|
||||
def atomic_write_failed(fn, mode="r", overwrite=False):
|
||||
e = IOError()
|
||||
e.errno = 10
|
||||
raise e
|
||||
@@ -866,9 +955,9 @@ class TestAssertionRewriteHookDetails(object):
|
||||
"""
|
||||
pytest.importorskip("pkg_resources")
|
||||
|
||||
testdir.mkpydir('testpkg')
|
||||
testdir.mkpydir("testpkg")
|
||||
contents = {
|
||||
'testpkg/test_pkg': """
|
||||
"testpkg/test_pkg": """
|
||||
import pkg_resources
|
||||
|
||||
import pytest
|
||||
@@ -879,10 +968,10 @@ class TestAssertionRewriteHookDetails(object):
|
||||
res = pkg_resources.resource_string(__name__, 'resource.txt')
|
||||
res = res.decode('ascii')
|
||||
assert res == 'Load me please.'
|
||||
""",
|
||||
"""
|
||||
}
|
||||
testdir.makepyfile(**contents)
|
||||
testdir.maketxtfile(**{'testpkg/resource': "Load me please."})
|
||||
testdir.maketxtfile(**{"testpkg/resource": "Load me please."})
|
||||
|
||||
result = testdir.runpytest_subprocess()
|
||||
result.assert_outcomes(passed=1)
|
||||
@@ -896,28 +985,33 @@ class TestAssertionRewriteHookDetails(object):
|
||||
import py_compile
|
||||
from _pytest.assertion.rewrite import _read_pyc
|
||||
|
||||
source = tmpdir.join('source.py')
|
||||
pyc = source + 'c'
|
||||
source = tmpdir.join("source.py")
|
||||
pyc = source + "c"
|
||||
|
||||
source.write('def test(): pass')
|
||||
source.write("def test(): pass")
|
||||
py_compile.compile(str(source), str(pyc))
|
||||
|
||||
contents = pyc.read(mode='rb')
|
||||
contents = pyc.read(mode="rb")
|
||||
strip_bytes = 20 # header is around 8 bytes, strip a little more
|
||||
assert len(contents) > strip_bytes
|
||||
pyc.write(contents[:strip_bytes], mode='wb')
|
||||
pyc.write(contents[:strip_bytes], mode="wb")
|
||||
|
||||
assert _read_pyc(source, str(pyc)) is None # no error
|
||||
|
||||
def test_reload_is_same(self, testdir):
|
||||
# A file that will be picked up during collecting.
|
||||
testdir.tmpdir.join("file.py").ensure()
|
||||
testdir.tmpdir.join("pytest.ini").write(textwrap.dedent("""
|
||||
testdir.tmpdir.join("pytest.ini").write(
|
||||
textwrap.dedent(
|
||||
"""
|
||||
[pytest]
|
||||
python_files = *.py
|
||||
"""))
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
testdir.makepyfile(test_fun="""
|
||||
testdir.makepyfile(
|
||||
test_fun="""
|
||||
import sys
|
||||
try:
|
||||
from imp import reload
|
||||
@@ -927,30 +1021,34 @@ class TestAssertionRewriteHookDetails(object):
|
||||
def test_loader():
|
||||
import file
|
||||
assert sys.modules["file"] is reload(file)
|
||||
""")
|
||||
result = testdir.runpytest('-s')
|
||||
result.stdout.fnmatch_lines([
|
||||
"* 1 passed*",
|
||||
])
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("-s")
|
||||
result.stdout.fnmatch_lines(["* 1 passed*"])
|
||||
|
||||
def test_get_data_support(self, testdir):
|
||||
"""Implement optional PEP302 api (#808).
|
||||
"""
|
||||
path = testdir.mkpydir("foo")
|
||||
path.join("test_foo.py").write(_pytest._code.Source("""
|
||||
path.join("test_foo.py").write(
|
||||
_pytest._code.Source(
|
||||
"""
|
||||
class Test(object):
|
||||
def test_foo(self):
|
||||
import pkgutil
|
||||
data = pkgutil.get_data('foo.test_foo', 'data.txt')
|
||||
assert data == b'Hey'
|
||||
"""))
|
||||
path.join('data.txt').write('Hey')
|
||||
"""
|
||||
)
|
||||
)
|
||||
path.join("data.txt").write("Hey")
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines('*1 passed*')
|
||||
result.stdout.fnmatch_lines("*1 passed*")
|
||||
|
||||
|
||||
def test_issue731(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
class LongReprWithBraces(object):
|
||||
def __repr__(self):
|
||||
return 'LongReprWithBraces({' + ('a' * 80) + '}' + ('a' * 120) + ')'
|
||||
@@ -961,47 +1059,60 @@ def test_issue731(testdir):
|
||||
def test_long_repr():
|
||||
obj = LongReprWithBraces()
|
||||
assert obj.some_method()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
assert 'unbalanced braces' not in result.stdout.str()
|
||||
assert "unbalanced braces" not in result.stdout.str()
|
||||
|
||||
|
||||
class TestIssue925(object):
|
||||
def test_simple_case(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_ternary_display():
|
||||
assert (False == False) == False
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines('*E*assert (False == False) == False')
|
||||
result.stdout.fnmatch_lines("*E*assert (False == False) == False")
|
||||
|
||||
def test_long_case(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_ternary_display():
|
||||
assert False == (False == True) == True
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines('*E*assert (False == True) == True')
|
||||
result.stdout.fnmatch_lines("*E*assert (False == True) == True")
|
||||
|
||||
def test_many_brackets(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_ternary_display():
|
||||
assert True == ((False == True) == True)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines('*E*assert True == ((False == True) == True)')
|
||||
result.stdout.fnmatch_lines("*E*assert True == ((False == True) == True)")
|
||||
|
||||
|
||||
class TestIssue2121():
|
||||
class TestIssue2121:
|
||||
def test_simple(self, testdir):
|
||||
testdir.tmpdir.join("tests/file.py").ensure().write("""
|
||||
testdir.tmpdir.join("tests/file.py").ensure().write(
|
||||
"""
|
||||
def test_simple_failure():
|
||||
assert 1 + 1 == 3
|
||||
""")
|
||||
testdir.tmpdir.join("pytest.ini").write(textwrap.dedent("""
|
||||
"""
|
||||
)
|
||||
testdir.tmpdir.join("pytest.ini").write(
|
||||
textwrap.dedent(
|
||||
"""
|
||||
[pytest]
|
||||
python_files = tests/**.py
|
||||
"""))
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines('*E*assert (1 + 1) == 3')
|
||||
result.stdout.fnmatch_lines("*E*assert (1 + 1) == 3")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -10,14 +10,17 @@ from _pytest.main import Session, EXIT_NOTESTSCOLLECTED, _in_venv
|
||||
class TestCollector(object):
|
||||
def test_collect_versus_item(self):
|
||||
from pytest import Collector, Item
|
||||
|
||||
assert not issubclass(Collector, Item)
|
||||
assert not issubclass(Item, Collector)
|
||||
|
||||
def test_compat_attributes(self, testdir, recwarn):
|
||||
modcol = testdir.getmodulecol("""
|
||||
modcol = testdir.getmodulecol(
|
||||
"""
|
||||
def test_pass(): pass
|
||||
def test_fail(): assert 0
|
||||
""")
|
||||
"""
|
||||
)
|
||||
recwarn.clear()
|
||||
assert modcol.Module == pytest.Module
|
||||
assert modcol.Class == pytest.Class
|
||||
@@ -26,10 +29,12 @@ class TestCollector(object):
|
||||
assert modcol.Function == pytest.Function
|
||||
|
||||
def test_check_equality(self, testdir):
|
||||
modcol = testdir.getmodulecol("""
|
||||
modcol = testdir.getmodulecol(
|
||||
"""
|
||||
def test_pass(): pass
|
||||
def test_fail(): assert 0
|
||||
""")
|
||||
"""
|
||||
)
|
||||
fn1 = testdir.collect_by_name(modcol, "test_pass")
|
||||
assert isinstance(fn1, pytest.Function)
|
||||
fn2 = testdir.collect_by_name(modcol, "test_pass")
|
||||
@@ -38,7 +43,7 @@ class TestCollector(object):
|
||||
assert fn1 == fn2
|
||||
assert fn1 != modcol
|
||||
if sys.version_info < (3, 0):
|
||||
assert cmp(fn1, fn2) == 0
|
||||
assert cmp(fn1, fn2) == 0 # NOQA
|
||||
assert hash(fn1) == hash(fn2)
|
||||
|
||||
fn3 = testdir.collect_by_name(modcol, "test_fail")
|
||||
@@ -54,14 +59,15 @@ class TestCollector(object):
|
||||
assert modcol != fn
|
||||
|
||||
def test_getparent(self, testdir):
|
||||
modcol = testdir.getmodulecol("""
|
||||
modcol = testdir.getmodulecol(
|
||||
"""
|
||||
class TestClass(object):
|
||||
def test_foo():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
cls = testdir.collect_by_name(modcol, "TestClass")
|
||||
fn = testdir.collect_by_name(
|
||||
testdir.collect_by_name(cls, "()"), "test_foo")
|
||||
fn = testdir.collect_by_name(testdir.collect_by_name(cls, "()"), "test_foo")
|
||||
|
||||
parent = fn.getparent(pytest.Module)
|
||||
assert parent is modcol
|
||||
@@ -74,14 +80,16 @@ class TestCollector(object):
|
||||
|
||||
def test_getcustomfile_roundtrip(self, testdir):
|
||||
hello = testdir.makefile(".xxx", hello="world")
|
||||
testdir.makepyfile(conftest="""
|
||||
testdir.makepyfile(
|
||||
conftest="""
|
||||
import pytest
|
||||
class CustomFile(pytest.File):
|
||||
pass
|
||||
def pytest_collect_file(path, parent):
|
||||
if path.ext == ".xxx":
|
||||
return CustomFile(path, parent=parent)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
node = testdir.getpathnode(hello)
|
||||
assert isinstance(node, pytest.File)
|
||||
assert node.name == "hello.xxx"
|
||||
@@ -91,32 +99,31 @@ class TestCollector(object):
|
||||
|
||||
def test_can_skip_class_with_test_attr(self, testdir):
|
||||
"""Assure test class is skipped when using `__test__=False` (See #2007)."""
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
class TestFoo(object):
|
||||
__test__ = False
|
||||
def __init__(self):
|
||||
pass
|
||||
def test_foo():
|
||||
assert True
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
'collected 0 items',
|
||||
'*no tests ran in*',
|
||||
])
|
||||
result.stdout.fnmatch_lines(["collected 0 items", "*no tests ran in*"])
|
||||
|
||||
|
||||
class TestCollectFS(object):
|
||||
def test_ignored_certain_directories(self, testdir):
|
||||
tmpdir = testdir.tmpdir
|
||||
tmpdir.ensure("build", 'test_notfound.py')
|
||||
tmpdir.ensure("dist", 'test_notfound.py')
|
||||
tmpdir.ensure("_darcs", 'test_notfound.py')
|
||||
tmpdir.ensure("CVS", 'test_notfound.py')
|
||||
tmpdir.ensure("{arch}", 'test_notfound.py')
|
||||
tmpdir.ensure(".whatever", 'test_notfound.py')
|
||||
tmpdir.ensure(".bzr", 'test_notfound.py')
|
||||
tmpdir.ensure("normal", 'test_found.py')
|
||||
tmpdir.ensure("build", "test_notfound.py")
|
||||
tmpdir.ensure("dist", "test_notfound.py")
|
||||
tmpdir.ensure("_darcs", "test_notfound.py")
|
||||
tmpdir.ensure("CVS", "test_notfound.py")
|
||||
tmpdir.ensure("{arch}", "test_notfound.py")
|
||||
tmpdir.ensure(".whatever", "test_notfound.py")
|
||||
tmpdir.ensure(".bzr", "test_notfound.py")
|
||||
tmpdir.ensure("normal", "test_found.py")
|
||||
for x in tmpdir.visit("test_*.py"):
|
||||
x.write("def test_hello(): pass")
|
||||
|
||||
@@ -125,9 +132,17 @@ class TestCollectFS(object):
|
||||
assert "test_notfound" not in s
|
||||
assert "test_found" in s
|
||||
|
||||
@pytest.mark.parametrize('fname',
|
||||
("activate", "activate.csh", "activate.fish",
|
||||
"Activate", "Activate.bat", "Activate.ps1"))
|
||||
@pytest.mark.parametrize(
|
||||
"fname",
|
||||
(
|
||||
"activate",
|
||||
"activate.csh",
|
||||
"activate.fish",
|
||||
"Activate",
|
||||
"Activate.bat",
|
||||
"Activate.ps1",
|
||||
),
|
||||
)
|
||||
def test_ignored_virtualenvs(self, testdir, fname):
|
||||
bindir = "Scripts" if sys.platform.startswith("win") else "bin"
|
||||
testdir.tmpdir.ensure("virtual", bindir, fname)
|
||||
@@ -144,9 +159,17 @@ class TestCollectFS(object):
|
||||
result = testdir.runpytest("virtual")
|
||||
assert "test_invenv" in result.stdout.str()
|
||||
|
||||
@pytest.mark.parametrize('fname',
|
||||
("activate", "activate.csh", "activate.fish",
|
||||
"Activate", "Activate.bat", "Activate.ps1"))
|
||||
@pytest.mark.parametrize(
|
||||
"fname",
|
||||
(
|
||||
"activate",
|
||||
"activate.csh",
|
||||
"activate.fish",
|
||||
"Activate",
|
||||
"Activate.bat",
|
||||
"Activate.ps1",
|
||||
),
|
||||
)
|
||||
def test_ignored_virtualenvs_norecursedirs_precedence(self, testdir, fname):
|
||||
bindir = "Scripts" if sys.platform.startswith("win") else "bin"
|
||||
# norecursedirs takes priority
|
||||
@@ -159,24 +182,34 @@ class TestCollectFS(object):
|
||||
result = testdir.runpytest("--collect-in-virtualenv", ".virtual")
|
||||
assert "test_invenv" in result.stdout.str()
|
||||
|
||||
@pytest.mark.parametrize('fname',
|
||||
("activate", "activate.csh", "activate.fish",
|
||||
"Activate", "Activate.bat", "Activate.ps1"))
|
||||
@pytest.mark.parametrize(
|
||||
"fname",
|
||||
(
|
||||
"activate",
|
||||
"activate.csh",
|
||||
"activate.fish",
|
||||
"Activate",
|
||||
"Activate.bat",
|
||||
"Activate.ps1",
|
||||
),
|
||||
)
|
||||
def test__in_venv(self, testdir, fname):
|
||||
"""Directly test the virtual env detection function"""
|
||||
bindir = "Scripts" if sys.platform.startswith("win") else "bin"
|
||||
# no bin/activate, not a virtualenv
|
||||
base_path = testdir.tmpdir.mkdir('venv')
|
||||
base_path = testdir.tmpdir.mkdir("venv")
|
||||
assert _in_venv(base_path) is False
|
||||
# with bin/activate, totally a virtualenv
|
||||
base_path.ensure(bindir, fname)
|
||||
assert _in_venv(base_path) is True
|
||||
|
||||
def test_custom_norecursedirs(self, testdir):
|
||||
testdir.makeini("""
|
||||
testdir.makeini(
|
||||
"""
|
||||
[pytest]
|
||||
norecursedirs = mydir xyz*
|
||||
""")
|
||||
"""
|
||||
)
|
||||
tmpdir = testdir.tmpdir
|
||||
tmpdir.ensure("mydir", "test_hello.py").write("def test_1(): pass")
|
||||
tmpdir.ensure("xyz123", "test_2.py").write("def test_2(): 0/0")
|
||||
@@ -187,10 +220,12 @@ class TestCollectFS(object):
|
||||
rec.assertoutcome(failed=1)
|
||||
|
||||
def test_testpaths_ini(self, testdir, monkeypatch):
|
||||
testdir.makeini("""
|
||||
testdir.makeini(
|
||||
"""
|
||||
[pytest]
|
||||
testpaths = gui uts
|
||||
""")
|
||||
"""
|
||||
)
|
||||
tmpdir = testdir.tmpdir
|
||||
tmpdir.ensure("env", "test_1.py").write("def test_env(): pass")
|
||||
tmpdir.ensure("gui", "test_2.py").write("def test_gui(): pass")
|
||||
@@ -198,21 +233,21 @@ class TestCollectFS(object):
|
||||
|
||||
# executing from rootdir only tests from `testpaths` directories
|
||||
# are collected
|
||||
items, reprec = testdir.inline_genitems('-v')
|
||||
assert [x.name for x in items] == ['test_gui', 'test_uts']
|
||||
items, reprec = testdir.inline_genitems("-v")
|
||||
assert [x.name for x in items] == ["test_gui", "test_uts"]
|
||||
|
||||
# check that explicitly passing directories in the command-line
|
||||
# collects the tests
|
||||
for dirname in ('env', 'gui', 'uts'):
|
||||
for dirname in ("env", "gui", "uts"):
|
||||
items, reprec = testdir.inline_genitems(tmpdir.join(dirname))
|
||||
assert [x.name for x in items] == ['test_%s' % dirname]
|
||||
assert [x.name for x in items] == ["test_%s" % dirname]
|
||||
|
||||
# changing cwd to each subdirectory and running pytest without
|
||||
# arguments collects the tests in that directory normally
|
||||
for dirname in ('env', 'gui', 'uts'):
|
||||
for dirname in ("env", "gui", "uts"):
|
||||
monkeypatch.chdir(testdir.tmpdir.join(dirname))
|
||||
items, reprec = testdir.inline_genitems()
|
||||
assert [x.name for x in items] == ['test_%s' % dirname]
|
||||
assert [x.name for x in items] == ["test_%s" % dirname]
|
||||
|
||||
|
||||
class TestCollectPluginHookRelay(object):
|
||||
@@ -228,7 +263,7 @@ class TestCollectPluginHookRelay(object):
|
||||
testdir.makefile(".abc", "xyz")
|
||||
pytest.main([testdir.tmpdir], plugins=[Plugin()])
|
||||
assert len(wascalled) == 1
|
||||
assert wascalled[0].ext == '.abc'
|
||||
assert wascalled[0].ext == ".abc"
|
||||
|
||||
def test_pytest_collect_directory(self, testdir):
|
||||
wascalled = []
|
||||
@@ -245,12 +280,14 @@ class TestCollectPluginHookRelay(object):
|
||||
|
||||
|
||||
class TestPrunetraceback(object):
|
||||
|
||||
def test_custom_repr_failure(self, testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import not_exists
|
||||
""")
|
||||
testdir.makeconftest("""
|
||||
"""
|
||||
)
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import pytest
|
||||
def pytest_collect_file(path, parent):
|
||||
return MyFile(path, parent)
|
||||
@@ -263,20 +300,21 @@ class TestPrunetraceback(object):
|
||||
if excinfo.errisinstance(MyError):
|
||||
return "hello world"
|
||||
return pytest.File.repr_failure(self, excinfo)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
result = testdir.runpytest(p)
|
||||
result.stdout.fnmatch_lines([
|
||||
"*ERROR collecting*",
|
||||
"*hello world*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*ERROR collecting*", "*hello world*"])
|
||||
|
||||
@pytest.mark.xfail(reason="other mechanism for adding to reporting needed")
|
||||
def test_collect_report_postprocessing(self, testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import not_exists
|
||||
""")
|
||||
testdir.makeconftest("""
|
||||
"""
|
||||
)
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_make_collect_report():
|
||||
@@ -284,21 +322,21 @@ class TestPrunetraceback(object):
|
||||
rep = outcome.get_result()
|
||||
rep.headerlines += ["header1"]
|
||||
outcome.force_result(rep)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest(p)
|
||||
result.stdout.fnmatch_lines([
|
||||
"*ERROR collecting*",
|
||||
"*header1*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*ERROR collecting*", "*header1*"])
|
||||
|
||||
|
||||
class TestCustomConftests(object):
|
||||
def test_ignore_collect_path(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
def pytest_ignore_collect(path, config):
|
||||
return path.basename.startswith("x") or \
|
||||
path.basename == "test_one.py"
|
||||
""")
|
||||
"""
|
||||
)
|
||||
sub = testdir.mkdir("xy123")
|
||||
sub.ensure("test_hello.py").write("syntax error")
|
||||
sub.join("conftest.py").write("syntax error")
|
||||
@@ -309,10 +347,12 @@ class TestCustomConftests(object):
|
||||
result.stdout.fnmatch_lines(["*1 passed*"])
|
||||
|
||||
def test_ignore_collect_not_called_on_argument(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
def pytest_ignore_collect(path, config):
|
||||
return True
|
||||
""")
|
||||
"""
|
||||
)
|
||||
p = testdir.makepyfile("def test_hello(): pass")
|
||||
result = testdir.runpytest(p)
|
||||
assert result.ret == 0
|
||||
@@ -322,14 +362,16 @@ class TestCustomConftests(object):
|
||||
result.stdout.fnmatch_lines("*collected 0 items*")
|
||||
|
||||
def test_collectignore_exclude_on_option(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
collect_ignore = ['hello', 'test_world.py']
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption("--XX", action="store_true", default=False)
|
||||
def pytest_configure(config):
|
||||
if config.getvalue("XX"):
|
||||
collect_ignore[:] = []
|
||||
""")
|
||||
"""
|
||||
)
|
||||
testdir.mkdir("hello")
|
||||
testdir.makepyfile(test_world="def test_hello(): pass")
|
||||
result = testdir.runpytest()
|
||||
@@ -340,52 +382,51 @@ class TestCustomConftests(object):
|
||||
assert "passed" in result.stdout.str()
|
||||
|
||||
def test_pytest_fs_collect_hooks_are_seen(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import pytest
|
||||
class MyModule(pytest.Module):
|
||||
pass
|
||||
def pytest_collect_file(path, parent):
|
||||
if path.ext == ".py":
|
||||
return MyModule(path, parent)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
testdir.mkdir("sub")
|
||||
testdir.makepyfile("def test_x(): pass")
|
||||
result = testdir.runpytest("--collect-only")
|
||||
result.stdout.fnmatch_lines([
|
||||
"*MyModule*",
|
||||
"*test_x*"
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*MyModule*", "*test_x*"])
|
||||
|
||||
def test_pytest_collect_file_from_sister_dir(self, testdir):
|
||||
sub1 = testdir.mkpydir("sub1")
|
||||
sub2 = testdir.mkpydir("sub2")
|
||||
conf1 = testdir.makeconftest("""
|
||||
conf1 = testdir.makeconftest(
|
||||
"""
|
||||
import pytest
|
||||
class MyModule1(pytest.Module):
|
||||
pass
|
||||
def pytest_collect_file(path, parent):
|
||||
if path.ext == ".py":
|
||||
return MyModule1(path, parent)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
conf1.move(sub1.join(conf1.basename))
|
||||
conf2 = testdir.makeconftest("""
|
||||
conf2 = testdir.makeconftest(
|
||||
"""
|
||||
import pytest
|
||||
class MyModule2(pytest.Module):
|
||||
pass
|
||||
def pytest_collect_file(path, parent):
|
||||
if path.ext == ".py":
|
||||
return MyModule2(path, parent)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
conf2.move(sub2.join(conf2.basename))
|
||||
p = testdir.makepyfile("def test_x(): pass")
|
||||
p.copy(sub1.join(p.basename))
|
||||
p.copy(sub2.join(p.basename))
|
||||
result = testdir.runpytest("--collect-only")
|
||||
result.stdout.fnmatch_lines([
|
||||
"*MyModule1*",
|
||||
"*MyModule2*",
|
||||
"*test_x*"
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*MyModule1*", "*MyModule2*", "*test_x*"])
|
||||
|
||||
|
||||
class TestSession(object):
|
||||
@@ -425,9 +466,13 @@ class TestSession(object):
|
||||
|
||||
def get_reported_items(self, hookrec):
|
||||
"""Return pytest.Item instances reported by the pytest_collectreport hook"""
|
||||
calls = hookrec.getcalls('pytest_collectreport')
|
||||
return [x for call in calls for x in call.report.result
|
||||
if isinstance(x, pytest.Item)]
|
||||
calls = hookrec.getcalls("pytest_collectreport")
|
||||
return [
|
||||
x
|
||||
for call in calls
|
||||
for x in call.report.result
|
||||
if isinstance(x, pytest.Item)
|
||||
]
|
||||
|
||||
def test_collect_protocol_single_function(self, testdir):
|
||||
p = testdir.makepyfile("def test_func(): pass")
|
||||
@@ -439,40 +484,46 @@ class TestSession(object):
|
||||
assert newid == id
|
||||
pprint.pprint(hookrec.calls)
|
||||
topdir = testdir.tmpdir # noqa
|
||||
hookrec.assert_contains([
|
||||
("pytest_collectstart", "collector.fspath == topdir"),
|
||||
("pytest_make_collect_report", "collector.fspath == topdir"),
|
||||
("pytest_collectstart", "collector.fspath == p"),
|
||||
("pytest_make_collect_report", "collector.fspath == p"),
|
||||
("pytest_pycollect_makeitem", "name == 'test_func'"),
|
||||
("pytest_collectreport", "report.result[0].name == 'test_func'"),
|
||||
])
|
||||
hookrec.assert_contains(
|
||||
[
|
||||
("pytest_collectstart", "collector.fspath == topdir"),
|
||||
("pytest_make_collect_report", "collector.fspath == topdir"),
|
||||
("pytest_collectstart", "collector.fspath == p"),
|
||||
("pytest_make_collect_report", "collector.fspath == p"),
|
||||
("pytest_pycollect_makeitem", "name == 'test_func'"),
|
||||
("pytest_collectreport", "report.result[0].name == 'test_func'"),
|
||||
]
|
||||
)
|
||||
# ensure we are reporting the collection of the single test item (#2464)
|
||||
assert [x.name for x in self.get_reported_items(hookrec)] == ['test_func']
|
||||
assert [x.name for x in self.get_reported_items(hookrec)] == ["test_func"]
|
||||
|
||||
def test_collect_protocol_method(self, testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
class TestClass(object):
|
||||
def test_method(self):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
normid = p.basename + "::TestClass::()::test_method"
|
||||
for id in [p.basename,
|
||||
p.basename + "::TestClass",
|
||||
p.basename + "::TestClass::()",
|
||||
normid,
|
||||
]:
|
||||
for id in [
|
||||
p.basename,
|
||||
p.basename + "::TestClass",
|
||||
p.basename + "::TestClass::()",
|
||||
normid,
|
||||
]:
|
||||
items, hookrec = testdir.inline_genitems(id)
|
||||
assert len(items) == 1
|
||||
assert items[0].name == "test_method"
|
||||
newid = items[0].nodeid
|
||||
assert newid == normid
|
||||
# ensure we are reporting the collection of the single test item (#2464)
|
||||
assert [x.name for x in self.get_reported_items(hookrec)] == ['test_method']
|
||||
assert [x.name for x in self.get_reported_items(hookrec)] == ["test_method"]
|
||||
|
||||
def test_collect_custom_nodes_multi_id(self, testdir):
|
||||
p = testdir.makepyfile("def test_func(): pass")
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import pytest
|
||||
class SpecialItem(pytest.Item):
|
||||
def runtest(self):
|
||||
@@ -483,22 +534,26 @@ class TestSession(object):
|
||||
def pytest_collect_file(path, parent):
|
||||
if path.basename == %r:
|
||||
return SpecialFile(fspath=path, parent=parent)
|
||||
""" % p.basename)
|
||||
"""
|
||||
% p.basename
|
||||
)
|
||||
id = p.basename
|
||||
|
||||
items, hookrec = testdir.inline_genitems(id)
|
||||
pprint.pprint(hookrec.calls)
|
||||
assert len(items) == 2
|
||||
hookrec.assert_contains([
|
||||
("pytest_collectstart",
|
||||
"collector.fspath == collector.session.fspath"),
|
||||
("pytest_collectstart",
|
||||
"collector.__class__.__name__ == 'SpecialFile'"),
|
||||
("pytest_collectstart",
|
||||
"collector.__class__.__name__ == 'Module'"),
|
||||
("pytest_pycollect_makeitem", "name == 'test_func'"),
|
||||
("pytest_collectreport", "report.nodeid.startswith(p.basename)"),
|
||||
])
|
||||
hookrec.assert_contains(
|
||||
[
|
||||
("pytest_collectstart", "collector.fspath == collector.session.fspath"),
|
||||
(
|
||||
"pytest_collectstart",
|
||||
"collector.__class__.__name__ == 'SpecialFile'",
|
||||
),
|
||||
("pytest_collectstart", "collector.__class__.__name__ == 'Module'"),
|
||||
("pytest_pycollect_makeitem", "name == 'test_func'"),
|
||||
("pytest_collectreport", "report.nodeid.startswith(p.basename)"),
|
||||
]
|
||||
)
|
||||
assert len(self.get_reported_items(hookrec)) == 2
|
||||
|
||||
def test_collect_subdir_event_ordering(self, testdir):
|
||||
@@ -510,12 +565,13 @@ class TestSession(object):
|
||||
items, hookrec = testdir.inline_genitems()
|
||||
assert len(items) == 1
|
||||
pprint.pprint(hookrec.calls)
|
||||
hookrec.assert_contains([
|
||||
("pytest_collectstart", "collector.fspath == test_aaa"),
|
||||
("pytest_pycollect_makeitem", "name == 'test_func'"),
|
||||
("pytest_collectreport",
|
||||
"report.nodeid.startswith('aaa/test_aaa.py')"),
|
||||
])
|
||||
hookrec.assert_contains(
|
||||
[
|
||||
("pytest_collectstart", "collector.fspath == test_aaa"),
|
||||
("pytest_pycollect_makeitem", "name == 'test_func'"),
|
||||
("pytest_collectreport", "report.nodeid.startswith('aaa/test_aaa.py')"),
|
||||
]
|
||||
)
|
||||
|
||||
def test_collect_two_commandline_args(self, testdir):
|
||||
p = testdir.makepyfile("def test_func(): pass")
|
||||
@@ -531,14 +587,16 @@ class TestSession(object):
|
||||
items, hookrec = testdir.inline_genitems(id)
|
||||
assert len(items) == 2
|
||||
pprint.pprint(hookrec.calls)
|
||||
hookrec.assert_contains([
|
||||
("pytest_collectstart", "collector.fspath == test_aaa"),
|
||||
("pytest_pycollect_makeitem", "name == 'test_func'"),
|
||||
("pytest_collectreport", "report.nodeid == 'aaa/test_aaa.py'"),
|
||||
("pytest_collectstart", "collector.fspath == test_bbb"),
|
||||
("pytest_pycollect_makeitem", "name == 'test_func'"),
|
||||
("pytest_collectreport", "report.nodeid == 'bbb/test_bbb.py'"),
|
||||
])
|
||||
hookrec.assert_contains(
|
||||
[
|
||||
("pytest_collectstart", "collector.fspath == test_aaa"),
|
||||
("pytest_pycollect_makeitem", "name == 'test_func'"),
|
||||
("pytest_collectreport", "report.nodeid == 'aaa/test_aaa.py'"),
|
||||
("pytest_collectstart", "collector.fspath == test_bbb"),
|
||||
("pytest_pycollect_makeitem", "name == 'test_func'"),
|
||||
("pytest_collectreport", "report.nodeid == 'bbb/test_bbb.py'"),
|
||||
]
|
||||
)
|
||||
|
||||
def test_serialization_byid(self, testdir):
|
||||
testdir.makepyfile("def test_func(): pass")
|
||||
@@ -551,18 +609,20 @@ class TestSession(object):
|
||||
assert item2.fspath == item.fspath
|
||||
|
||||
def test_find_byid_without_instance_parents(self, testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
class TestClass(object):
|
||||
def test_method(self):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
arg = p.basename + "::TestClass::test_method"
|
||||
items, hookrec = testdir.inline_genitems(arg)
|
||||
assert len(items) == 1
|
||||
item, = items
|
||||
assert item.nodeid.endswith("TestClass::()::test_method")
|
||||
# ensure we are reporting the collection of the single test item (#2464)
|
||||
assert [x.name for x in self.get_reported_items(hookrec)] == ['test_method']
|
||||
assert [x.name for x in self.get_reported_items(hookrec)] == ["test_method"]
|
||||
|
||||
|
||||
class Test_getinitialnodes(object):
|
||||
@@ -572,7 +632,7 @@ class Test_getinitialnodes(object):
|
||||
config = testdir.parseconfigure(x)
|
||||
col = testdir.getnode(config, x)
|
||||
assert isinstance(col, pytest.Module)
|
||||
assert col.name == 'x.py'
|
||||
assert col.name == "x.py"
|
||||
assert col.parent.parent is None
|
||||
for col in col.listchain():
|
||||
assert col.config is config
|
||||
@@ -586,7 +646,7 @@ class Test_getinitialnodes(object):
|
||||
config = testdir.parseconfigure(x)
|
||||
col = testdir.getnode(config, x)
|
||||
assert isinstance(col, pytest.Module)
|
||||
assert col.name == 'x.py'
|
||||
assert col.name == "x.py"
|
||||
assert col.parent.parent.parent is None
|
||||
for col in col.listchain():
|
||||
assert col.config is config
|
||||
@@ -594,13 +654,15 @@ class Test_getinitialnodes(object):
|
||||
|
||||
class Test_genitems(object):
|
||||
def test_check_collect_hashes(self, testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
def test_1():
|
||||
pass
|
||||
|
||||
def test_2():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
p.copy(p.dirpath(p.purebasename + "2" + ".py"))
|
||||
items, reprec = testdir.inline_genitems(p.dirpath())
|
||||
assert len(items) == 4
|
||||
@@ -611,7 +673,8 @@ class Test_genitems(object):
|
||||
assert i != j
|
||||
|
||||
def test_example_items1(self, testdir):
|
||||
p = testdir.makepyfile('''
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
def testone():
|
||||
pass
|
||||
|
||||
@@ -621,12 +684,13 @@ class Test_genitems(object):
|
||||
|
||||
class TestY(TestX):
|
||||
pass
|
||||
''')
|
||||
"""
|
||||
)
|
||||
items, reprec = testdir.inline_genitems(p)
|
||||
assert len(items) == 3
|
||||
assert items[0].name == 'testone'
|
||||
assert items[1].name == 'testmethod_one'
|
||||
assert items[2].name == 'testmethod_one'
|
||||
assert items[0].name == "testone"
|
||||
assert items[1].name == "testmethod_one"
|
||||
assert items[2].name == "testmethod_one"
|
||||
|
||||
# let's also test getmodpath here
|
||||
assert items[0].getmodpath() == "testone"
|
||||
@@ -642,12 +706,15 @@ class Test_genitems(object):
|
||||
tests that python_classes and python_functions config options work
|
||||
as prefixes and glob-like patterns (issue #600).
|
||||
"""
|
||||
testdir.makeini("""
|
||||
testdir.makeini(
|
||||
"""
|
||||
[pytest]
|
||||
python_classes = *Suite Test
|
||||
python_functions = *_test test
|
||||
""")
|
||||
p = testdir.makepyfile('''
|
||||
"""
|
||||
)
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
class MyTestSuite(object):
|
||||
def x_test(self):
|
||||
pass
|
||||
@@ -655,14 +722,16 @@ class Test_genitems(object):
|
||||
class TestCase(object):
|
||||
def test_y(self):
|
||||
pass
|
||||
''')
|
||||
"""
|
||||
)
|
||||
items, reprec = testdir.inline_genitems(p)
|
||||
ids = [x.getmodpath() for x in items]
|
||||
assert ids == ['MyTestSuite.x_test', 'TestCase.test_y']
|
||||
assert ids == ["MyTestSuite.x_test", "TestCase.test_y"]
|
||||
|
||||
|
||||
def test_matchnodes_two_collections_same_file(testdir):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import pytest
|
||||
def pytest_configure(config):
|
||||
config.pluginmanager.register(Plugin2())
|
||||
@@ -686,25 +755,24 @@ def test_matchnodes_two_collections_same_file(testdir):
|
||||
class Item2(pytest.Item):
|
||||
def runtest(self):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
p = testdir.makefile(".abc", "")
|
||||
result = testdir.runpytest()
|
||||
assert result.ret == 0
|
||||
result.stdout.fnmatch_lines([
|
||||
"*2 passed*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*2 passed*"])
|
||||
res = testdir.runpytest("%s::hello" % p.basename)
|
||||
res.stdout.fnmatch_lines([
|
||||
"*1 passed*",
|
||||
])
|
||||
res.stdout.fnmatch_lines(["*1 passed*"])
|
||||
|
||||
|
||||
class TestNodekeywords(object):
|
||||
def test_no_under(self, testdir):
|
||||
modcol = testdir.getmodulecol("""
|
||||
modcol = testdir.getmodulecol(
|
||||
"""
|
||||
def test_pass(): pass
|
||||
def test_fail(): assert 0
|
||||
""")
|
||||
"""
|
||||
)
|
||||
values = list(modcol.keywords)
|
||||
assert modcol.name in values
|
||||
for x in values:
|
||||
@@ -712,13 +780,15 @@ class TestNodekeywords(object):
|
||||
assert modcol.name in repr(modcol.keywords)
|
||||
|
||||
def test_issue345(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_should_not_be_selected():
|
||||
assert False, 'I should not have been selected to run'
|
||||
|
||||
def test___repr__():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run("-k repr")
|
||||
reprec.assertoutcome(passed=1, failed=0)
|
||||
|
||||
@@ -752,13 +822,15 @@ def test_exit_on_collection_error(testdir):
|
||||
res = testdir.runpytest()
|
||||
assert res.ret == 2
|
||||
|
||||
res.stdout.fnmatch_lines([
|
||||
"collected 2 items / 2 errors",
|
||||
"*ERROR collecting test_02_import_error.py*",
|
||||
"*No module named *asdfa*",
|
||||
"*ERROR collecting test_03_import_error.py*",
|
||||
"*No module named *asdfa*",
|
||||
])
|
||||
res.stdout.fnmatch_lines(
|
||||
[
|
||||
"collected 2 items / 2 errors",
|
||||
"*ERROR collecting test_02_import_error.py*",
|
||||
"*No module named *asdfa*",
|
||||
"*ERROR collecting test_03_import_error.py*",
|
||||
"*No module named *asdfa*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_exit_on_collection_with_maxfail_smaller_than_n_errors(testdir):
|
||||
@@ -771,12 +843,11 @@ def test_exit_on_collection_with_maxfail_smaller_than_n_errors(testdir):
|
||||
res = testdir.runpytest("--maxfail=1")
|
||||
assert res.ret == 1
|
||||
|
||||
res.stdout.fnmatch_lines([
|
||||
"*ERROR collecting test_02_import_error.py*",
|
||||
"*No module named *asdfa*",
|
||||
])
|
||||
res.stdout.fnmatch_lines(
|
||||
["*ERROR collecting test_02_import_error.py*", "*No module named *asdfa*"]
|
||||
)
|
||||
|
||||
assert 'test_03' not in res.stdout.str()
|
||||
assert "test_03" not in res.stdout.str()
|
||||
|
||||
|
||||
def test_exit_on_collection_with_maxfail_bigger_than_n_errors(testdir):
|
||||
@@ -789,13 +860,15 @@ def test_exit_on_collection_with_maxfail_bigger_than_n_errors(testdir):
|
||||
res = testdir.runpytest("--maxfail=4")
|
||||
assert res.ret == 2
|
||||
|
||||
res.stdout.fnmatch_lines([
|
||||
"collected 2 items / 2 errors",
|
||||
"*ERROR collecting test_02_import_error.py*",
|
||||
"*No module named *asdfa*",
|
||||
"*ERROR collecting test_03_import_error.py*",
|
||||
"*No module named *asdfa*",
|
||||
])
|
||||
res.stdout.fnmatch_lines(
|
||||
[
|
||||
"collected 2 items / 2 errors",
|
||||
"*ERROR collecting test_02_import_error.py*",
|
||||
"*No module named *asdfa*",
|
||||
"*ERROR collecting test_03_import_error.py*",
|
||||
"*No module named *asdfa*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_continue_on_collection_errors(testdir):
|
||||
@@ -808,10 +881,9 @@ def test_continue_on_collection_errors(testdir):
|
||||
res = testdir.runpytest("--continue-on-collection-errors")
|
||||
assert res.ret == 1
|
||||
|
||||
res.stdout.fnmatch_lines([
|
||||
"collected 2 items / 2 errors",
|
||||
"*1 failed, 1 passed, 2 error*",
|
||||
])
|
||||
res.stdout.fnmatch_lines(
|
||||
["collected 2 items / 2 errors", "*1 failed, 1 passed, 2 error*"]
|
||||
)
|
||||
|
||||
|
||||
def test_continue_on_collection_errors_maxfail(testdir):
|
||||
@@ -827,21 +899,22 @@ def test_continue_on_collection_errors_maxfail(testdir):
|
||||
res = testdir.runpytest("--continue-on-collection-errors", "--maxfail=3")
|
||||
assert res.ret == 1
|
||||
|
||||
res.stdout.fnmatch_lines([
|
||||
"collected 2 items / 2 errors",
|
||||
"*1 failed, 2 error*",
|
||||
])
|
||||
res.stdout.fnmatch_lines(["collected 2 items / 2 errors", "*1 failed, 2 error*"])
|
||||
|
||||
|
||||
def test_fixture_scope_sibling_conftests(testdir):
|
||||
"""Regression test case for https://github.com/pytest-dev/pytest/issues/2836"""
|
||||
foo_path = testdir.mkdir("foo")
|
||||
foo_path.join("conftest.py").write(_pytest._code.Source("""
|
||||
foo_path.join("conftest.py").write(
|
||||
_pytest._code.Source(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def fix():
|
||||
return 1
|
||||
"""))
|
||||
"""
|
||||
)
|
||||
)
|
||||
foo_path.join("test_foo.py").write("def test_foo(fix): assert fix == 1")
|
||||
|
||||
# Tests in `food/` should not see the conftest fixture from `foo/`
|
||||
@@ -851,8 +924,10 @@ def test_fixture_scope_sibling_conftests(testdir):
|
||||
res = testdir.runpytest()
|
||||
assert res.ret == 1
|
||||
|
||||
res.stdout.fnmatch_lines([
|
||||
"*ERROR at setup of test_food*",
|
||||
"E*fixture 'fix' not found",
|
||||
"*1 passed, 1 error*",
|
||||
])
|
||||
res.stdout.fnmatch_lines(
|
||||
[
|
||||
"*ERROR at setup of test_food*",
|
||||
"E*fixture 'fix' not found",
|
||||
"*1 passed, 1 error*",
|
||||
]
|
||||
)
|
||||
|
||||
@@ -18,7 +18,6 @@ def test_is_generator():
|
||||
|
||||
|
||||
def test_real_func_loop_limit():
|
||||
|
||||
class Evil(object):
|
||||
def __init__(self):
|
||||
self.left = 1000
|
||||
@@ -28,7 +27,7 @@ def test_real_func_loop_limit():
|
||||
|
||||
def __getattr__(self, attr):
|
||||
if not self.left:
|
||||
raise RuntimeError('its over')
|
||||
raise RuntimeError("its over")
|
||||
self.left -= 1
|
||||
return self
|
||||
|
||||
@@ -39,10 +38,12 @@ def test_real_func_loop_limit():
|
||||
print(res)
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 4),
|
||||
reason='asyncio available in Python 3.4+')
|
||||
@pytest.mark.skipif(
|
||||
sys.version_info < (3, 4), reason="asyncio available in Python 3.4+"
|
||||
)
|
||||
def test_is_generator_asyncio(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
from _pytest.compat import is_generator
|
||||
import asyncio
|
||||
@asyncio.coroutine
|
||||
@@ -51,17 +52,20 @@ def test_is_generator_asyncio(testdir):
|
||||
|
||||
def test_is_generator_asyncio():
|
||||
assert not is_generator(baz)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
# avoid importing asyncio into pytest's own process,
|
||||
# which in turn imports logging (#8)
|
||||
result = testdir.runpytest_subprocess()
|
||||
result.stdout.fnmatch_lines(['*1 passed*'])
|
||||
result.stdout.fnmatch_lines(["*1 passed*"])
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 5),
|
||||
reason='async syntax available in Python 3.5+')
|
||||
@pytest.mark.skipif(
|
||||
sys.version_info < (3, 5), reason="async syntax available in Python 3.5+"
|
||||
)
|
||||
def test_is_generator_async_syntax(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
from _pytest.compat import is_generator
|
||||
def test_is_generator_py35():
|
||||
async def foo():
|
||||
@@ -72,19 +76,20 @@ def test_is_generator_async_syntax(testdir):
|
||||
|
||||
assert not is_generator(foo)
|
||||
assert not is_generator(bar)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(['*1 passed*'])
|
||||
result.stdout.fnmatch_lines(["*1 passed*"])
|
||||
|
||||
|
||||
class ErrorsHelper(object):
|
||||
@property
|
||||
def raise_exception(self):
|
||||
raise Exception('exception should be catched')
|
||||
raise Exception("exception should be catched")
|
||||
|
||||
@property
|
||||
def raise_fail(self):
|
||||
pytest.fail('fail should be catched')
|
||||
pytest.fail("fail should be catched")
|
||||
|
||||
|
||||
def test_helper_failures():
|
||||
@@ -97,5 +102,5 @@ def test_helper_failures():
|
||||
|
||||
def test_safe_getattr():
|
||||
helper = ErrorsHelper()
|
||||
assert safe_getattr(helper, 'raise_exception', 'default') == 'default'
|
||||
assert safe_getattr(helper, 'raise_fail', 'default') == 'default'
|
||||
assert safe_getattr(helper, "raise_exception", "default") == "default"
|
||||
assert safe_getattr(helper, "raise_fail", "default") == "default"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@ from _pytest.main import EXIT_NOTESTSCOLLECTED, EXIT_USAGEERROR
|
||||
@pytest.fixture(scope="module", params=["global", "inpackage"])
|
||||
def basedir(request, tmpdir_factory):
|
||||
from _pytest.tmpdir import tmpdir
|
||||
|
||||
tmpdir = tmpdir(request, tmpdir_factory)
|
||||
tmpdir.ensure("adir/conftest.py").write("a=1 ; Directory = 3")
|
||||
tmpdir.ensure("adir/b/conftest.py").write("b=2 ; a = 1.5")
|
||||
@@ -32,6 +33,7 @@ def conftest_setinitial(conftest, args, confcutdir=None):
|
||||
self.file_or_dir = args
|
||||
self.confcutdir = str(confcutdir)
|
||||
self.noconftest = False
|
||||
|
||||
conftest._set_initial_conftests(Namespace())
|
||||
|
||||
|
||||
@@ -47,15 +49,15 @@ class TestConftestValueAccessGlobal(object):
|
||||
conftest._getconftestmodules(basedir)
|
||||
snap1 = len(conftest._path2confmods)
|
||||
# assert len(conftest._path2confmods) == snap1 + 1
|
||||
conftest._getconftestmodules(basedir.join('adir'))
|
||||
conftest._getconftestmodules(basedir.join("adir"))
|
||||
assert len(conftest._path2confmods) == snap1 + 1
|
||||
conftest._getconftestmodules(basedir.join('b'))
|
||||
conftest._getconftestmodules(basedir.join("b"))
|
||||
assert len(conftest._path2confmods) == snap1 + 2
|
||||
|
||||
def test_value_access_not_existing(self, basedir):
|
||||
conftest = ConftestWithSetinitial(basedir)
|
||||
with pytest.raises(KeyError):
|
||||
conftest._rget_with_confmod('a', basedir)
|
||||
conftest._rget_with_confmod("a", basedir)
|
||||
|
||||
def test_value_access_by_path(self, basedir):
|
||||
conftest = ConftestWithSetinitial(basedir)
|
||||
@@ -105,7 +107,8 @@ def test_issue151_load_all_conftests(testdir):
|
||||
|
||||
def test_conftest_global_import(testdir):
|
||||
testdir.makeconftest("x=3")
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import py, pytest
|
||||
from _pytest.config import PytestPluginManager
|
||||
conf = PytestPluginManager()
|
||||
@@ -120,7 +123,8 @@ def test_conftest_global_import(testdir):
|
||||
assert mod2.y == 4
|
||||
import conftest
|
||||
assert conftest is mod2, (conftest, mod)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
res = testdir.runpython(p)
|
||||
assert res.ret == 0
|
||||
|
||||
@@ -154,13 +158,13 @@ def test_conftestcutdir_inplace_considered(testdir):
|
||||
assert values[0].__file__.startswith(str(conf))
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name", 'test tests whatever .dotdir'.split())
|
||||
@pytest.mark.parametrize("name", "test tests whatever .dotdir".split())
|
||||
def test_setinitial_conftest_subdirs(testdir, name):
|
||||
sub = testdir.mkdir(name)
|
||||
subconftest = sub.ensure("conftest.py")
|
||||
conftest = PytestPluginManager()
|
||||
conftest_setinitial(conftest, [sub.dirpath()], confcutdir=testdir.tmpdir)
|
||||
if name not in ('whatever', '.dotdir'):
|
||||
if name not in ("whatever", ".dotdir"):
|
||||
assert subconftest in conftest._conftestpath2mod
|
||||
assert len(conftest._conftestpath2mod) == 1
|
||||
else:
|
||||
@@ -171,13 +175,17 @@ def test_setinitial_conftest_subdirs(testdir, name):
|
||||
def test_conftest_confcutdir(testdir):
|
||||
testdir.makeconftest("assert 0")
|
||||
x = testdir.mkdir("x")
|
||||
x.join("conftest.py").write(_pytest._code.Source("""
|
||||
x.join("conftest.py").write(
|
||||
_pytest._code.Source(
|
||||
"""
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption("--xyz", action="store_true")
|
||||
"""))
|
||||
"""
|
||||
)
|
||||
)
|
||||
result = testdir.runpytest("-h", "--confcutdir=%s" % x, x)
|
||||
result.stdout.fnmatch_lines(["*--xyz*"])
|
||||
assert 'warning: could not load initial' not in result.stdout.str()
|
||||
assert "warning: could not load initial" not in result.stdout.str()
|
||||
|
||||
|
||||
def test_no_conftest(testdir):
|
||||
@@ -191,10 +199,14 @@ def test_no_conftest(testdir):
|
||||
|
||||
def test_conftest_existing_resultlog(testdir):
|
||||
x = testdir.mkdir("tests")
|
||||
x.join("conftest.py").write(_pytest._code.Source("""
|
||||
x.join("conftest.py").write(
|
||||
_pytest._code.Source(
|
||||
"""
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption("--xyz", action="store_true")
|
||||
"""))
|
||||
"""
|
||||
)
|
||||
)
|
||||
testdir.makefile(ext=".log", result="") # Writes result.log
|
||||
result = testdir.runpytest("-h", "--resultlog", "result.log")
|
||||
result.stdout.fnmatch_lines(["*--xyz*"])
|
||||
@@ -202,10 +214,14 @@ def test_conftest_existing_resultlog(testdir):
|
||||
|
||||
def test_conftest_existing_junitxml(testdir):
|
||||
x = testdir.mkdir("tests")
|
||||
x.join("conftest.py").write(_pytest._code.Source("""
|
||||
x.join("conftest.py").write(
|
||||
_pytest._code.Source(
|
||||
"""
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption("--xyz", action="store_true")
|
||||
"""))
|
||||
"""
|
||||
)
|
||||
)
|
||||
testdir.makefile(ext=".xml", junit="") # Writes junit.xml
|
||||
result = testdir.runpytest("-h", "--junitxml", "junit.xml")
|
||||
result.stdout.fnmatch_lines(["*--xyz*"])
|
||||
@@ -222,7 +238,7 @@ def test_conftest_import_order(testdir, monkeypatch):
|
||||
|
||||
conftest = PytestPluginManager()
|
||||
conftest._confcutdir = testdir.tmpdir
|
||||
monkeypatch.setattr(conftest, '_importconftest', impct)
|
||||
monkeypatch.setattr(conftest, "_importconftest", impct)
|
||||
assert conftest._getconftestmodules(sub) == [ct1, ct2]
|
||||
|
||||
|
||||
@@ -232,7 +248,9 @@ def test_fixture_dependency(testdir, monkeypatch):
|
||||
ct1.write("")
|
||||
sub = testdir.mkdir("sub")
|
||||
sub.join("__init__.py").write("")
|
||||
sub.join("conftest.py").write(dedent("""
|
||||
sub.join("conftest.py").write(
|
||||
dedent(
|
||||
"""
|
||||
import pytest
|
||||
|
||||
@pytest.fixture
|
||||
@@ -246,10 +264,14 @@ def test_fixture_dependency(testdir, monkeypatch):
|
||||
@pytest.fixture
|
||||
def bar(foo):
|
||||
return 'bar'
|
||||
"""))
|
||||
"""
|
||||
)
|
||||
)
|
||||
subsub = sub.mkdir("subsub")
|
||||
subsub.join("__init__.py").write("")
|
||||
subsub.join("test_bar.py").write(dedent("""
|
||||
subsub.join("test_bar.py").write(
|
||||
dedent(
|
||||
"""
|
||||
import pytest
|
||||
|
||||
@pytest.fixture
|
||||
@@ -258,23 +280,31 @@ def test_fixture_dependency(testdir, monkeypatch):
|
||||
|
||||
def test_event_fixture(bar):
|
||||
assert bar == 'sub bar'
|
||||
"""))
|
||||
"""
|
||||
)
|
||||
)
|
||||
result = testdir.runpytest("sub")
|
||||
result.stdout.fnmatch_lines(["*1 passed*"])
|
||||
|
||||
|
||||
def test_conftest_found_with_double_dash(testdir):
|
||||
sub = testdir.mkdir("sub")
|
||||
sub.join("conftest.py").write(dedent("""
|
||||
sub.join("conftest.py").write(
|
||||
dedent(
|
||||
"""
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption("--hello-world", action="store_true")
|
||||
"""))
|
||||
"""
|
||||
)
|
||||
)
|
||||
p = sub.join("test_hello.py")
|
||||
p.write("def test_hello(): pass")
|
||||
result = testdir.runpytest(str(p) + "::test_hello", "-h")
|
||||
result.stdout.fnmatch_lines("""
|
||||
result.stdout.fnmatch_lines(
|
||||
"""
|
||||
*--hello-world*
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
class TestConftestVisibility(object):
|
||||
@@ -284,82 +314,98 @@ class TestConftestVisibility(object):
|
||||
runner = testdir.mkdir("empty")
|
||||
package = testdir.mkdir("package")
|
||||
|
||||
package.join("conftest.py").write(dedent("""\
|
||||
package.join("conftest.py").write(
|
||||
dedent(
|
||||
"""\
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def fxtr():
|
||||
return "from-package"
|
||||
"""))
|
||||
package.join("test_pkgroot.py").write(dedent("""\
|
||||
"""
|
||||
)
|
||||
)
|
||||
package.join("test_pkgroot.py").write(
|
||||
dedent(
|
||||
"""\
|
||||
def test_pkgroot(fxtr):
|
||||
assert fxtr == "from-package"
|
||||
"""))
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
swc = package.mkdir("swc")
|
||||
swc.join("__init__.py").ensure()
|
||||
swc.join("conftest.py").write(dedent("""\
|
||||
swc.join("conftest.py").write(
|
||||
dedent(
|
||||
"""\
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def fxtr():
|
||||
return "from-swc"
|
||||
"""))
|
||||
swc.join("test_with_conftest.py").write(dedent("""\
|
||||
"""
|
||||
)
|
||||
)
|
||||
swc.join("test_with_conftest.py").write(
|
||||
dedent(
|
||||
"""\
|
||||
def test_with_conftest(fxtr):
|
||||
assert fxtr == "from-swc"
|
||||
|
||||
"""))
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
snc = package.mkdir("snc")
|
||||
snc.join("__init__.py").ensure()
|
||||
snc.join("test_no_conftest.py").write(dedent("""\
|
||||
snc.join("test_no_conftest.py").write(
|
||||
dedent(
|
||||
"""\
|
||||
def test_no_conftest(fxtr):
|
||||
assert fxtr == "from-package" # No local conftest.py, so should
|
||||
# use value from parent dir's
|
||||
|
||||
"""))
|
||||
"""
|
||||
)
|
||||
)
|
||||
print("created directory structure:")
|
||||
for x in testdir.tmpdir.visit():
|
||||
print(" " + x.relto(testdir.tmpdir))
|
||||
|
||||
return {
|
||||
"runner": runner,
|
||||
"package": package,
|
||||
"swc": swc,
|
||||
"snc": snc}
|
||||
return {"runner": runner, "package": package, "swc": swc, "snc": snc}
|
||||
|
||||
# N.B.: "swc" stands for "subdir with conftest.py"
|
||||
# "snc" stands for "subdir no [i.e. without] conftest.py"
|
||||
@pytest.mark.parametrize("chdir,testarg,expect_ntests_passed", [
|
||||
# Effective target: package/..
|
||||
("runner", "..", 3),
|
||||
("package", "..", 3),
|
||||
("swc", "../..", 3),
|
||||
("snc", "../..", 3),
|
||||
|
||||
# Effective target: package
|
||||
("runner", "../package", 3),
|
||||
("package", ".", 3),
|
||||
("swc", "..", 3),
|
||||
("snc", "..", 3),
|
||||
|
||||
# Effective target: package/swc
|
||||
("runner", "../package/swc", 1),
|
||||
("package", "./swc", 1),
|
||||
("swc", ".", 1),
|
||||
("snc", "../swc", 1),
|
||||
|
||||
# Effective target: package/snc
|
||||
("runner", "../package/snc", 1),
|
||||
("package", "./snc", 1),
|
||||
("swc", "../snc", 1),
|
||||
("snc", ".", 1),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"chdir,testarg,expect_ntests_passed",
|
||||
[
|
||||
# Effective target: package/..
|
||||
("runner", "..", 3),
|
||||
("package", "..", 3),
|
||||
("swc", "../..", 3),
|
||||
("snc", "../..", 3),
|
||||
# Effective target: package
|
||||
("runner", "../package", 3),
|
||||
("package", ".", 3),
|
||||
("swc", "..", 3),
|
||||
("snc", "..", 3),
|
||||
# Effective target: package/swc
|
||||
("runner", "../package/swc", 1),
|
||||
("package", "./swc", 1),
|
||||
("swc", ".", 1),
|
||||
("snc", "../swc", 1),
|
||||
# Effective target: package/snc
|
||||
("runner", "../package/snc", 1),
|
||||
("package", "./snc", 1),
|
||||
("swc", "../snc", 1),
|
||||
("snc", ".", 1),
|
||||
],
|
||||
)
|
||||
@pytest.mark.issue616
|
||||
def test_parsefactories_relative_node_ids(
|
||||
self, testdir, chdir, testarg, expect_ntests_passed):
|
||||
self, testdir, chdir, testarg, expect_ntests_passed
|
||||
):
|
||||
dirs = self._setup_tree(testdir)
|
||||
print("pytest run in cwd: %s" % (
|
||||
dirs[chdir].relto(testdir.tmpdir)))
|
||||
print("pytest run in cwd: %s" % (dirs[chdir].relto(testdir.tmpdir)))
|
||||
print("pytestarg : %s" % (testarg))
|
||||
print("expected pass : %s" % (expect_ntests_passed))
|
||||
with dirs[chdir].as_cwd():
|
||||
@@ -367,108 +413,127 @@ class TestConftestVisibility(object):
|
||||
reprec.assertoutcome(passed=expect_ntests_passed)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('confcutdir,passed,error', [
|
||||
('.', 2, 0),
|
||||
('src', 1, 1),
|
||||
(None, 1, 1),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"confcutdir,passed,error", [(".", 2, 0), ("src", 1, 1), (None, 1, 1)]
|
||||
)
|
||||
def test_search_conftest_up_to_inifile(testdir, confcutdir, passed, error):
|
||||
"""Test that conftest files are detected only up to a ini file, unless
|
||||
"""Test that conftest files are detected only up to an ini file, unless
|
||||
an explicit --confcutdir option is given.
|
||||
"""
|
||||
root = testdir.tmpdir
|
||||
src = root.join('src').ensure(dir=1)
|
||||
src.join('pytest.ini').write('[pytest]')
|
||||
src.join('conftest.py').write(_pytest._code.Source("""
|
||||
src = root.join("src").ensure(dir=1)
|
||||
src.join("pytest.ini").write("[pytest]")
|
||||
src.join("conftest.py").write(
|
||||
_pytest._code.Source(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def fix1(): pass
|
||||
"""))
|
||||
src.join('test_foo.py').write(_pytest._code.Source("""
|
||||
"""
|
||||
)
|
||||
)
|
||||
src.join("test_foo.py").write(
|
||||
_pytest._code.Source(
|
||||
"""
|
||||
def test_1(fix1):
|
||||
pass
|
||||
def test_2(out_of_reach):
|
||||
pass
|
||||
"""))
|
||||
root.join('conftest.py').write(_pytest._code.Source("""
|
||||
"""
|
||||
)
|
||||
)
|
||||
root.join("conftest.py").write(
|
||||
_pytest._code.Source(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.fixture
|
||||
def out_of_reach(): pass
|
||||
"""))
|
||||
"""
|
||||
)
|
||||
)
|
||||
|
||||
args = [str(src)]
|
||||
if confcutdir:
|
||||
args = ['--confcutdir=%s' % root.join(confcutdir)]
|
||||
args = ["--confcutdir=%s" % root.join(confcutdir)]
|
||||
result = testdir.runpytest(*args)
|
||||
match = ''
|
||||
match = ""
|
||||
if passed:
|
||||
match += '*%d passed*' % passed
|
||||
match += "*%d passed*" % passed
|
||||
if error:
|
||||
match += '*%d error*' % error
|
||||
match += "*%d error*" % error
|
||||
result.stdout.fnmatch_lines(match)
|
||||
|
||||
|
||||
def test_issue1073_conftest_special_objects(testdir):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
class DontTouchMe(object):
|
||||
def __getattr__(self, x):
|
||||
raise Exception('cant touch me')
|
||||
|
||||
x = DontTouchMe()
|
||||
""")
|
||||
testdir.makepyfile("""
|
||||
"""
|
||||
)
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_some():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
res = testdir.runpytest()
|
||||
assert res.ret == 0
|
||||
|
||||
|
||||
def test_conftest_exception_handling(testdir):
|
||||
testdir.makeconftest('''
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
raise ValueError()
|
||||
''')
|
||||
testdir.makepyfile("""
|
||||
"""
|
||||
)
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_some():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
res = testdir.runpytest()
|
||||
assert res.ret == 4
|
||||
assert 'raise ValueError()' in [line.strip() for line in res.errlines]
|
||||
assert "raise ValueError()" in [line.strip() for line in res.errlines]
|
||||
|
||||
|
||||
def test_hook_proxy(testdir):
|
||||
"""Session's gethookproxy() would cache conftests incorrectly (#2016).
|
||||
It was decided to remove the cache altogether.
|
||||
"""
|
||||
testdir.makepyfile(**{
|
||||
'root/demo-0/test_foo1.py': "def test1(): pass",
|
||||
|
||||
'root/demo-a/test_foo2.py': "def test1(): pass",
|
||||
'root/demo-a/conftest.py': """
|
||||
testdir.makepyfile(
|
||||
**{
|
||||
"root/demo-0/test_foo1.py": "def test1(): pass",
|
||||
"root/demo-a/test_foo2.py": "def test1(): pass",
|
||||
"root/demo-a/conftest.py": """
|
||||
def pytest_ignore_collect(path, config):
|
||||
return True
|
||||
""",
|
||||
|
||||
'root/demo-b/test_foo3.py': "def test1(): pass",
|
||||
'root/demo-c/test_foo4.py': "def test1(): pass",
|
||||
})
|
||||
"root/demo-b/test_foo3.py": "def test1(): pass",
|
||||
"root/demo-c/test_foo4.py": "def test1(): pass",
|
||||
}
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
'*test_foo1.py*',
|
||||
'*test_foo3.py*',
|
||||
'*test_foo4.py*',
|
||||
'*3 passed*',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
["*test_foo1.py*", "*test_foo3.py*", "*test_foo4.py*", "*3 passed*"]
|
||||
)
|
||||
|
||||
|
||||
def test_required_option_help(testdir):
|
||||
testdir.makeconftest("assert 0")
|
||||
x = testdir.mkdir("x")
|
||||
x.join("conftest.py").write(_pytest._code.Source("""
|
||||
x.join("conftest.py").write(
|
||||
_pytest._code.Source(
|
||||
"""
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption("--xyz", action="store_true", required=True)
|
||||
"""))
|
||||
"""
|
||||
)
|
||||
)
|
||||
result = testdir.runpytest("-h", x)
|
||||
assert 'argument --xyz is required' not in result.stdout.str()
|
||||
assert 'general:' in result.stdout.str()
|
||||
assert "argument --xyz is required" not in result.stdout.str()
|
||||
assert "general:" in result.stdout.str()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,11 +4,11 @@ import pkg_resources
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.parametrize("entrypoint", ['py.test', 'pytest'])
|
||||
@pytest.mark.parametrize("entrypoint", ["py.test", "pytest"])
|
||||
def test_entry_point_exist(entrypoint):
|
||||
assert entrypoint in pkg_resources.get_entry_map('pytest')['console_scripts']
|
||||
assert entrypoint in pkg_resources.get_entry_map("pytest")["console_scripts"]
|
||||
|
||||
|
||||
def test_pytest_entry_points_are_identical():
|
||||
entryMap = pkg_resources.get_entry_map('pytest')['console_scripts']
|
||||
assert entryMap['pytest'].module_name == entryMap['py.test'].module_name
|
||||
entryMap = pkg_resources.get_entry_map("pytest")["console_scripts"]
|
||||
assert entryMap["pytest"].module_name == entryMap["py.test"].module_name
|
||||
|
||||
@@ -7,57 +7,53 @@ def test_version(testdir, pytestconfig):
|
||||
result = testdir.runpytest("--version")
|
||||
assert result.ret == 0
|
||||
# p = py.path.local(py.__file__).dirpath()
|
||||
result.stderr.fnmatch_lines([
|
||||
'*pytest*%s*imported from*' % (pytest.__version__, )
|
||||
])
|
||||
result.stderr.fnmatch_lines(["*pytest*%s*imported from*" % (pytest.__version__,)])
|
||||
if pytestconfig.pluginmanager.list_plugin_distinfo():
|
||||
result.stderr.fnmatch_lines([
|
||||
"*setuptools registered plugins:",
|
||||
"*at*",
|
||||
])
|
||||
result.stderr.fnmatch_lines(["*setuptools registered plugins:", "*at*"])
|
||||
|
||||
|
||||
def test_help(testdir):
|
||||
result = testdir.runpytest("--help")
|
||||
assert result.ret == 0
|
||||
result.stdout.fnmatch_lines("""
|
||||
result.stdout.fnmatch_lines(
|
||||
"""
|
||||
*-v*verbose*
|
||||
*setup.cfg*
|
||||
*minversion*
|
||||
*to see*markers*pytest --markers*
|
||||
*to see*fixtures*pytest --fixtures*
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def test_hookvalidation_unknown(testdir):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
def pytest_hello(xyz):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
assert result.ret != 0
|
||||
result.stdout.fnmatch_lines([
|
||||
'*unknown hook*pytest_hello*'
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*unknown hook*pytest_hello*"])
|
||||
|
||||
|
||||
def test_hookvalidation_optional(testdir):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.hookimpl(optionalhook=True)
|
||||
def pytest_hello(xyz):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
assert result.ret == EXIT_NOTESTSCOLLECTED
|
||||
|
||||
|
||||
def test_traceconfig(testdir):
|
||||
result = testdir.runpytest("--traceconfig")
|
||||
result.stdout.fnmatch_lines([
|
||||
"*using*pytest*py*",
|
||||
"*active plugins*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*using*pytest*py*", "*active plugins*"])
|
||||
|
||||
|
||||
def test_debug(testdir, monkeypatch):
|
||||
@@ -71,7 +67,6 @@ def test_PYTEST_DEBUG(testdir, monkeypatch):
|
||||
monkeypatch.setenv("PYTEST_DEBUG", "1")
|
||||
result = testdir.runpytest_subprocess()
|
||||
assert result.ret == EXIT_NOTESTSCOLLECTED
|
||||
result.stderr.fnmatch_lines([
|
||||
"*pytest_plugin_registered*",
|
||||
"*manager*PluginManager*"
|
||||
])
|
||||
result.stderr.fnmatch_lines(
|
||||
["*pytest_plugin_registered*", "*manager*PluginManager*"]
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -5,21 +5,25 @@ import pytest
|
||||
import _pytest
|
||||
|
||||
MODSET = [
|
||||
x for x in py.path.local(_pytest.__file__).dirpath().visit('*.py')
|
||||
if x.purebasename != '__init__'
|
||||
x
|
||||
for x in py.path.local(_pytest.__file__).dirpath().visit("*.py")
|
||||
if x.purebasename != "__init__"
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('modfile', MODSET, ids=lambda x: x.purebasename)
|
||||
@pytest.mark.parametrize("modfile", MODSET, ids=lambda x: x.purebasename)
|
||||
def test_fileimport(modfile):
|
||||
# this test ensures all internal packages can import
|
||||
# without needing the pytest namespace being set
|
||||
# this is critical for the initialization of xdist
|
||||
|
||||
res = subprocess.call([
|
||||
sys.executable,
|
||||
'-c', 'import sys, py; py.path.local(sys.argv[1]).pyimport()',
|
||||
modfile.strpath,
|
||||
])
|
||||
res = subprocess.call(
|
||||
[
|
||||
sys.executable,
|
||||
"-c",
|
||||
"import sys, py; py.path.local(sys.argv[1]).pyimport()",
|
||||
modfile.strpath,
|
||||
]
|
||||
)
|
||||
if res:
|
||||
pytest.fail("command result %s" % res)
|
||||
|
||||
@@ -22,15 +22,15 @@ def test_setattr():
|
||||
|
||||
monkeypatch = MonkeyPatch()
|
||||
pytest.raises(AttributeError, "monkeypatch.setattr(A, 'notexists', 2)")
|
||||
monkeypatch.setattr(A, 'y', 2, raising=False)
|
||||
monkeypatch.setattr(A, "y", 2, raising=False)
|
||||
assert A.y == 2
|
||||
monkeypatch.undo()
|
||||
assert not hasattr(A, 'y')
|
||||
assert not hasattr(A, "y")
|
||||
|
||||
monkeypatch = MonkeyPatch()
|
||||
monkeypatch.setattr(A, 'x', 2)
|
||||
monkeypatch.setattr(A, "x", 2)
|
||||
assert A.x == 2
|
||||
monkeypatch.setattr(A, 'x', 3)
|
||||
monkeypatch.setattr(A, "x", 3)
|
||||
assert A.x == 3
|
||||
monkeypatch.undo()
|
||||
assert A.x == 1
|
||||
@@ -48,11 +48,13 @@ class TestSetattrWithImportPath(object):
|
||||
def test_string_expression_class(self, monkeypatch):
|
||||
monkeypatch.setattr("_pytest.config.Config", 42)
|
||||
import _pytest
|
||||
|
||||
assert _pytest.config.Config == 42
|
||||
|
||||
def test_unicode_string(self, monkeypatch):
|
||||
monkeypatch.setattr("_pytest.config.Config", 42)
|
||||
import _pytest
|
||||
|
||||
assert _pytest.config.Config == 42
|
||||
monkeypatch.delattr("_pytest.config.Config")
|
||||
|
||||
@@ -60,16 +62,16 @@ class TestSetattrWithImportPath(object):
|
||||
pytest.raises(TypeError, lambda: monkeypatch.setattr(None, None))
|
||||
|
||||
def test_unknown_import(self, monkeypatch):
|
||||
pytest.raises(ImportError,
|
||||
lambda: monkeypatch.setattr("unkn123.classx", None))
|
||||
pytest.raises(ImportError, lambda: monkeypatch.setattr("unkn123.classx", None))
|
||||
|
||||
def test_unknown_attr(self, monkeypatch):
|
||||
pytest.raises(AttributeError,
|
||||
lambda: monkeypatch.setattr("os.path.qweqwe", None))
|
||||
pytest.raises(
|
||||
AttributeError, lambda: monkeypatch.setattr("os.path.qweqwe", None)
|
||||
)
|
||||
|
||||
def test_unknown_attr_non_raising(self, monkeypatch):
|
||||
# https://github.com/pytest-dev/pytest/issues/746
|
||||
monkeypatch.setattr('os.path.qweqwe', 42, raising=False)
|
||||
monkeypatch.setattr("os.path.qweqwe", 42, raising=False)
|
||||
assert os.path.qweqwe == 42
|
||||
|
||||
def test_delattr(self, monkeypatch):
|
||||
@@ -84,44 +86,44 @@ def test_delattr():
|
||||
x = 1
|
||||
|
||||
monkeypatch = MonkeyPatch()
|
||||
monkeypatch.delattr(A, 'x')
|
||||
assert not hasattr(A, 'x')
|
||||
monkeypatch.delattr(A, "x")
|
||||
assert not hasattr(A, "x")
|
||||
monkeypatch.undo()
|
||||
assert A.x == 1
|
||||
|
||||
monkeypatch = MonkeyPatch()
|
||||
monkeypatch.delattr(A, 'x')
|
||||
monkeypatch.delattr(A, "x")
|
||||
pytest.raises(AttributeError, "monkeypatch.delattr(A, 'y')")
|
||||
monkeypatch.delattr(A, 'y', raising=False)
|
||||
monkeypatch.setattr(A, 'x', 5, raising=False)
|
||||
monkeypatch.delattr(A, "y", raising=False)
|
||||
monkeypatch.setattr(A, "x", 5, raising=False)
|
||||
assert A.x == 5
|
||||
monkeypatch.undo()
|
||||
assert A.x == 1
|
||||
|
||||
|
||||
def test_setitem():
|
||||
d = {'x': 1}
|
||||
d = {"x": 1}
|
||||
monkeypatch = MonkeyPatch()
|
||||
monkeypatch.setitem(d, 'x', 2)
|
||||
monkeypatch.setitem(d, 'y', 1700)
|
||||
monkeypatch.setitem(d, 'y', 1700)
|
||||
assert d['x'] == 2
|
||||
assert d['y'] == 1700
|
||||
monkeypatch.setitem(d, 'x', 3)
|
||||
assert d['x'] == 3
|
||||
monkeypatch.setitem(d, "x", 2)
|
||||
monkeypatch.setitem(d, "y", 1700)
|
||||
monkeypatch.setitem(d, "y", 1700)
|
||||
assert d["x"] == 2
|
||||
assert d["y"] == 1700
|
||||
monkeypatch.setitem(d, "x", 3)
|
||||
assert d["x"] == 3
|
||||
monkeypatch.undo()
|
||||
assert d['x'] == 1
|
||||
assert 'y' not in d
|
||||
d['x'] = 5
|
||||
assert d["x"] == 1
|
||||
assert "y" not in d
|
||||
d["x"] = 5
|
||||
monkeypatch.undo()
|
||||
assert d['x'] == 5
|
||||
assert d["x"] == 5
|
||||
|
||||
|
||||
def test_setitem_deleted_meanwhile():
|
||||
d = {}
|
||||
monkeypatch = MonkeyPatch()
|
||||
monkeypatch.setitem(d, 'x', 2)
|
||||
del d['x']
|
||||
monkeypatch.setitem(d, "x", 2)
|
||||
del d["x"]
|
||||
monkeypatch.undo()
|
||||
assert not d
|
||||
|
||||
@@ -132,7 +134,7 @@ def test_setenv_deleted_meanwhile(before):
|
||||
if before:
|
||||
os.environ[key] = "world"
|
||||
monkeypatch = MonkeyPatch()
|
||||
monkeypatch.setenv(key, 'hello')
|
||||
monkeypatch.setenv(key, "hello")
|
||||
del os.environ[key]
|
||||
monkeypatch.undo()
|
||||
if before:
|
||||
@@ -143,33 +145,34 @@ def test_setenv_deleted_meanwhile(before):
|
||||
|
||||
|
||||
def test_delitem():
|
||||
d = {'x': 1}
|
||||
d = {"x": 1}
|
||||
monkeypatch = MonkeyPatch()
|
||||
monkeypatch.delitem(d, 'x')
|
||||
assert 'x' not in d
|
||||
monkeypatch.delitem(d, 'y', raising=False)
|
||||
monkeypatch.delitem(d, "x")
|
||||
assert "x" not in d
|
||||
monkeypatch.delitem(d, "y", raising=False)
|
||||
pytest.raises(KeyError, "monkeypatch.delitem(d, 'y')")
|
||||
assert not d
|
||||
monkeypatch.setitem(d, 'y', 1700)
|
||||
assert d['y'] == 1700
|
||||
d['hello'] = 'world'
|
||||
monkeypatch.setitem(d, 'x', 1500)
|
||||
assert d['x'] == 1500
|
||||
monkeypatch.setitem(d, "y", 1700)
|
||||
assert d["y"] == 1700
|
||||
d["hello"] = "world"
|
||||
monkeypatch.setitem(d, "x", 1500)
|
||||
assert d["x"] == 1500
|
||||
monkeypatch.undo()
|
||||
assert d == {'hello': 'world', 'x': 1}
|
||||
assert d == {"hello": "world", "x": 1}
|
||||
|
||||
|
||||
def test_setenv():
|
||||
monkeypatch = MonkeyPatch()
|
||||
monkeypatch.setenv('XYZ123', 2)
|
||||
monkeypatch.setenv("XYZ123", 2)
|
||||
import os
|
||||
assert os.environ['XYZ123'] == "2"
|
||||
|
||||
assert os.environ["XYZ123"] == "2"
|
||||
monkeypatch.undo()
|
||||
assert 'XYZ123' not in os.environ
|
||||
assert "XYZ123" not in os.environ
|
||||
|
||||
|
||||
def test_delenv():
|
||||
name = 'xyz1234'
|
||||
name = "xyz1234"
|
||||
assert name not in os.environ
|
||||
monkeypatch = MonkeyPatch()
|
||||
pytest.raises(KeyError, "monkeypatch.delenv(%r, raising=True)" % name)
|
||||
@@ -191,28 +194,31 @@ def test_delenv():
|
||||
|
||||
def test_setenv_prepend():
|
||||
import os
|
||||
|
||||
monkeypatch = MonkeyPatch()
|
||||
monkeypatch.setenv('XYZ123', 2, prepend="-")
|
||||
assert os.environ['XYZ123'] == "2"
|
||||
monkeypatch.setenv('XYZ123', 3, prepend="-")
|
||||
assert os.environ['XYZ123'] == "3-2"
|
||||
monkeypatch.setenv("XYZ123", 2, prepend="-")
|
||||
assert os.environ["XYZ123"] == "2"
|
||||
monkeypatch.setenv("XYZ123", 3, prepend="-")
|
||||
assert os.environ["XYZ123"] == "3-2"
|
||||
monkeypatch.undo()
|
||||
assert 'XYZ123' not in os.environ
|
||||
assert "XYZ123" not in os.environ
|
||||
|
||||
|
||||
def test_monkeypatch_plugin(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
reprec = testdir.inline_runsource(
|
||||
"""
|
||||
def test_method(monkeypatch):
|
||||
assert monkeypatch.__class__.__name__ == "MonkeyPatch"
|
||||
""")
|
||||
"""
|
||||
)
|
||||
res = reprec.countoutcomes()
|
||||
assert tuple(res) == (1, 0, 0), res
|
||||
|
||||
|
||||
def test_syspath_prepend(mp):
|
||||
old = list(sys.path)
|
||||
mp.syspath_prepend('world')
|
||||
mp.syspath_prepend('hello')
|
||||
mp.syspath_prepend("world")
|
||||
mp.syspath_prepend("hello")
|
||||
assert sys.path[0] == "hello"
|
||||
assert sys.path[1] == "world"
|
||||
mp.undo()
|
||||
@@ -222,11 +228,11 @@ def test_syspath_prepend(mp):
|
||||
|
||||
|
||||
def test_syspath_prepend_double_undo(mp):
|
||||
mp.syspath_prepend('hello world')
|
||||
mp.syspath_prepend("hello world")
|
||||
mp.undo()
|
||||
sys.path.append('more hello world')
|
||||
sys.path.append("more hello world")
|
||||
mp.undo()
|
||||
assert sys.path[-1] == 'more hello world'
|
||||
assert sys.path[-1] == "more hello world"
|
||||
|
||||
|
||||
def test_chdir_with_path_local(mp, tmpdir):
|
||||
@@ -255,34 +261,50 @@ def test_chdir_double_undo(mp, tmpdir):
|
||||
|
||||
|
||||
def test_issue185_time_breaks(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import time
|
||||
def test_m(monkeypatch):
|
||||
def f():
|
||||
raise Exception
|
||||
monkeypatch.setattr(time, "time", f)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines("""
|
||||
result.stdout.fnmatch_lines(
|
||||
"""
|
||||
*1 passed*
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def test_importerror(testdir):
|
||||
p = testdir.mkpydir("package")
|
||||
p.join("a.py").write(textwrap.dedent("""\
|
||||
p.join("a.py").write(
|
||||
textwrap.dedent(
|
||||
"""\
|
||||
import doesnotexist
|
||||
|
||||
x = 1
|
||||
"""))
|
||||
testdir.tmpdir.join("test_importerror.py").write(textwrap.dedent("""\
|
||||
"""
|
||||
)
|
||||
)
|
||||
testdir.tmpdir.join("test_importerror.py").write(
|
||||
textwrap.dedent(
|
||||
"""\
|
||||
def test_importerror(monkeypatch):
|
||||
monkeypatch.setattr('package.a.x', 2)
|
||||
"""))
|
||||
"""
|
||||
)
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines("""
|
||||
result.stdout.fnmatch_lines(
|
||||
"""
|
||||
*import error in package.a: No module named {0}doesnotexist{0}*
|
||||
""".format("'" if sys.version_info > (3, 0) else ""))
|
||||
""".format(
|
||||
"'" if sys.version_info > (3, 0) else ""
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class SampleNew(object):
|
||||
@@ -306,14 +328,15 @@ class SampleOldInherit(SampleOld):
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.parametrize('Sample', [
|
||||
SampleNew, SampleNewInherit,
|
||||
SampleOld, SampleOldInherit,
|
||||
], ids=['new', 'new-inherit', 'old', 'old-inherit'])
|
||||
@pytest.mark.parametrize(
|
||||
"Sample",
|
||||
[SampleNew, SampleNewInherit, SampleOld, SampleOldInherit],
|
||||
ids=["new", "new-inherit", "old", "old-inherit"],
|
||||
)
|
||||
def test_issue156_undo_staticmethod(Sample):
|
||||
monkeypatch = MonkeyPatch()
|
||||
|
||||
monkeypatch.setattr(Sample, 'hello', None)
|
||||
monkeypatch.setattr(Sample, "hello", None)
|
||||
assert Sample.hello is None
|
||||
|
||||
monkeypatch.undo()
|
||||
@@ -321,10 +344,10 @@ def test_issue156_undo_staticmethod(Sample):
|
||||
|
||||
|
||||
def test_issue1338_name_resolving():
|
||||
pytest.importorskip('requests')
|
||||
pytest.importorskip("requests")
|
||||
monkeypatch = MonkeyPatch()
|
||||
try:
|
||||
monkeypatch.delattr('requests.sessions.Session.request')
|
||||
monkeypatch.delattr("requests.sessions.Session.request")
|
||||
finally:
|
||||
monkeypatch.undo()
|
||||
|
||||
|
||||
@@ -3,16 +3,19 @@ import pytest
|
||||
from _pytest import nodes
|
||||
|
||||
|
||||
@pytest.mark.parametrize("baseid, nodeid, expected", (
|
||||
('', '', True),
|
||||
('', 'foo', True),
|
||||
('', 'foo/bar', True),
|
||||
('', 'foo/bar::TestBaz::()', True),
|
||||
('foo', 'food', False),
|
||||
('foo/bar::TestBaz::()', 'foo/bar', False),
|
||||
('foo/bar::TestBaz::()', 'foo/bar::TestBop::()', False),
|
||||
('foo/bar', 'foo/bar::TestBop::()', True),
|
||||
))
|
||||
@pytest.mark.parametrize(
|
||||
"baseid, nodeid, expected",
|
||||
(
|
||||
("", "", True),
|
||||
("", "foo", True),
|
||||
("", "foo/bar", True),
|
||||
("", "foo/bar::TestBaz::()", True),
|
||||
("foo", "food", False),
|
||||
("foo/bar::TestBaz::()", "foo/bar", False),
|
||||
("foo/bar::TestBaz::()", "foo/bar::TestBop::()", False),
|
||||
("foo/bar", "foo/bar::TestBop::()", True),
|
||||
),
|
||||
)
|
||||
def test_ischildnode(baseid, nodeid, expected):
|
||||
result = nodes.ischildnode(baseid, nodeid)
|
||||
assert result is expected
|
||||
|
||||
@@ -7,7 +7,8 @@ def setup_module(mod):
|
||||
|
||||
|
||||
def test_nose_setup(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
values = []
|
||||
from nose.tools import with_setup
|
||||
|
||||
@@ -20,13 +21,15 @@ def test_nose_setup(testdir):
|
||||
|
||||
test_hello.setup = lambda: values.append(1)
|
||||
test_hello.teardown = lambda: values.append(2)
|
||||
""")
|
||||
result = testdir.runpytest(p, '-p', 'nose')
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest(p, "-p", "nose")
|
||||
result.assert_outcomes(passed=2)
|
||||
|
||||
|
||||
def test_setup_func_with_setup_decorator():
|
||||
from _pytest.nose import call_optional
|
||||
|
||||
values = []
|
||||
|
||||
class A(object):
|
||||
@@ -48,7 +51,8 @@ def test_setup_func_not_callable():
|
||||
|
||||
|
||||
def test_nose_setup_func(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
from nose.tools import with_setup
|
||||
|
||||
values = []
|
||||
@@ -70,13 +74,15 @@ def test_nose_setup_func(testdir):
|
||||
print (values)
|
||||
assert values == [1,2]
|
||||
|
||||
""")
|
||||
result = testdir.runpytest(p, '-p', 'nose')
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest(p, "-p", "nose")
|
||||
result.assert_outcomes(passed=2)
|
||||
|
||||
|
||||
def test_nose_setup_func_failure(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
from nose.tools import with_setup
|
||||
|
||||
values = []
|
||||
@@ -92,15 +98,15 @@ def test_nose_setup_func_failure(testdir):
|
||||
print (values)
|
||||
assert values == [1,2]
|
||||
|
||||
""")
|
||||
result = testdir.runpytest(p, '-p', 'nose')
|
||||
result.stdout.fnmatch_lines([
|
||||
"*TypeError: <lambda>()*"
|
||||
])
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest(p, "-p", "nose")
|
||||
result.stdout.fnmatch_lines(["*TypeError: <lambda>()*"])
|
||||
|
||||
|
||||
def test_nose_setup_func_failure_2(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
values = []
|
||||
|
||||
my_setup = 1
|
||||
@@ -111,14 +117,16 @@ def test_nose_setup_func_failure_2(testdir):
|
||||
|
||||
test_hello.setup = my_setup
|
||||
test_hello.teardown = my_teardown
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=1)
|
||||
|
||||
|
||||
def test_nose_setup_partial(testdir):
|
||||
pytest.importorskip("functools")
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
from functools import partial
|
||||
|
||||
values = []
|
||||
@@ -144,15 +152,15 @@ def test_nose_setup_partial(testdir):
|
||||
|
||||
test_hello.setup = my_setup_partial
|
||||
test_hello.teardown = my_teardown_partial
|
||||
""")
|
||||
result = testdir.runpytest(p, '-p', 'nose')
|
||||
result.stdout.fnmatch_lines([
|
||||
"*2 passed*"
|
||||
])
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest(p, "-p", "nose")
|
||||
result.stdout.fnmatch_lines(["*2 passed*"])
|
||||
|
||||
|
||||
def test_nose_test_generator_fixtures(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
# taken from nose-0.11.1 unit_tests/test_generator_fixtures.py
|
||||
from nose.tools import eq_
|
||||
called = []
|
||||
@@ -211,15 +219,15 @@ def test_nose_test_generator_fixtures(testdir):
|
||||
# expect.append('teardown')
|
||||
#expect.append('setup')
|
||||
eq_(self.called, expect)
|
||||
""")
|
||||
result = testdir.runpytest(p, '-p', 'nose')
|
||||
result.stdout.fnmatch_lines([
|
||||
"*10 passed*"
|
||||
])
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest(p, "-p", "nose")
|
||||
result.stdout.fnmatch_lines(["*10 passed*"])
|
||||
|
||||
|
||||
def test_module_level_setup(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
from nose.tools import with_setup
|
||||
items = {}
|
||||
|
||||
@@ -242,15 +250,15 @@ def test_module_level_setup(testdir):
|
||||
def test_local_setup():
|
||||
assert items[2] == 2
|
||||
assert 1 not in items
|
||||
""")
|
||||
result = testdir.runpytest('-p', 'nose')
|
||||
result.stdout.fnmatch_lines([
|
||||
"*2 passed*",
|
||||
])
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("-p", "nose")
|
||||
result.stdout.fnmatch_lines(["*2 passed*"])
|
||||
|
||||
|
||||
def test_nose_style_setup_teardown(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
values = []
|
||||
|
||||
def setup_module():
|
||||
@@ -264,15 +272,15 @@ def test_nose_style_setup_teardown(testdir):
|
||||
|
||||
def test_world():
|
||||
assert values == [1]
|
||||
""")
|
||||
result = testdir.runpytest('-p', 'nose')
|
||||
result.stdout.fnmatch_lines([
|
||||
"*2 passed*",
|
||||
])
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("-p", "nose")
|
||||
result.stdout.fnmatch_lines(["*2 passed*"])
|
||||
|
||||
|
||||
def test_nose_setup_ordering(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def setup_module(mod):
|
||||
mod.visited = True
|
||||
|
||||
@@ -281,17 +289,17 @@ def test_nose_setup_ordering(testdir):
|
||||
assert visited
|
||||
def test_first(self):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
"*1 passed*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*1 passed*"])
|
||||
|
||||
|
||||
def test_apiwrapper_problem_issue260(testdir):
|
||||
# this would end up trying a call a optional teardown on the class
|
||||
# this would end up trying a call an optional teardown on the class
|
||||
# for plain unittests we dont want nose behaviour
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
class TestCase(unittest.TestCase):
|
||||
def setup(self):
|
||||
@@ -306,7 +314,8 @@ def test_apiwrapper_problem_issue260(testdir):
|
||||
print('teardown')
|
||||
def test_fun(self):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.assert_outcomes(passed=1)
|
||||
|
||||
@@ -314,7 +323,8 @@ def test_apiwrapper_problem_issue260(testdir):
|
||||
def test_setup_teardown_linking_issue265(testdir):
|
||||
# we accidentally didnt integrate nose setupstate with normal setupstate
|
||||
# this test ensures that won't happen again
|
||||
testdir.makepyfile('''
|
||||
testdir.makepyfile(
|
||||
'''
|
||||
import pytest
|
||||
|
||||
class TestGeneric(object):
|
||||
@@ -332,51 +342,60 @@ def test_setup_teardown_linking_issue265(testdir):
|
||||
def teardown(self):
|
||||
"""Undoes the setup."""
|
||||
raise Exception("should not call teardown for skipped tests")
|
||||
''')
|
||||
'''
|
||||
)
|
||||
reprec = testdir.runpytest()
|
||||
reprec.assert_outcomes(passed=1, skipped=1)
|
||||
|
||||
|
||||
def test_SkipTest_during_collection(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import nose
|
||||
raise nose.SkipTest("during collection")
|
||||
def test_failing():
|
||||
assert False
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest(p)
|
||||
result.assert_outcomes(skipped=1)
|
||||
|
||||
|
||||
def test_SkipTest_in_test(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import nose
|
||||
|
||||
def test_skipping():
|
||||
raise nose.SkipTest("in test")
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(skipped=1)
|
||||
|
||||
|
||||
def test_istest_function_decorator(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import nose.tools
|
||||
@nose.tools.istest
|
||||
def not_test_prefix():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest(p)
|
||||
result.assert_outcomes(passed=1)
|
||||
|
||||
|
||||
def test_nottest_function_decorator(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import nose.tools
|
||||
@nose.tools.nottest
|
||||
def test_prefix():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
assert not reprec.getfailedcollections()
|
||||
calls = reprec.getreports("pytest_runtest_logreport")
|
||||
@@ -384,25 +403,29 @@ def test_nottest_function_decorator(testdir):
|
||||
|
||||
|
||||
def test_istest_class_decorator(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import nose.tools
|
||||
@nose.tools.istest
|
||||
class NotTestPrefix(object):
|
||||
def test_method(self):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest(p)
|
||||
result.assert_outcomes(passed=1)
|
||||
|
||||
|
||||
def test_nottest_class_decorator(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import nose.tools
|
||||
@nose.tools.nottest
|
||||
class TestPrefix(object):
|
||||
def test_method(self):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
assert not reprec.getfailedcollections()
|
||||
calls = reprec.getreports("pytest_runtest_logreport")
|
||||
|
||||
@@ -4,7 +4,7 @@ import sys
|
||||
import os
|
||||
import py
|
||||
import pytest
|
||||
from _pytest import config as parseopt
|
||||
from _pytest.config import argparsing as parseopt
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -23,41 +23,42 @@ class TestParser(object):
|
||||
with pytest.raises(parseopt.ArgumentError):
|
||||
# need a short or long option
|
||||
argument = parseopt.Argument()
|
||||
argument = parseopt.Argument('-t')
|
||||
assert argument._short_opts == ['-t']
|
||||
argument = parseopt.Argument("-t")
|
||||
assert argument._short_opts == ["-t"]
|
||||
assert argument._long_opts == []
|
||||
assert argument.dest == 't'
|
||||
argument = parseopt.Argument('-t', '--test')
|
||||
assert argument._short_opts == ['-t']
|
||||
assert argument._long_opts == ['--test']
|
||||
assert argument.dest == 'test'
|
||||
argument = parseopt.Argument('-t', '--test', dest='abc')
|
||||
assert argument.dest == 'abc'
|
||||
assert argument.dest == "t"
|
||||
argument = parseopt.Argument("-t", "--test")
|
||||
assert argument._short_opts == ["-t"]
|
||||
assert argument._long_opts == ["--test"]
|
||||
assert argument.dest == "test"
|
||||
argument = parseopt.Argument("-t", "--test", dest="abc")
|
||||
assert argument.dest == "abc"
|
||||
assert str(argument) == (
|
||||
"Argument(_short_opts: ['-t'], _long_opts: ['--test'], dest: 'abc')"
|
||||
)
|
||||
|
||||
def test_argument_type(self):
|
||||
argument = parseopt.Argument('-t', dest='abc', type=int)
|
||||
argument = parseopt.Argument("-t", dest="abc", type=int)
|
||||
assert argument.type is int
|
||||
argument = parseopt.Argument('-t', dest='abc', type=str)
|
||||
argument = parseopt.Argument("-t", dest="abc", type=str)
|
||||
assert argument.type is str
|
||||
argument = parseopt.Argument('-t', dest='abc', type=float)
|
||||
argument = parseopt.Argument("-t", dest="abc", type=float)
|
||||
assert argument.type is float
|
||||
with pytest.warns(DeprecationWarning):
|
||||
with pytest.raises(KeyError):
|
||||
argument = parseopt.Argument('-t', dest='abc', type='choice')
|
||||
argument = parseopt.Argument('-t', dest='abc', type=str,
|
||||
choices=['red', 'blue'])
|
||||
argument = parseopt.Argument("-t", dest="abc", type="choice")
|
||||
argument = parseopt.Argument(
|
||||
"-t", dest="abc", type=str, choices=["red", "blue"]
|
||||
)
|
||||
assert argument.type is str
|
||||
|
||||
def test_argument_processopt(self):
|
||||
argument = parseopt.Argument('-t', type=int)
|
||||
argument = parseopt.Argument("-t", type=int)
|
||||
argument.default = 42
|
||||
argument.dest = 'abc'
|
||||
argument.dest = "abc"
|
||||
res = argument.attrs()
|
||||
assert res['default'] == 42
|
||||
assert res['dest'] == 'abc'
|
||||
assert res["default"] == 42
|
||||
assert res["dest"] == "abc"
|
||||
|
||||
def test_group_add_and_get(self, parser):
|
||||
group = parser.getgroup("hello", description="desc")
|
||||
@@ -90,13 +91,16 @@ class TestParser(object):
|
||||
group.addoption("--option1", "--option-1", action="store_true")
|
||||
with pytest.raises(ValueError) as err:
|
||||
group.addoption("--option1", "--option-one", action="store_true")
|
||||
assert str(set(["--option1"])) in str(err.value)
|
||||
assert str({"--option1"}) in str(err.value)
|
||||
|
||||
def test_group_shortopt_lowercase(self, parser):
|
||||
group = parser.getgroup("hello")
|
||||
pytest.raises(ValueError, """
|
||||
pytest.raises(
|
||||
ValueError,
|
||||
"""
|
||||
group.addoption("-x", action="store_true")
|
||||
""")
|
||||
""",
|
||||
)
|
||||
assert len(group.options) == 0
|
||||
group._addoption("-x", action="store_true")
|
||||
assert len(group.options) == 1
|
||||
@@ -109,7 +113,7 @@ class TestParser(object):
|
||||
|
||||
def test_parse(self, parser):
|
||||
parser.addoption("--hello", dest="hello", action="store")
|
||||
args = parser.parse(['--hello', 'world'])
|
||||
args = parser.parse(["--hello", "world"])
|
||||
assert args.hello == "world"
|
||||
assert not getattr(args, parseopt.FILE_OR_DIR)
|
||||
|
||||
@@ -122,15 +126,16 @@ class TestParser(object):
|
||||
parser.addoption("--hello", action="store_true")
|
||||
ns = parser.parse_known_args(["x", "--y", "--hello", "this"])
|
||||
assert ns.hello
|
||||
assert ns.file_or_dir == ['x']
|
||||
assert ns.file_or_dir == ["x"]
|
||||
|
||||
def test_parse_known_and_unknown_args(self, parser):
|
||||
parser.addoption("--hello", action="store_true")
|
||||
ns, unknown = parser.parse_known_and_unknown_args(["x", "--y",
|
||||
"--hello", "this"])
|
||||
ns, unknown = parser.parse_known_and_unknown_args(
|
||||
["x", "--y", "--hello", "this"]
|
||||
)
|
||||
assert ns.hello
|
||||
assert ns.file_or_dir == ['x']
|
||||
assert unknown == ['--y', 'this']
|
||||
assert ns.file_or_dir == ["x"]
|
||||
assert unknown == ["--y", "this"]
|
||||
|
||||
def test_parse_will_set_default(self, parser):
|
||||
parser.addoption("--hello", dest="hello", default="x", action="store")
|
||||
@@ -148,38 +153,39 @@ class TestParser(object):
|
||||
pass
|
||||
|
||||
option = A()
|
||||
args = parser.parse_setoption(['--hello', 'world'], option)
|
||||
args = parser.parse_setoption(["--hello", "world"], option)
|
||||
assert option.hello == "world"
|
||||
assert option.world == 42
|
||||
assert not args
|
||||
|
||||
def test_parse_special_destination(self, parser):
|
||||
parser.addoption("--ultimate-answer", type=int)
|
||||
args = parser.parse(['--ultimate-answer', '42'])
|
||||
args = parser.parse(["--ultimate-answer", "42"])
|
||||
assert args.ultimate_answer == 42
|
||||
|
||||
def test_parse_split_positional_arguments(self, parser):
|
||||
parser.addoption("-R", action='store_true')
|
||||
parser.addoption("-S", action='store_false')
|
||||
args = parser.parse(['-R', '4', '2', '-S'])
|
||||
assert getattr(args, parseopt.FILE_OR_DIR) == ['4', '2']
|
||||
args = parser.parse(['-R', '-S', '4', '2', '-R'])
|
||||
assert getattr(args, parseopt.FILE_OR_DIR) == ['4', '2']
|
||||
parser.addoption("-R", action="store_true")
|
||||
parser.addoption("-S", action="store_false")
|
||||
args = parser.parse(["-R", "4", "2", "-S"])
|
||||
assert getattr(args, parseopt.FILE_OR_DIR) == ["4", "2"]
|
||||
args = parser.parse(["-R", "-S", "4", "2", "-R"])
|
||||
assert getattr(args, parseopt.FILE_OR_DIR) == ["4", "2"]
|
||||
assert args.R is True
|
||||
assert args.S is False
|
||||
args = parser.parse(['-R', '4', '-S', '2'])
|
||||
assert getattr(args, parseopt.FILE_OR_DIR) == ['4', '2']
|
||||
args = parser.parse(["-R", "4", "-S", "2"])
|
||||
assert getattr(args, parseopt.FILE_OR_DIR) == ["4", "2"]
|
||||
assert args.R is True
|
||||
assert args.S is False
|
||||
|
||||
def test_parse_defaultgetter(self):
|
||||
def defaultget(option):
|
||||
if not hasattr(option, 'type'):
|
||||
if not hasattr(option, "type"):
|
||||
return
|
||||
if option.type is int:
|
||||
option.default = 42
|
||||
elif option.type is str:
|
||||
option.default = "world"
|
||||
|
||||
parser = parseopt.Parser(processopt=defaultget)
|
||||
parser.addoption("--this", dest="this", type=int, action="store")
|
||||
parser.addoption("--hello", dest="hello", type=str, action="store")
|
||||
@@ -190,73 +196,82 @@ class TestParser(object):
|
||||
assert option.no is False
|
||||
|
||||
def test_drop_short_helper(self):
|
||||
parser = argparse.ArgumentParser(formatter_class=parseopt.DropShorterLongHelpFormatter)
|
||||
parser.add_argument('-t', '--twoword', '--duo', '--two-word', '--two',
|
||||
help='foo').map_long_option = {'two': 'two-word'}
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=parseopt.DropShorterLongHelpFormatter
|
||||
)
|
||||
parser.add_argument(
|
||||
"-t", "--twoword", "--duo", "--two-word", "--two", help="foo"
|
||||
).map_long_option = {"two": "two-word"}
|
||||
# throws error on --deux only!
|
||||
parser.add_argument('-d', '--deuxmots', '--deux-mots',
|
||||
action='store_true', help='foo').map_long_option = {'deux': 'deux-mots'}
|
||||
parser.add_argument('-s', action='store_true', help='single short')
|
||||
parser.add_argument('--abc', '-a',
|
||||
action='store_true', help='bar')
|
||||
parser.add_argument('--klm', '-k', '--kl-m',
|
||||
action='store_true', help='bar')
|
||||
parser.add_argument('-P', '--pq-r', '-p', '--pqr',
|
||||
action='store_true', help='bar')
|
||||
parser.add_argument('--zwei-wort', '--zweiwort', '--zweiwort',
|
||||
action='store_true', help='bar')
|
||||
parser.add_argument('-x', '--exit-on-first', '--exitfirst',
|
||||
action='store_true', help='spam').map_long_option = {'exitfirst': 'exit-on-first'}
|
||||
parser.add_argument('files_and_dirs', nargs='*')
|
||||
args = parser.parse_args(['-k', '--duo', 'hallo', '--exitfirst'])
|
||||
assert args.twoword == 'hallo'
|
||||
parser.add_argument(
|
||||
"-d", "--deuxmots", "--deux-mots", action="store_true", help="foo"
|
||||
).map_long_option = {"deux": "deux-mots"}
|
||||
parser.add_argument("-s", action="store_true", help="single short")
|
||||
parser.add_argument("--abc", "-a", action="store_true", help="bar")
|
||||
parser.add_argument("--klm", "-k", "--kl-m", action="store_true", help="bar")
|
||||
parser.add_argument(
|
||||
"-P", "--pq-r", "-p", "--pqr", action="store_true", help="bar"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--zwei-wort", "--zweiwort", "--zweiwort", action="store_true", help="bar"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-x", "--exit-on-first", "--exitfirst", action="store_true", help="spam"
|
||||
).map_long_option = {"exitfirst": "exit-on-first"}
|
||||
parser.add_argument("files_and_dirs", nargs="*")
|
||||
args = parser.parse_args(["-k", "--duo", "hallo", "--exitfirst"])
|
||||
assert args.twoword == "hallo"
|
||||
assert args.klm is True
|
||||
assert args.zwei_wort is False
|
||||
assert args.exit_on_first is True
|
||||
assert args.s is False
|
||||
args = parser.parse_args(['--deux-mots'])
|
||||
args = parser.parse_args(["--deux-mots"])
|
||||
with pytest.raises(AttributeError):
|
||||
assert args.deux_mots is True
|
||||
assert args.deuxmots is True
|
||||
args = parser.parse_args(['file', 'dir'])
|
||||
assert '|'.join(args.files_and_dirs) == 'file|dir'
|
||||
args = parser.parse_args(["file", "dir"])
|
||||
assert "|".join(args.files_and_dirs) == "file|dir"
|
||||
|
||||
def test_drop_short_0(self, parser):
|
||||
parser.addoption('--funcarg', '--func-arg', action='store_true')
|
||||
parser.addoption('--abc-def', '--abc-def', action='store_true')
|
||||
parser.addoption('--klm-hij', action='store_true')
|
||||
args = parser.parse(['--funcarg', '--k'])
|
||||
parser.addoption("--funcarg", "--func-arg", action="store_true")
|
||||
parser.addoption("--abc-def", "--abc-def", action="store_true")
|
||||
parser.addoption("--klm-hij", action="store_true")
|
||||
args = parser.parse(["--funcarg", "--k"])
|
||||
assert args.funcarg is True
|
||||
assert args.abc_def is False
|
||||
assert args.klm_hij is True
|
||||
|
||||
def test_drop_short_2(self, parser):
|
||||
parser.addoption('--func-arg', '--doit', action='store_true')
|
||||
args = parser.parse(['--doit'])
|
||||
parser.addoption("--func-arg", "--doit", action="store_true")
|
||||
args = parser.parse(["--doit"])
|
||||
assert args.func_arg is True
|
||||
|
||||
def test_drop_short_3(self, parser):
|
||||
parser.addoption('--func-arg', '--funcarg', '--doit', action='store_true')
|
||||
args = parser.parse(['abcd'])
|
||||
parser.addoption("--func-arg", "--funcarg", "--doit", action="store_true")
|
||||
args = parser.parse(["abcd"])
|
||||
assert args.func_arg is False
|
||||
assert args.file_or_dir == ['abcd']
|
||||
assert args.file_or_dir == ["abcd"]
|
||||
|
||||
def test_drop_short_help0(self, parser, capsys):
|
||||
parser.addoption('--func-args', '--doit', help='foo',
|
||||
action='store_true')
|
||||
parser.addoption("--func-args", "--doit", help="foo", action="store_true")
|
||||
parser.parse([])
|
||||
help = parser.optparser.format_help()
|
||||
assert '--func-args, --doit foo' in help
|
||||
assert "--func-args, --doit foo" in help
|
||||
|
||||
# testing would be more helpful with all help generated
|
||||
def test_drop_short_help1(self, parser, capsys):
|
||||
group = parser.getgroup("general")
|
||||
group.addoption('--doit', '--func-args', action='store_true', help='foo')
|
||||
group._addoption("-h", "--help", action="store_true", dest="help",
|
||||
help="show help message and configuration info")
|
||||
parser.parse(['-h'])
|
||||
group.addoption("--doit", "--func-args", action="store_true", help="foo")
|
||||
group._addoption(
|
||||
"-h",
|
||||
"--help",
|
||||
action="store_true",
|
||||
dest="help",
|
||||
help="show help message and configuration info",
|
||||
)
|
||||
parser.parse(["-h"])
|
||||
help = parser.optparser.format_help()
|
||||
assert '-doit, --func-args foo' in help
|
||||
assert "-doit, --func-args foo" in help
|
||||
|
||||
def test_multiple_metavar_help(self, parser):
|
||||
"""
|
||||
@@ -264,22 +279,24 @@ class TestParser(object):
|
||||
in the form "--preferences=value1 value2 value3" (#2004).
|
||||
"""
|
||||
group = parser.getgroup("general")
|
||||
group.addoption('--preferences', metavar=('value1', 'value2', 'value3'), nargs=3)
|
||||
group.addoption(
|
||||
"--preferences", metavar=("value1", "value2", "value3"), nargs=3
|
||||
)
|
||||
group._addoption("-h", "--help", action="store_true", dest="help")
|
||||
parser.parse(['-h'])
|
||||
parser.parse(["-h"])
|
||||
help = parser.optparser.format_help()
|
||||
assert '--preferences=value1 value2 value3' in help
|
||||
assert "--preferences=value1 value2 value3" in help
|
||||
|
||||
|
||||
def test_argcomplete(testdir, monkeypatch):
|
||||
if not py.path.local.sysfind('bash'):
|
||||
if not py.path.local.sysfind("bash"):
|
||||
pytest.skip("bash not available")
|
||||
script = str(testdir.tmpdir.join("test_argcomplete"))
|
||||
pytest_bin = sys.argv[0]
|
||||
if "pytest" not in os.path.basename(pytest_bin):
|
||||
pytest.skip("need to be run with pytest executable, not %s" % (pytest_bin,))
|
||||
|
||||
with open(str(script), 'w') as fp:
|
||||
with open(str(script), "w") as fp:
|
||||
# redirect output from argcomplete to stdin and stderr is not trivial
|
||||
# http://stackoverflow.com/q/12589419/1307905
|
||||
# so we use bash
|
||||
@@ -287,14 +304,14 @@ def test_argcomplete(testdir, monkeypatch):
|
||||
# alternative would be exteneded Testdir.{run(),_run(),popen()} to be able
|
||||
# to handle a keyword argument env that replaces os.environ in popen or
|
||||
# extends the copy, advantage: could not forget to restore
|
||||
monkeypatch.setenv('_ARGCOMPLETE', "1")
|
||||
monkeypatch.setenv('_ARGCOMPLETE_IFS', "\x0b")
|
||||
monkeypatch.setenv('COMP_WORDBREAKS', ' \\t\\n"\\\'><=;|&(:')
|
||||
monkeypatch.setenv("_ARGCOMPLETE", "1")
|
||||
monkeypatch.setenv("_ARGCOMPLETE_IFS", "\x0b")
|
||||
monkeypatch.setenv("COMP_WORDBREAKS", " \\t\\n\"\\'><=;|&(:")
|
||||
|
||||
arg = '--fu'
|
||||
monkeypatch.setenv('COMP_LINE', "pytest " + arg)
|
||||
monkeypatch.setenv('COMP_POINT', str(len("pytest " + arg)))
|
||||
result = testdir.run('bash', str(script), arg)
|
||||
arg = "--fu"
|
||||
monkeypatch.setenv("COMP_LINE", "pytest " + arg)
|
||||
monkeypatch.setenv("COMP_POINT", str(len("pytest " + arg)))
|
||||
result = testdir.run("bash", str(script), arg)
|
||||
if result.ret == 255:
|
||||
# argcomplete not found
|
||||
pytest.skip("argcomplete not available")
|
||||
@@ -302,9 +319,9 @@ def test_argcomplete(testdir, monkeypatch):
|
||||
pytest.skip("bash provided no output, argcomplete not available?")
|
||||
else:
|
||||
result.stdout.fnmatch_lines(["--funcargs", "--fulltrace"])
|
||||
os.mkdir('test_argcomplete.d')
|
||||
arg = 'test_argc'
|
||||
monkeypatch.setenv('COMP_LINE', "pytest " + arg)
|
||||
monkeypatch.setenv('COMP_POINT', str(len('pytest ' + arg)))
|
||||
result = testdir.run('bash', str(script), arg)
|
||||
os.mkdir("test_argcomplete.d")
|
||||
arg = "test_argc"
|
||||
monkeypatch.setenv("COMP_LINE", "pytest " + arg)
|
||||
monkeypatch.setenv("COMP_POINT", str(len("pytest " + arg)))
|
||||
result = testdir.run("bash", str(script), arg)
|
||||
result.stdout.fnmatch_lines(["test_argcomplete", "test_argcomplete.d/"])
|
||||
|
||||
@@ -5,16 +5,16 @@ import pytest
|
||||
|
||||
|
||||
class TestPasteCapture(object):
|
||||
|
||||
@pytest.fixture
|
||||
def pastebinlist(self, monkeypatch, request):
|
||||
pastebinlist = []
|
||||
plugin = request.config.pluginmanager.getplugin('pastebin')
|
||||
monkeypatch.setattr(plugin, 'create_new_paste', pastebinlist.append)
|
||||
plugin = request.config.pluginmanager.getplugin("pastebin")
|
||||
monkeypatch.setattr(plugin, "create_new_paste", pastebinlist.append)
|
||||
return pastebinlist
|
||||
|
||||
def test_failed(self, testdir, pastebinlist):
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def test_pass():
|
||||
pass
|
||||
@@ -22,7 +22,8 @@ class TestPasteCapture(object):
|
||||
assert 0
|
||||
def test_skip():
|
||||
pytest.skip("")
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(testpath, "--paste=failed")
|
||||
assert len(pastebinlist) == 1
|
||||
s = pastebinlist[0]
|
||||
@@ -31,7 +32,9 @@ class TestPasteCapture(object):
|
||||
|
||||
def test_all(self, testdir, pastebinlist):
|
||||
from _pytest.pytester import LineMatcher
|
||||
testpath = testdir.makepyfile("""
|
||||
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def test_pass():
|
||||
pass
|
||||
@@ -39,45 +42,51 @@ class TestPasteCapture(object):
|
||||
assert 0
|
||||
def test_skip():
|
||||
pytest.skip("")
|
||||
""")
|
||||
reprec = testdir.inline_run(testpath, "--pastebin=all", '-v')
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(testpath, "--pastebin=all", "-v")
|
||||
assert reprec.countoutcomes() == [1, 1, 1]
|
||||
assert len(pastebinlist) == 1
|
||||
contents = pastebinlist[0].decode('utf-8')
|
||||
contents = pastebinlist[0].decode("utf-8")
|
||||
matcher = LineMatcher(contents.splitlines())
|
||||
matcher.fnmatch_lines([
|
||||
'*test_pass PASSED*',
|
||||
'*test_fail FAILED*',
|
||||
'*test_skip SKIPPED*',
|
||||
'*== 1 failed, 1 passed, 1 skipped in *'
|
||||
])
|
||||
matcher.fnmatch_lines(
|
||||
[
|
||||
"*test_pass PASSED*",
|
||||
"*test_fail FAILED*",
|
||||
"*test_skip SKIPPED*",
|
||||
"*== 1 failed, 1 passed, 1 skipped in *",
|
||||
]
|
||||
)
|
||||
|
||||
def test_non_ascii_paste_text(self, testdir):
|
||||
"""Make sure that text which contains non-ascii characters is pasted
|
||||
correctly. See #1219.
|
||||
"""
|
||||
testdir.makepyfile(test_unicode="""
|
||||
testdir.makepyfile(
|
||||
test_unicode="""
|
||||
# encoding: utf-8
|
||||
def test():
|
||||
assert '☺' == 1
|
||||
""")
|
||||
result = testdir.runpytest('--pastebin=all')
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("--pastebin=all")
|
||||
if sys.version_info[0] == 3:
|
||||
expected_msg = "*assert '☺' == 1*"
|
||||
else:
|
||||
expected_msg = "*assert '\\xe2\\x98\\xba' == 1*"
|
||||
result.stdout.fnmatch_lines([
|
||||
expected_msg,
|
||||
"*== 1 failed in *",
|
||||
'*Sending information to Paste Service*',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
expected_msg,
|
||||
"*== 1 failed in *",
|
||||
"*Sending information to Paste Service*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class TestPaste(object):
|
||||
|
||||
@pytest.fixture
|
||||
def pastebin(self, request):
|
||||
return request.config.pluginmanager.getplugin('pastebin')
|
||||
return request.config.pluginmanager.getplugin("pastebin")
|
||||
|
||||
@pytest.fixture
|
||||
def mocked_urlopen(self, monkeypatch):
|
||||
@@ -94,24 +103,27 @@ class TestPaste(object):
|
||||
def read(self):
|
||||
# part of html of a normal response
|
||||
return b'View <a href="/raw/3c0c6750bd">raw</a>.'
|
||||
|
||||
return DummyFile()
|
||||
|
||||
if sys.version_info < (3, 0):
|
||||
import urllib
|
||||
monkeypatch.setattr(urllib, 'urlopen', mocked)
|
||||
|
||||
monkeypatch.setattr(urllib, "urlopen", mocked)
|
||||
else:
|
||||
import urllib.request
|
||||
monkeypatch.setattr(urllib.request, 'urlopen', mocked)
|
||||
|
||||
monkeypatch.setattr(urllib.request, "urlopen", mocked)
|
||||
return calls
|
||||
|
||||
def test_create_new_paste(self, pastebin, mocked_urlopen):
|
||||
result = pastebin.create_new_paste(b'full-paste-contents')
|
||||
assert result == 'https://bpaste.net/show/3c0c6750bd'
|
||||
result = pastebin.create_new_paste(b"full-paste-contents")
|
||||
assert result == "https://bpaste.net/show/3c0c6750bd"
|
||||
assert len(mocked_urlopen) == 1
|
||||
url, data = mocked_urlopen[0]
|
||||
assert type(data) is bytes
|
||||
lexer = 'python3' if sys.version_info[0] == 3 else 'python'
|
||||
assert url == 'https://bpaste.net'
|
||||
assert 'lexer=%s' % lexer in data.decode()
|
||||
assert 'code=full-paste-contents' in data.decode()
|
||||
assert 'expiry=1week' in data.decode()
|
||||
lexer = "python3" if sys.version_info[0] == 3 else "python"
|
||||
assert url == "https://bpaste.net"
|
||||
assert "lexer=%s" % lexer in data.decode()
|
||||
assert "code=full-paste-contents" in data.decode()
|
||||
assert "expiry=1week" in data.decode()
|
||||
|
||||
@@ -8,7 +8,7 @@ from _pytest.debugging import SUPPORTS_BREAKPOINT_BUILTIN
|
||||
import pytest
|
||||
|
||||
|
||||
_ENVIRON_PYTHONBREAKPOINT = os.environ.get('PYTHONBREAKPOINT', '')
|
||||
_ENVIRON_PYTHONBREAKPOINT = os.environ.get("PYTHONBREAKPOINT", "")
|
||||
|
||||
|
||||
def runpdb_and_get_report(testdir, source):
|
||||
@@ -63,7 +63,6 @@ def custom_debugger_hook():
|
||||
|
||||
|
||||
class TestPDB(object):
|
||||
|
||||
@pytest.fixture
|
||||
def pdblist(self, request):
|
||||
monkeypatch = request.getfixturevalue("monkeypatch")
|
||||
@@ -72,54 +71,79 @@ class TestPDB(object):
|
||||
def mypdb(*args):
|
||||
pdblist.append(args)
|
||||
|
||||
plugin = request.config.pluginmanager.getplugin('debugging')
|
||||
monkeypatch.setattr(plugin, 'post_mortem', mypdb)
|
||||
plugin = request.config.pluginmanager.getplugin("debugging")
|
||||
monkeypatch.setattr(plugin, "post_mortem", mypdb)
|
||||
return pdblist
|
||||
|
||||
def test_pdb_on_fail(self, testdir, pdblist):
|
||||
rep = runpdb_and_get_report(testdir, """
|
||||
rep = runpdb_and_get_report(
|
||||
testdir,
|
||||
"""
|
||||
def test_func():
|
||||
assert 0
|
||||
""")
|
||||
""",
|
||||
)
|
||||
assert rep.failed
|
||||
assert len(pdblist) == 1
|
||||
tb = _pytest._code.Traceback(pdblist[0][0])
|
||||
assert tb[-1].name == "test_func"
|
||||
|
||||
def test_pdb_on_xfail(self, testdir, pdblist):
|
||||
rep = runpdb_and_get_report(testdir, """
|
||||
rep = runpdb_and_get_report(
|
||||
testdir,
|
||||
"""
|
||||
import pytest
|
||||
@pytest.mark.xfail
|
||||
def test_func():
|
||||
assert 0
|
||||
""")
|
||||
""",
|
||||
)
|
||||
assert "xfail" in rep.keywords
|
||||
assert not pdblist
|
||||
|
||||
def test_pdb_on_skip(self, testdir, pdblist):
|
||||
rep = runpdb_and_get_report(testdir, """
|
||||
rep = runpdb_and_get_report(
|
||||
testdir,
|
||||
"""
|
||||
import pytest
|
||||
def test_func():
|
||||
pytest.skip("hello")
|
||||
""")
|
||||
""",
|
||||
)
|
||||
assert rep.skipped
|
||||
assert len(pdblist) == 0
|
||||
|
||||
def test_pdb_on_BdbQuit(self, testdir, pdblist):
|
||||
rep = runpdb_and_get_report(testdir, """
|
||||
rep = runpdb_and_get_report(
|
||||
testdir,
|
||||
"""
|
||||
import bdb
|
||||
def test_func():
|
||||
raise bdb.BdbQuit
|
||||
""")
|
||||
""",
|
||||
)
|
||||
assert rep.failed
|
||||
assert len(pdblist) == 0
|
||||
|
||||
def test_pdb_on_KeyboardInterrupt(self, testdir, pdblist):
|
||||
rep = runpdb_and_get_report(
|
||||
testdir,
|
||||
"""
|
||||
def test_func():
|
||||
raise KeyboardInterrupt
|
||||
""",
|
||||
)
|
||||
assert rep.failed
|
||||
assert len(pdblist) == 1
|
||||
|
||||
def test_pdb_interaction(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
def test_1():
|
||||
i = 0
|
||||
assert i == 1
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
||||
child.expect(".*def test_1")
|
||||
child.expect(".*i = 0")
|
||||
@@ -132,13 +156,14 @@ class TestPDB(object):
|
||||
|
||||
@staticmethod
|
||||
def flush(child):
|
||||
if platform.system() == 'Darwin':
|
||||
if platform.system() == "Darwin":
|
||||
return
|
||||
if child.isalive():
|
||||
child.wait()
|
||||
|
||||
def test_pdb_unittest_postmortem(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
class Blub(unittest.TestCase):
|
||||
def tearDown(self):
|
||||
@@ -146,36 +171,41 @@ class TestPDB(object):
|
||||
def test_false(self):
|
||||
self.filename = 'debug' + '.me'
|
||||
assert 0
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
||||
child.expect('(Pdb)')
|
||||
child.sendline('p self.filename')
|
||||
child.expect("(Pdb)")
|
||||
child.sendline("p self.filename")
|
||||
child.sendeof()
|
||||
rest = child.read().decode("utf8")
|
||||
assert 'debug.me' in rest
|
||||
assert "debug.me" in rest
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_unittest_skip(self, testdir):
|
||||
"""Test for issue #2137"""
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
@unittest.skipIf(True, 'Skipping also with pdb active')
|
||||
class MyTestCase(unittest.TestCase):
|
||||
def test_one(self):
|
||||
assert 0
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest("-rs --pdb %s" % p1)
|
||||
child.expect('Skipping also with pdb active')
|
||||
child.expect('1 skipped in')
|
||||
child.expect("Skipping also with pdb active")
|
||||
child.expect("1 skipped in")
|
||||
child.sendeof()
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_print_captured_stdout(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
def test_1():
|
||||
print("get\\x20rekt")
|
||||
assert False
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
||||
child.expect("captured stdout")
|
||||
child.expect("get rekt")
|
||||
@@ -187,12 +217,14 @@ class TestPDB(object):
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_print_captured_stderr(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
def test_1():
|
||||
import sys
|
||||
sys.stderr.write("get\\x20rekt")
|
||||
assert False
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
||||
child.expect("captured stderr")
|
||||
child.expect("get rekt")
|
||||
@@ -204,10 +236,12 @@ class TestPDB(object):
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_dont_print_empty_captured_stdout_and_stderr(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
def test_1():
|
||||
assert False
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
||||
child.expect("(Pdb)")
|
||||
output = child.before.decode("utf8")
|
||||
@@ -216,16 +250,18 @@ class TestPDB(object):
|
||||
assert "captured stderr" not in output
|
||||
self.flush(child)
|
||||
|
||||
@pytest.mark.parametrize('showcapture', ['all', 'no', 'log'])
|
||||
@pytest.mark.parametrize("showcapture", ["all", "no", "log"])
|
||||
def test_pdb_print_captured_logs(self, testdir, showcapture):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
def test_1():
|
||||
import logging
|
||||
logging.warn("get " + "rekt")
|
||||
assert False
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest("--show-capture=%s --pdb %s" % (showcapture, p1))
|
||||
if showcapture in ('all', 'log'):
|
||||
if showcapture in ("all", "log"):
|
||||
child.expect("captured log")
|
||||
child.expect("get rekt")
|
||||
child.expect("(Pdb)")
|
||||
@@ -235,14 +271,17 @@ class TestPDB(object):
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_print_captured_logs_nologging(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
def test_1():
|
||||
import logging
|
||||
logging.warn("get " + "rekt")
|
||||
assert False
|
||||
""")
|
||||
child = testdir.spawn_pytest("--show-capture=all --pdb "
|
||||
"-p no:logging %s" % p1)
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest(
|
||||
"--show-capture=all --pdb " "-p no:logging %s" % p1
|
||||
)
|
||||
child.expect("get rekt")
|
||||
output = child.before.decode("utf8")
|
||||
assert "captured log" not in output
|
||||
@@ -253,13 +292,15 @@ class TestPDB(object):
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_interaction_exception(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def globalfunc():
|
||||
pass
|
||||
def test_1():
|
||||
pytest.raises(ValueError, globalfunc)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
||||
child.expect(".*def test_1")
|
||||
child.expect(".*pytest.raises.*globalfunc")
|
||||
@@ -271,10 +312,12 @@ class TestPDB(object):
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_interaction_on_collection_issue181(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
xxx
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
||||
# child.expect(".*import pytest.*")
|
||||
child.expect("(Pdb)")
|
||||
@@ -283,10 +326,12 @@ class TestPDB(object):
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_interaction_on_internal_error(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
def pytest_runtest_protocol():
|
||||
0/0
|
||||
""")
|
||||
"""
|
||||
)
|
||||
p1 = testdir.makepyfile("def test_func(): pass")
|
||||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
||||
# child.expect(".*import pytest.*")
|
||||
@@ -295,14 +340,16 @@ class TestPDB(object):
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_interaction_capturing_simple(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def test_1():
|
||||
i = 0
|
||||
print ("hello17")
|
||||
pytest.set_trace()
|
||||
x = 3
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest(str(p1))
|
||||
child.expect("test_1")
|
||||
child.expect("x = 3")
|
||||
@@ -315,11 +362,13 @@ class TestPDB(object):
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_set_trace_interception(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
import pdb
|
||||
def test_1():
|
||||
pdb.set_trace()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest(str(p1))
|
||||
child.expect("test_1")
|
||||
child.expect("(Pdb)")
|
||||
@@ -330,12 +379,14 @@ class TestPDB(object):
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_and_capsys(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def test_1(capsys):
|
||||
print ("hello1")
|
||||
pytest.set_trace()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest(str(p1))
|
||||
child.expect("test_1")
|
||||
child.send("capsys.readouterr()\n")
|
||||
@@ -345,14 +396,16 @@ class TestPDB(object):
|
||||
self.flush(child)
|
||||
|
||||
def test_set_trace_capturing_afterwards(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
import pdb
|
||||
def test_1():
|
||||
pdb.set_trace()
|
||||
def test_2():
|
||||
print ("hello")
|
||||
assert 0
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest(str(p1))
|
||||
child.expect("test_1")
|
||||
child.send("c\n")
|
||||
@@ -364,17 +417,19 @@ class TestPDB(object):
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_interaction_doctest(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def function_1():
|
||||
'''
|
||||
>>> i = 0
|
||||
>>> assert i == 1
|
||||
'''
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest("--doctest-modules --pdb %s" % p1)
|
||||
child.expect("(Pdb)")
|
||||
child.sendline('i')
|
||||
child.sendline("i")
|
||||
child.expect("0")
|
||||
child.expect("(Pdb)")
|
||||
child.sendeof()
|
||||
@@ -383,7 +438,8 @@ class TestPDB(object):
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_interaction_capturing_twice(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def test_1():
|
||||
i = 0
|
||||
@@ -393,12 +449,13 @@ class TestPDB(object):
|
||||
print ("hello18")
|
||||
pytest.set_trace()
|
||||
x = 4
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest(str(p1))
|
||||
child.expect("test_1")
|
||||
child.expect("x = 3")
|
||||
child.expect("(Pdb)")
|
||||
child.sendline('c')
|
||||
child.sendline("c")
|
||||
child.expect("x = 4")
|
||||
child.sendeof()
|
||||
rest = child.read().decode("utf8")
|
||||
@@ -409,25 +466,29 @@ class TestPDB(object):
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_used_outside_test(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
pytest.set_trace()
|
||||
x = 5
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn("%s %s" % (sys.executable, p1))
|
||||
child.expect("x = 5")
|
||||
child.sendeof()
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_used_in_generate_tests(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def pytest_generate_tests(metafunc):
|
||||
pytest.set_trace()
|
||||
x = 5
|
||||
def test_foo(a):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest(str(p1))
|
||||
child.expect("x = 5")
|
||||
child.sendeof()
|
||||
@@ -436,73 +497,69 @@ class TestPDB(object):
|
||||
def test_pdb_collection_failure_is_shown(self, testdir):
|
||||
p1 = testdir.makepyfile("xxx")
|
||||
result = testdir.runpytest_subprocess("--pdb", p1)
|
||||
result.stdout.fnmatch_lines([
|
||||
"*NameError*xxx*",
|
||||
"*1 error*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*NameError*xxx*", "*1 error*"])
|
||||
|
||||
def test_enter_pdb_hook_is_called(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
def pytest_enter_pdb(config):
|
||||
assert config.testing_verification == 'configured'
|
||||
print 'enter_pdb_hook'
|
||||
|
||||
def pytest_configure(config):
|
||||
config.testing_verification = 'configured'
|
||||
""")
|
||||
p1 = testdir.makepyfile("""
|
||||
"""
|
||||
)
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
|
||||
def test_foo():
|
||||
pytest.set_trace()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest(str(p1))
|
||||
child.expect("enter_pdb_hook")
|
||||
child.send('c\n')
|
||||
child.send("c\n")
|
||||
child.sendeof()
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_custom_cls(self, testdir, custom_pdb_calls):
|
||||
p1 = testdir.makepyfile("""xxx """)
|
||||
result = testdir.runpytest_inprocess(
|
||||
"--pdb", "--pdbcls=_pytest:_CustomPdb", p1)
|
||||
result.stdout.fnmatch_lines([
|
||||
"*NameError*xxx*",
|
||||
"*1 error*",
|
||||
])
|
||||
result = testdir.runpytest_inprocess("--pdb", "--pdbcls=_pytest:_CustomPdb", p1)
|
||||
result.stdout.fnmatch_lines(["*NameError*xxx*", "*1 error*"])
|
||||
assert custom_pdb_calls == ["init", "reset", "interaction"]
|
||||
|
||||
def test_pdb_custom_cls_without_pdb(self, testdir, custom_pdb_calls):
|
||||
p1 = testdir.makepyfile("""xxx """)
|
||||
result = testdir.runpytest_inprocess(
|
||||
"--pdbcls=_pytest:_CustomPdb", p1)
|
||||
result.stdout.fnmatch_lines([
|
||||
"*NameError*xxx*",
|
||||
"*1 error*",
|
||||
])
|
||||
result = testdir.runpytest_inprocess("--pdbcls=_pytest:_CustomPdb", p1)
|
||||
result.stdout.fnmatch_lines(["*NameError*xxx*", "*1 error*"])
|
||||
assert custom_pdb_calls == []
|
||||
|
||||
def test_pdb_custom_cls_with_settrace(self, testdir, monkeypatch):
|
||||
testdir.makepyfile(custom_pdb="""
|
||||
testdir.makepyfile(
|
||||
custom_pdb="""
|
||||
class CustomPdb(object):
|
||||
def set_trace(*args, **kwargs):
|
||||
print 'custom set_trace>'
|
||||
""")
|
||||
p1 = testdir.makepyfile("""
|
||||
"""
|
||||
)
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
|
||||
def test_foo():
|
||||
pytest.set_trace()
|
||||
""")
|
||||
monkeypatch.setenv('PYTHONPATH', str(testdir.tmpdir))
|
||||
"""
|
||||
)
|
||||
monkeypatch.setenv("PYTHONPATH", str(testdir.tmpdir))
|
||||
child = testdir.spawn_pytest("--pdbcls=custom_pdb:CustomPdb %s" % str(p1))
|
||||
|
||||
child.expect('custom set_trace>')
|
||||
child.expect("custom set_trace>")
|
||||
self.flush(child)
|
||||
|
||||
|
||||
class TestDebuggingBreakpoints(object):
|
||||
|
||||
def test_supports_breakpoint_module_global(self):
|
||||
"""
|
||||
Test that supports breakpoint global marks on Python 3.7+ and not on
|
||||
@@ -515,14 +572,17 @@ class TestDebuggingBreakpoints(object):
|
||||
if sys.version_info.major == 2 and sys.version_info.minor == 7:
|
||||
assert SUPPORTS_BREAKPOINT_BUILTIN is False
|
||||
|
||||
@pytest.mark.skipif(not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin")
|
||||
@pytest.mark.parametrize('arg', ['--pdb', ''])
|
||||
@pytest.mark.skipif(
|
||||
not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin"
|
||||
)
|
||||
@pytest.mark.parametrize("arg", ["--pdb", ""])
|
||||
def test_sys_breakpointhook_configure_and_unconfigure(self, testdir, arg):
|
||||
"""
|
||||
Test that sys.breakpointhook is set to the custom Pdb class once configured, test that
|
||||
hook is reset to system value once pytest has been unconfigured
|
||||
"""
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import sys
|
||||
from pytest import hookimpl
|
||||
from _pytest.debugging import pytestPDB
|
||||
@@ -535,34 +595,40 @@ class TestDebuggingBreakpoints(object):
|
||||
|
||||
def test_check():
|
||||
assert sys.breakpointhook == pytestPDB.set_trace
|
||||
""")
|
||||
testdir.makepyfile("""
|
||||
"""
|
||||
)
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_nothing(): pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
args = (arg,) if arg else ()
|
||||
result = testdir.runpytest_subprocess(*args)
|
||||
result.stdout.fnmatch_lines([
|
||||
'*1 passed in *',
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*1 passed in *"])
|
||||
|
||||
@pytest.mark.skipif(not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin")
|
||||
@pytest.mark.skipif(
|
||||
not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin"
|
||||
)
|
||||
def test_pdb_custom_cls(self, testdir, custom_debugger_hook):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
def test_nothing():
|
||||
breakpoint()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest_inprocess(
|
||||
"--pdb", "--pdbcls=_pytest:_CustomDebugger", p1)
|
||||
result.stdout.fnmatch_lines([
|
||||
"*CustomDebugger*",
|
||||
"*1 passed*",
|
||||
])
|
||||
"--pdb", "--pdbcls=_pytest:_CustomDebugger", p1
|
||||
)
|
||||
result.stdout.fnmatch_lines(["*CustomDebugger*", "*1 passed*"])
|
||||
assert custom_debugger_hook == ["init", "set_trace"]
|
||||
|
||||
@pytest.mark.parametrize('arg', ['--pdb', ''])
|
||||
@pytest.mark.skipif(not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin")
|
||||
@pytest.mark.parametrize("arg", ["--pdb", ""])
|
||||
@pytest.mark.skipif(
|
||||
not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin"
|
||||
)
|
||||
def test_environ_custom_class(self, testdir, custom_debugger_hook, arg):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
||||
@@ -577,23 +643,31 @@ class TestDebuggingBreakpoints(object):
|
||||
def test_check():
|
||||
import _pytest
|
||||
assert sys.breakpointhook is _pytest._CustomDebugger.set_trace
|
||||
""")
|
||||
testdir.makepyfile("""
|
||||
"""
|
||||
)
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_nothing(): pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
args = (arg,) if arg else ()
|
||||
result = testdir.runpytest_subprocess(*args)
|
||||
result.stdout.fnmatch_lines([
|
||||
'*1 passed in *',
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*1 passed in *"])
|
||||
|
||||
@pytest.mark.skipif(not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin")
|
||||
@pytest.mark.skipif(not _ENVIRON_PYTHONBREAKPOINT == '', reason="Requires breakpoint() default value")
|
||||
@pytest.mark.skipif(
|
||||
not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin"
|
||||
)
|
||||
@pytest.mark.skipif(
|
||||
not _ENVIRON_PYTHONBREAKPOINT == "",
|
||||
reason="Requires breakpoint() default value",
|
||||
)
|
||||
def test_sys_breakpoint_interception(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
def test_1():
|
||||
breakpoint()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest(str(p1))
|
||||
child.expect("test_1")
|
||||
child.expect("(Pdb)")
|
||||
@@ -603,13 +677,17 @@ class TestDebuggingBreakpoints(object):
|
||||
assert "reading from stdin while output" not in rest
|
||||
TestPDB.flush(child)
|
||||
|
||||
@pytest.mark.skipif(not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin")
|
||||
@pytest.mark.skipif(
|
||||
not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin"
|
||||
)
|
||||
def test_pdb_not_altered(self, testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
import pdb
|
||||
def test_1():
|
||||
pdb.set_trace()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest(str(p1))
|
||||
child.expect("test_1")
|
||||
child.expect("(Pdb)")
|
||||
|
||||
@@ -17,71 +17,84 @@ def pytestpm():
|
||||
|
||||
class TestPytestPluginInteractions(object):
|
||||
def test_addhooks_conftestplugin(self, testdir):
|
||||
testdir.makepyfile(newhooks="""
|
||||
testdir.makepyfile(
|
||||
newhooks="""
|
||||
def pytest_myhook(xyz):
|
||||
"new hook"
|
||||
""")
|
||||
conf = testdir.makeconftest("""
|
||||
"""
|
||||
)
|
||||
conf = testdir.makeconftest(
|
||||
"""
|
||||
import sys ; sys.path.insert(0, '.')
|
||||
import newhooks
|
||||
def pytest_addhooks(pluginmanager):
|
||||
pluginmanager.addhooks(newhooks)
|
||||
def pytest_myhook(xyz):
|
||||
return xyz + 1
|
||||
""")
|
||||
"""
|
||||
)
|
||||
config = get_config()
|
||||
pm = config.pluginmanager
|
||||
pm.hook.pytest_addhooks.call_historic(
|
||||
kwargs=dict(pluginmanager=config.pluginmanager))
|
||||
kwargs=dict(pluginmanager=config.pluginmanager)
|
||||
)
|
||||
config.pluginmanager._importconftest(conf)
|
||||
# print(config.pluginmanager.get_plugins())
|
||||
res = config.hook.pytest_myhook(xyz=10)
|
||||
assert res == [11]
|
||||
|
||||
def test_addhooks_nohooks(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import sys
|
||||
def pytest_addhooks(pluginmanager):
|
||||
pluginmanager.addhooks(sys)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
res = testdir.runpytest()
|
||||
assert res.ret != 0
|
||||
res.stderr.fnmatch_lines([
|
||||
"*did not find*sys*"
|
||||
])
|
||||
res.stderr.fnmatch_lines(["*did not find*sys*"])
|
||||
|
||||
def test_namespace_early_from_import(self, testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
from pytest import Item
|
||||
from pytest import Item as Item2
|
||||
assert Item is Item2
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpython(p)
|
||||
assert result.ret == 0
|
||||
|
||||
def test_do_ext_namespace(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
def pytest_namespace():
|
||||
return {'hello': 'world'}
|
||||
""")
|
||||
p = testdir.makepyfile("""
|
||||
"""
|
||||
)
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
from pytest import hello
|
||||
import pytest
|
||||
def test_hello():
|
||||
assert hello == "world"
|
||||
assert 'hello' in pytest.__all__
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(p)
|
||||
reprec.assertoutcome(passed=1)
|
||||
|
||||
def test_do_option_postinitialize(self, testdir):
|
||||
config = testdir.parseconfigure()
|
||||
assert not hasattr(config.option, 'test123')
|
||||
p = testdir.makepyfile("""
|
||||
assert not hasattr(config.option, "test123")
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption('--test123', action="store_true",
|
||||
default=True)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
config.pluginmanager._importconftest(p)
|
||||
assert config.option.test123
|
||||
|
||||
@@ -127,8 +140,8 @@ class TestPytestPluginInteractions(object):
|
||||
pytestpm.register(p)
|
||||
assert pytestpm.trace.root.indent == indent
|
||||
assert len(values) >= 2
|
||||
assert 'pytest_plugin_registered' in values[0]
|
||||
assert 'finish' in values[1]
|
||||
assert "pytest_plugin_registered" in values[0]
|
||||
assert "finish" in values[1]
|
||||
|
||||
values[:] = []
|
||||
with pytest.raises(ValueError):
|
||||
@@ -142,19 +155,16 @@ class TestPytestPluginInteractions(object):
|
||||
"""Test the gethookproxy function(#2016)"""
|
||||
config = testdir.parseconfig()
|
||||
session = Session(config)
|
||||
testdir.makepyfile(**{
|
||||
'tests/conftest.py': '',
|
||||
'tests/subdir/conftest.py': '',
|
||||
})
|
||||
testdir.makepyfile(**{"tests/conftest.py": "", "tests/subdir/conftest.py": ""})
|
||||
|
||||
conftest1 = testdir.tmpdir.join('tests/conftest.py')
|
||||
conftest2 = testdir.tmpdir.join('tests/subdir/conftest.py')
|
||||
conftest1 = testdir.tmpdir.join("tests/conftest.py")
|
||||
conftest2 = testdir.tmpdir.join("tests/subdir/conftest.py")
|
||||
|
||||
config.pluginmanager._importconftest(conftest1)
|
||||
ihook_a = session.gethookproxy(testdir.tmpdir.join('tests'))
|
||||
ihook_a = session.gethookproxy(testdir.tmpdir.join("tests"))
|
||||
assert ihook_a is not None
|
||||
config.pluginmanager._importconftest(conftest2)
|
||||
ihook_b = session.gethookproxy(testdir.tmpdir.join('tests'))
|
||||
ihook_b = session.gethookproxy(testdir.tmpdir.join("tests"))
|
||||
assert ihook_a is not ihook_b
|
||||
|
||||
def test_warn_on_deprecated_addhooks(self, pytestpm):
|
||||
@@ -176,20 +186,19 @@ class TestPytestPluginInteractions(object):
|
||||
|
||||
|
||||
def test_namespace_has_default_and_env_plugins(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
pytest.mark
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpython(p)
|
||||
assert result.ret == 0
|
||||
|
||||
|
||||
def test_default_markers(testdir):
|
||||
result = testdir.runpytest("--markers")
|
||||
result.stdout.fnmatch_lines([
|
||||
"*tryfirst*first*",
|
||||
"*trylast*last*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*tryfirst*first*", "*trylast*last*"])
|
||||
|
||||
|
||||
def test_importplugin_error_message(testdir, pytestpm):
|
||||
@@ -199,12 +208,14 @@ def test_importplugin_error_message(testdir, pytestpm):
|
||||
See #375 and #1998.
|
||||
"""
|
||||
testdir.syspathinsert(testdir.tmpdir)
|
||||
testdir.makepyfile(qwe="""
|
||||
testdir.makepyfile(
|
||||
qwe="""
|
||||
# encoding: UTF-8
|
||||
def test_traceback():
|
||||
raise ImportError(u'Not possible to import: ☺')
|
||||
test_traceback()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
with pytest.raises(ImportError) as excinfo:
|
||||
pytestpm.import_plugin("qwe")
|
||||
|
||||
@@ -229,10 +240,10 @@ class TestPytestPluginManager(object):
|
||||
|
||||
def test_canonical_import(self, monkeypatch):
|
||||
mod = types.ModuleType("pytest_xyz")
|
||||
monkeypatch.setitem(sys.modules, 'pytest_xyz', mod)
|
||||
monkeypatch.setitem(sys.modules, "pytest_xyz", mod)
|
||||
pm = PytestPluginManager()
|
||||
pm.import_plugin('pytest_xyz')
|
||||
assert pm.get_plugin('pytest_xyz') == mod
|
||||
pm.import_plugin("pytest_xyz")
|
||||
assert pm.get_plugin("pytest_xyz") == mod
|
||||
assert pm.is_registered(mod)
|
||||
|
||||
def test_consider_module(self, testdir, pytestpm):
|
||||
@@ -263,46 +274,49 @@ class TestPytestPluginManager(object):
|
||||
assert len(values) == 1
|
||||
|
||||
def test_consider_env_fails_to_import(self, monkeypatch, pytestpm):
|
||||
monkeypatch.setenv('PYTEST_PLUGINS', 'nonexisting', prepend=",")
|
||||
monkeypatch.setenv("PYTEST_PLUGINS", "nonexisting", prepend=",")
|
||||
with pytest.raises(ImportError):
|
||||
pytestpm.consider_env()
|
||||
|
||||
def test_plugin_skip(self, testdir, monkeypatch):
|
||||
p = testdir.makepyfile(skipping1="""
|
||||
p = testdir.makepyfile(
|
||||
skipping1="""
|
||||
import pytest
|
||||
pytest.skip("hello")
|
||||
""")
|
||||
"""
|
||||
)
|
||||
p.copy(p.dirpath("skipping2.py"))
|
||||
monkeypatch.setenv("PYTEST_PLUGINS", "skipping2")
|
||||
result = testdir.runpytest("-rw", "-p", "skipping1", syspathinsert=True)
|
||||
assert result.ret == EXIT_NOTESTSCOLLECTED
|
||||
result.stdout.fnmatch_lines([
|
||||
"*skipped plugin*skipping1*hello*",
|
||||
"*skipped plugin*skipping2*hello*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
["*skipped plugin*skipping1*hello*", "*skipped plugin*skipping2*hello*"]
|
||||
)
|
||||
|
||||
def test_consider_env_plugin_instantiation(self, testdir, monkeypatch, pytestpm):
|
||||
testdir.syspathinsert()
|
||||
testdir.makepyfile(xy123="#")
|
||||
monkeypatch.setitem(os.environ, 'PYTEST_PLUGINS', 'xy123')
|
||||
monkeypatch.setitem(os.environ, "PYTEST_PLUGINS", "xy123")
|
||||
l1 = len(pytestpm.get_plugins())
|
||||
pytestpm.consider_env()
|
||||
l2 = len(pytestpm.get_plugins())
|
||||
assert l2 == l1 + 1
|
||||
assert pytestpm.get_plugin('xy123')
|
||||
assert pytestpm.get_plugin("xy123")
|
||||
pytestpm.consider_env()
|
||||
l3 = len(pytestpm.get_plugins())
|
||||
assert l2 == l3
|
||||
|
||||
def test_pluginmanager_ENV_startup(self, testdir, monkeypatch):
|
||||
testdir.makepyfile(pytest_x500="#")
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def test_hello(pytestconfig):
|
||||
plugin = pytestconfig.pluginmanager.get_plugin('pytest_x500')
|
||||
assert plugin is not None
|
||||
""")
|
||||
monkeypatch.setenv('PYTEST_PLUGINS', 'pytest_x500', prepend=",")
|
||||
"""
|
||||
)
|
||||
monkeypatch.setenv("PYTEST_PLUGINS", "pytest_x500", prepend=",")
|
||||
result = testdir.runpytest(p, syspathinsert=True)
|
||||
assert result.ret == 0
|
||||
result.stdout.fnmatch_lines(["*1 passed*"])
|
||||
@@ -320,7 +334,7 @@ class TestPytestPluginManager(object):
|
||||
len2 = len(pytestpm.get_plugins())
|
||||
assert len1 == len2
|
||||
plugin1 = pytestpm.get_plugin("pytest_hello")
|
||||
assert plugin1.__name__.endswith('pytest_hello')
|
||||
assert plugin1.__name__.endswith("pytest_hello")
|
||||
plugin2 = pytestpm.get_plugin("pytest_hello")
|
||||
assert plugin2 is plugin1
|
||||
|
||||
@@ -343,8 +357,9 @@ class TestPytestPluginManager(object):
|
||||
|
||||
class TestPytestPluginManagerBootstrapming(object):
|
||||
def test_preparse_args(self, pytestpm):
|
||||
pytest.raises(ImportError, lambda:
|
||||
pytestpm.consider_preparse(["xyz", "-p", "hello123"]))
|
||||
pytest.raises(
|
||||
ImportError, lambda: pytestpm.consider_preparse(["xyz", "-p", "hello123"])
|
||||
)
|
||||
|
||||
def test_plugin_prevent_register(self, pytestpm):
|
||||
pytestpm.consider_preparse(["xyz", "-p", "no:abc"])
|
||||
|
||||
@@ -37,6 +37,7 @@ def test_make_hook_recorder(testdir):
|
||||
failed = False
|
||||
skipped = True
|
||||
when = "call"
|
||||
|
||||
rep.passed = False
|
||||
rep.skipped = True
|
||||
recorder.hook.pytest_runtest_logreport(report=rep)
|
||||
@@ -71,11 +72,13 @@ def test_parseconfig(testdir):
|
||||
|
||||
|
||||
def test_testdir_runs_with_plugin(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
pytest_plugins = "pytester"
|
||||
def test_hello(testdir):
|
||||
assert 1
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.assert_outcomes(passed=1)
|
||||
|
||||
@@ -88,7 +91,7 @@ def make_holder():
|
||||
def pytest_xyz_noarg(self):
|
||||
"x"
|
||||
|
||||
apimod = type(os)('api')
|
||||
apimod = type(os)("api")
|
||||
|
||||
def pytest_xyz(arg):
|
||||
"x"
|
||||
@@ -130,9 +133,11 @@ def test_makepyfile_utf8(testdir):
|
||||
utf8_contents = u"""
|
||||
def setup_function(function):
|
||||
mixed_encoding = u'São Paulo'
|
||||
""".encode('utf-8')
|
||||
""".encode(
|
||||
"utf-8"
|
||||
)
|
||||
p = testdir.makepyfile(utf8_contents)
|
||||
assert u"mixed_encoding = u'São Paulo'".encode('utf-8') in p.read('rb')
|
||||
assert u"mixed_encoding = u'São Paulo'".encode("utf-8") in p.read("rb")
|
||||
|
||||
|
||||
class TestInlineRunModulesCleanup(object):
|
||||
@@ -158,19 +163,23 @@ class TestInlineRunModulesCleanup(object):
|
||||
def restore(self):
|
||||
self._spy_restore_count += 1
|
||||
return self.__snapshot.restore()
|
||||
|
||||
return SysModulesSnapshotSpy
|
||||
|
||||
def test_inline_run_taking_and_restoring_a_sys_modules_snapshot(
|
||||
self, testdir, monkeypatch):
|
||||
self, testdir, monkeypatch
|
||||
):
|
||||
spy_factory = self.spy_factory()
|
||||
monkeypatch.setattr(pytester, "SysModulesSnapshot", spy_factory)
|
||||
original = dict(sys.modules)
|
||||
testdir.syspathinsert()
|
||||
testdir.makepyfile(import1="# you son of a silly person")
|
||||
testdir.makepyfile(import2="# my hovercraft is full of eels")
|
||||
test_mod = testdir.makepyfile("""
|
||||
test_mod = testdir.makepyfile(
|
||||
"""
|
||||
import import1
|
||||
def test_foo(): import import2""")
|
||||
def test_foo(): import import2"""
|
||||
)
|
||||
testdir.inline_run(str(test_mod))
|
||||
assert len(spy_factory.instances) == 1
|
||||
spy = spy_factory.instances[0]
|
||||
@@ -179,7 +188,8 @@ class TestInlineRunModulesCleanup(object):
|
||||
assert all(sys.modules[x] is original[x] for x in sys.modules)
|
||||
|
||||
def test_inline_run_sys_modules_snapshot_restore_preserving_modules(
|
||||
self, testdir, monkeypatch):
|
||||
self, testdir, monkeypatch
|
||||
):
|
||||
spy_factory = self.spy_factory()
|
||||
monkeypatch.setattr(pytester, "SysModulesSnapshot", spy_factory)
|
||||
test_mod = testdir.makepyfile("def test_foo(): pass")
|
||||
@@ -194,10 +204,13 @@ class TestInlineRunModulesCleanup(object):
|
||||
testdir.syspathinsert()
|
||||
testdir.makepyfile(imported="data = 'you son of a silly person'")
|
||||
import imported
|
||||
test_mod = testdir.makepyfile("""
|
||||
|
||||
test_mod = testdir.makepyfile(
|
||||
"""
|
||||
def test_foo():
|
||||
import imported
|
||||
imported.data = 42""")
|
||||
imported.data = 42"""
|
||||
)
|
||||
testdir.inline_run(str(test_mod))
|
||||
assert imported.data == 42
|
||||
|
||||
@@ -211,13 +224,17 @@ def test_inline_run_clean_sys_paths(testdir):
|
||||
sys.meta_path.append(test_path1)
|
||||
original_path = list(sys.path)
|
||||
original_meta_path = list(sys.meta_path)
|
||||
test_mod = testdir.makepyfile("""
|
||||
test_mod = testdir.makepyfile(
|
||||
"""
|
||||
import sys
|
||||
sys.path.append({:test_path2})
|
||||
sys.meta_path.append({:test_path2})
|
||||
def test_foo():
|
||||
sys.path.append({:test_path3})
|
||||
sys.meta_path.append({:test_path3})""".format(locals()))
|
||||
sys.meta_path.append({:test_path3})""".format(
|
||||
locals()
|
||||
)
|
||||
)
|
||||
testdir.inline_run(str(test_mod))
|
||||
assert sys.path == original_path
|
||||
assert sys.meta_path == original_meta_path
|
||||
@@ -234,10 +251,12 @@ def test_inline_run_clean_sys_paths(testdir):
|
||||
def restore(self):
|
||||
self._spy_restore_count += 1
|
||||
return self.__snapshot.restore()
|
||||
|
||||
return SysPathsSnapshotSpy
|
||||
|
||||
def test_inline_run_taking_and_restoring_a_sys_paths_snapshot(
|
||||
self, testdir, monkeypatch):
|
||||
self, testdir, monkeypatch
|
||||
):
|
||||
spy_factory = self.spy_factory()
|
||||
monkeypatch.setattr(pytester, "SysPathsSnapshot", spy_factory)
|
||||
test_mod = testdir.makepyfile("def test_foo(): pass")
|
||||
@@ -250,14 +269,14 @@ def test_inline_run_clean_sys_paths(testdir):
|
||||
def test_assert_outcomes_after_pytest_error(testdir):
|
||||
testdir.makepyfile("def test_foo(): assert True")
|
||||
|
||||
result = testdir.runpytest('--unexpected-argument')
|
||||
result = testdir.runpytest("--unexpected-argument")
|
||||
with pytest.raises(ValueError, message="Pytest terminal report not found"):
|
||||
result.assert_outcomes(passed=0)
|
||||
|
||||
|
||||
def test_cwd_snapshot(tmpdir):
|
||||
foo = tmpdir.ensure('foo', dir=1)
|
||||
bar = tmpdir.ensure('bar', dir=1)
|
||||
foo = tmpdir.ensure("foo", dir=1)
|
||||
bar = tmpdir.ensure("bar", dir=1)
|
||||
foo.chdir()
|
||||
snapshot = CwdSnapshot()
|
||||
bar.chdir()
|
||||
@@ -267,20 +286,20 @@ def test_cwd_snapshot(tmpdir):
|
||||
|
||||
|
||||
class TestSysModulesSnapshot(object):
|
||||
key = 'my-test-module'
|
||||
key = "my-test-module"
|
||||
|
||||
def test_remove_added(self):
|
||||
original = dict(sys.modules)
|
||||
assert self.key not in sys.modules
|
||||
snapshot = SysModulesSnapshot()
|
||||
sys.modules[self.key] = 'something'
|
||||
sys.modules[self.key] = "something"
|
||||
assert self.key in sys.modules
|
||||
snapshot.restore()
|
||||
assert sys.modules == original
|
||||
|
||||
def test_add_removed(self, monkeypatch):
|
||||
assert self.key not in sys.modules
|
||||
monkeypatch.setitem(sys.modules, self.key, 'something')
|
||||
monkeypatch.setitem(sys.modules, self.key, "something")
|
||||
assert self.key in sys.modules
|
||||
original = dict(sys.modules)
|
||||
snapshot = SysModulesSnapshot()
|
||||
@@ -291,11 +310,11 @@ class TestSysModulesSnapshot(object):
|
||||
|
||||
def test_restore_reloaded(self, monkeypatch):
|
||||
assert self.key not in sys.modules
|
||||
monkeypatch.setitem(sys.modules, self.key, 'something')
|
||||
monkeypatch.setitem(sys.modules, self.key, "something")
|
||||
assert self.key in sys.modules
|
||||
original = dict(sys.modules)
|
||||
snapshot = SysModulesSnapshot()
|
||||
sys.modules[self.key] = 'something else'
|
||||
sys.modules[self.key] = "something else"
|
||||
snapshot.restore()
|
||||
assert sys.modules == original
|
||||
|
||||
@@ -303,16 +322,16 @@ class TestSysModulesSnapshot(object):
|
||||
key = [self.key + str(i) for i in range(3)]
|
||||
assert not any(k in sys.modules for k in key)
|
||||
for i, k in enumerate(key):
|
||||
monkeypatch.setitem(sys.modules, k, 'something' + str(i))
|
||||
monkeypatch.setitem(sys.modules, k, "something" + str(i))
|
||||
original = dict(sys.modules)
|
||||
|
||||
def preserve(name):
|
||||
return name in (key[0], key[1], 'some-other-key')
|
||||
return name in (key[0], key[1], "some-other-key")
|
||||
|
||||
snapshot = SysModulesSnapshot(preserve=preserve)
|
||||
sys.modules[key[0]] = original[key[0]] = 'something else0'
|
||||
sys.modules[key[1]] = original[key[1]] = 'something else1'
|
||||
sys.modules[key[2]] = 'something else2'
|
||||
sys.modules[key[0]] = original[key[0]] = "something else0"
|
||||
sys.modules[key[1]] = original[key[1]] = "something else1"
|
||||
sys.modules[key[2]] = "something else2"
|
||||
snapshot.restore()
|
||||
assert sys.modules == original
|
||||
|
||||
@@ -320,23 +339,21 @@ class TestSysModulesSnapshot(object):
|
||||
original = dict(sys.modules)
|
||||
assert self.key not in original
|
||||
replacement = dict(sys.modules)
|
||||
replacement[self.key] = 'life of brian'
|
||||
replacement[self.key] = "life of brian"
|
||||
snapshot = SysModulesSnapshot()
|
||||
monkeypatch.setattr(sys, 'modules', replacement)
|
||||
monkeypatch.setattr(sys, "modules", replacement)
|
||||
snapshot.restore()
|
||||
assert sys.modules is replacement
|
||||
assert sys.modules == original
|
||||
|
||||
|
||||
@pytest.mark.parametrize('path_type', ('path', 'meta_path'))
|
||||
@pytest.mark.parametrize("path_type", ("path", "meta_path"))
|
||||
class TestSysPathsSnapshot(object):
|
||||
other_path = {
|
||||
'path': 'meta_path',
|
||||
'meta_path': 'path'}
|
||||
other_path = {"path": "meta_path", "meta_path": "path"}
|
||||
|
||||
@staticmethod
|
||||
def path(n):
|
||||
return 'my-dirty-little-secret-' + str(n)
|
||||
return "my-dirty-little-secret-" + str(n)
|
||||
|
||||
def test_restore(self, monkeypatch, path_type):
|
||||
other_path_type = self.other_path[path_type]
|
||||
@@ -348,16 +365,17 @@ class TestSysPathsSnapshot(object):
|
||||
original_other = list(getattr(sys, other_path_type))
|
||||
snapshot = SysPathsSnapshot()
|
||||
transformation = {
|
||||
'source': (0, 1, 2, 3, 4, 5),
|
||||
'target': ( 6, 2, 9, 7, 5, 8)} # noqa: E201
|
||||
assert sys_path == [self.path(x) for x in transformation['source']]
|
||||
"source": (0, 1, 2, 3, 4, 5),
|
||||
"target": (6, 2, 9, 7, 5, 8),
|
||||
} # noqa: E201
|
||||
assert sys_path == [self.path(x) for x in transformation["source"]]
|
||||
sys_path[1] = self.path(6)
|
||||
sys_path[3] = self.path(7)
|
||||
sys_path.append(self.path(8))
|
||||
del sys_path[4]
|
||||
sys_path[3:3] = [self.path(9)]
|
||||
del sys_path[0]
|
||||
assert sys_path == [self.path(x) for x in transformation['target']]
|
||||
assert sys_path == [self.path(x) for x in transformation["target"]]
|
||||
snapshot.restore()
|
||||
assert getattr(sys, path_type) is sys_path
|
||||
assert getattr(sys, path_type) == original
|
||||
|
||||
@@ -7,13 +7,15 @@ from _pytest.recwarn import WarningsRecorder
|
||||
|
||||
|
||||
def test_recwarn_functional(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
reprec = testdir.inline_runsource(
|
||||
"""
|
||||
import warnings
|
||||
def test_method(recwarn):
|
||||
warnings.warn("hello")
|
||||
warn = recwarn.pop()
|
||||
assert isinstance(warn.message, UserWarning)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
res = reprec.countoutcomes()
|
||||
assert tuple(res) == (1, 0, 0), res
|
||||
|
||||
@@ -37,10 +39,11 @@ class TestWarningsRecorderChecker(object):
|
||||
|
||||
def test_typechecking(self):
|
||||
from _pytest.recwarn import WarningsChecker
|
||||
|
||||
with pytest.raises(TypeError):
|
||||
WarningsChecker(5)
|
||||
with pytest.raises(TypeError):
|
||||
WarningsChecker(('hi', RuntimeWarning))
|
||||
WarningsChecker(("hi", RuntimeWarning))
|
||||
with pytest.raises(TypeError):
|
||||
WarningsChecker([DeprecationWarning, RuntimeWarning])
|
||||
|
||||
@@ -63,19 +66,19 @@ class TestDeprecatedCall(object):
|
||||
|
||||
def dep(self, i, j=None):
|
||||
if i == 0:
|
||||
warnings.warn("is deprecated", DeprecationWarning,
|
||||
stacklevel=1)
|
||||
warnings.warn("is deprecated", DeprecationWarning, stacklevel=1)
|
||||
return 42
|
||||
|
||||
def dep_explicit(self, i):
|
||||
if i == 0:
|
||||
warnings.warn_explicit("dep_explicit", category=DeprecationWarning,
|
||||
filename="hello", lineno=3)
|
||||
warnings.warn_explicit(
|
||||
"dep_explicit", category=DeprecationWarning, filename="hello", lineno=3
|
||||
)
|
||||
|
||||
def test_deprecated_call_raises(self):
|
||||
with pytest.raises(AssertionError) as excinfo:
|
||||
pytest.deprecated_call(self.dep, 3, 5)
|
||||
assert 'Did not produce' in str(excinfo)
|
||||
assert "Did not produce" in str(excinfo)
|
||||
|
||||
def test_deprecated_call(self):
|
||||
pytest.deprecated_call(self.dep, 0, 5)
|
||||
@@ -104,30 +107,34 @@ class TestDeprecatedCall(object):
|
||||
pytest.deprecated_call(self.dep_explicit, 0)
|
||||
pytest.deprecated_call(self.dep_explicit, 0)
|
||||
|
||||
@pytest.mark.parametrize('mode', ['context_manager', 'call'])
|
||||
@pytest.mark.parametrize("mode", ["context_manager", "call"])
|
||||
def test_deprecated_call_no_warning(self, mode):
|
||||
"""Ensure deprecated_call() raises the expected failure when its block/function does
|
||||
not raise a deprecation warning.
|
||||
"""
|
||||
|
||||
def f():
|
||||
pass
|
||||
|
||||
msg = 'Did not produce DeprecationWarning or PendingDeprecationWarning'
|
||||
msg = "Did not produce DeprecationWarning or PendingDeprecationWarning"
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
if mode == 'call':
|
||||
if mode == "call":
|
||||
pytest.deprecated_call(f)
|
||||
else:
|
||||
with pytest.deprecated_call():
|
||||
f()
|
||||
|
||||
@pytest.mark.parametrize('warning_type', [PendingDeprecationWarning, DeprecationWarning])
|
||||
@pytest.mark.parametrize('mode', ['context_manager', 'call'])
|
||||
@pytest.mark.parametrize('call_f_first', [True, False])
|
||||
@pytest.mark.filterwarnings('ignore')
|
||||
@pytest.mark.parametrize(
|
||||
"warning_type", [PendingDeprecationWarning, DeprecationWarning]
|
||||
)
|
||||
@pytest.mark.parametrize("mode", ["context_manager", "call"])
|
||||
@pytest.mark.parametrize("call_f_first", [True, False])
|
||||
@pytest.mark.filterwarnings("ignore")
|
||||
def test_deprecated_call_modes(self, warning_type, mode, call_f_first):
|
||||
"""Ensure deprecated_call() captures a deprecation warning as expected inside its
|
||||
block/function.
|
||||
"""
|
||||
|
||||
def f():
|
||||
warnings.warn(warning_type("hi"))
|
||||
return 10
|
||||
@@ -135,31 +142,40 @@ class TestDeprecatedCall(object):
|
||||
# ensure deprecated_call() can capture the warning even if it has already been triggered
|
||||
if call_f_first:
|
||||
assert f() == 10
|
||||
if mode == 'call':
|
||||
if mode == "call":
|
||||
assert pytest.deprecated_call(f) == 10
|
||||
else:
|
||||
with pytest.deprecated_call():
|
||||
assert f() == 10
|
||||
|
||||
@pytest.mark.parametrize('mode', ['context_manager', 'call'])
|
||||
@pytest.mark.parametrize("mode", ["context_manager", "call"])
|
||||
def test_deprecated_call_exception_is_raised(self, mode):
|
||||
"""If the block of the code being tested by deprecated_call() raises an exception,
|
||||
it must raise the exception undisturbed.
|
||||
"""
|
||||
def f():
|
||||
raise ValueError('some exception')
|
||||
|
||||
with pytest.raises(ValueError, match='some exception'):
|
||||
if mode == 'call':
|
||||
def f():
|
||||
raise ValueError("some exception")
|
||||
|
||||
with pytest.raises(ValueError, match="some exception"):
|
||||
if mode == "call":
|
||||
pytest.deprecated_call(f)
|
||||
else:
|
||||
with pytest.deprecated_call():
|
||||
f()
|
||||
|
||||
def test_deprecated_call_specificity(self):
|
||||
other_warnings = [Warning, UserWarning, SyntaxWarning, RuntimeWarning,
|
||||
FutureWarning, ImportWarning, UnicodeWarning]
|
||||
other_warnings = [
|
||||
Warning,
|
||||
UserWarning,
|
||||
SyntaxWarning,
|
||||
RuntimeWarning,
|
||||
FutureWarning,
|
||||
ImportWarning,
|
||||
UnicodeWarning,
|
||||
]
|
||||
for warning in other_warnings:
|
||||
|
||||
def f():
|
||||
warnings.warn(warning("hi"))
|
||||
|
||||
@@ -177,23 +193,28 @@ class TestWarns(object):
|
||||
source2 = "warnings.warn('w2', RuntimeWarning)"
|
||||
source3 = "warnings.warn('w3', RuntimeWarning)"
|
||||
pytest.warns(RuntimeWarning, source1)
|
||||
pytest.raises(pytest.fail.Exception,
|
||||
lambda: pytest.warns(UserWarning, source2))
|
||||
pytest.raises(pytest.fail.Exception, lambda: pytest.warns(UserWarning, source2))
|
||||
pytest.warns(RuntimeWarning, source3)
|
||||
|
||||
def test_function(self):
|
||||
pytest.warns(SyntaxWarning,
|
||||
lambda msg: warnings.warn(msg, SyntaxWarning), "syntax")
|
||||
pytest.warns(
|
||||
SyntaxWarning, lambda msg: warnings.warn(msg, SyntaxWarning), "syntax"
|
||||
)
|
||||
|
||||
def test_warning_tuple(self):
|
||||
pytest.warns((RuntimeWarning, SyntaxWarning),
|
||||
lambda: warnings.warn('w1', RuntimeWarning))
|
||||
pytest.warns((RuntimeWarning, SyntaxWarning),
|
||||
lambda: warnings.warn('w2', SyntaxWarning))
|
||||
pytest.raises(pytest.fail.Exception,
|
||||
lambda: pytest.warns(
|
||||
(RuntimeWarning, SyntaxWarning),
|
||||
lambda: warnings.warn('w3', UserWarning)))
|
||||
pytest.warns(
|
||||
(RuntimeWarning, SyntaxWarning), lambda: warnings.warn("w1", RuntimeWarning)
|
||||
)
|
||||
pytest.warns(
|
||||
(RuntimeWarning, SyntaxWarning), lambda: warnings.warn("w2", SyntaxWarning)
|
||||
)
|
||||
pytest.raises(
|
||||
pytest.fail.Exception,
|
||||
lambda: pytest.warns(
|
||||
(RuntimeWarning, SyntaxWarning),
|
||||
lambda: warnings.warn("w3", UserWarning),
|
||||
),
|
||||
)
|
||||
|
||||
def test_as_contextmanager(self):
|
||||
with pytest.warns(RuntimeWarning):
|
||||
@@ -205,20 +226,26 @@ class TestWarns(object):
|
||||
with pytest.raises(pytest.fail.Exception) as excinfo:
|
||||
with pytest.warns(RuntimeWarning):
|
||||
warnings.warn("user", UserWarning)
|
||||
excinfo.match(r"DID NOT WARN. No warnings of type \(.+RuntimeWarning.+,\) was emitted. "
|
||||
r"The list of emitted warnings is: \[UserWarning\('user',?\)\].")
|
||||
excinfo.match(
|
||||
r"DID NOT WARN. No warnings of type \(.+RuntimeWarning.+,\) was emitted. "
|
||||
r"The list of emitted warnings is: \[UserWarning\('user',?\)\]."
|
||||
)
|
||||
|
||||
with pytest.raises(pytest.fail.Exception) as excinfo:
|
||||
with pytest.warns(UserWarning):
|
||||
warnings.warn("runtime", RuntimeWarning)
|
||||
excinfo.match(r"DID NOT WARN. No warnings of type \(.+UserWarning.+,\) was emitted. "
|
||||
r"The list of emitted warnings is: \[RuntimeWarning\('runtime',?\)\].")
|
||||
excinfo.match(
|
||||
r"DID NOT WARN. No warnings of type \(.+UserWarning.+,\) was emitted. "
|
||||
r"The list of emitted warnings is: \[RuntimeWarning\('runtime',?\)\]."
|
||||
)
|
||||
|
||||
with pytest.raises(pytest.fail.Exception) as excinfo:
|
||||
with pytest.warns(UserWarning):
|
||||
pass
|
||||
excinfo.match(r"DID NOT WARN. No warnings of type \(.+UserWarning.+,\) was emitted. "
|
||||
r"The list of emitted warnings is: \[\].")
|
||||
excinfo.match(
|
||||
r"DID NOT WARN. No warnings of type \(.+UserWarning.+,\) was emitted. "
|
||||
r"The list of emitted warnings is: \[\]."
|
||||
)
|
||||
|
||||
warning_classes = (UserWarning, FutureWarning)
|
||||
with pytest.raises(pytest.fail.Exception) as excinfo:
|
||||
@@ -226,10 +253,17 @@ class TestWarns(object):
|
||||
warnings.warn("runtime", RuntimeWarning)
|
||||
warnings.warn("import", ImportWarning)
|
||||
|
||||
message_template = ("DID NOT WARN. No warnings of type {0} was emitted. "
|
||||
"The list of emitted warnings is: {1}.")
|
||||
excinfo.match(re.escape(message_template.format(warning_classes,
|
||||
[each.message for each in warninfo])))
|
||||
message_template = (
|
||||
"DID NOT WARN. No warnings of type {0} was emitted. "
|
||||
"The list of emitted warnings is: {1}."
|
||||
)
|
||||
excinfo.match(
|
||||
re.escape(
|
||||
message_template.format(
|
||||
warning_classes, [each.message for each in warninfo]
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def test_record(self):
|
||||
with pytest.warns(UserWarning) as record:
|
||||
@@ -272,7 +306,8 @@ class TestWarns(object):
|
||||
|
||||
def test_double_test(self, testdir):
|
||||
"""If a test is run again, the warning should still be raised"""
|
||||
testdir.makepyfile('''
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
import warnings
|
||||
|
||||
@@ -280,30 +315,31 @@ class TestWarns(object):
|
||||
def test(run):
|
||||
with pytest.warns(RuntimeWarning):
|
||||
warnings.warn("runtime", RuntimeWarning)
|
||||
''')
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(['*2 passed in*'])
|
||||
result.stdout.fnmatch_lines(["*2 passed in*"])
|
||||
|
||||
def test_match_regex(self):
|
||||
with pytest.warns(UserWarning, match=r'must be \d+$'):
|
||||
with pytest.warns(UserWarning, match=r"must be \d+$"):
|
||||
warnings.warn("value must be 42", UserWarning)
|
||||
|
||||
with pytest.raises(pytest.fail.Exception):
|
||||
with pytest.warns(UserWarning, match=r'must be \d+$'):
|
||||
with pytest.warns(UserWarning, match=r"must be \d+$"):
|
||||
warnings.warn("this is not here", UserWarning)
|
||||
|
||||
with pytest.raises(pytest.fail.Exception):
|
||||
with pytest.warns(FutureWarning, match=r'must be \d+$'):
|
||||
with pytest.warns(FutureWarning, match=r"must be \d+$"):
|
||||
warnings.warn("value must be 42", UserWarning)
|
||||
|
||||
def test_one_from_multiple_warns(self):
|
||||
with pytest.warns(UserWarning, match=r'aaa'):
|
||||
with pytest.warns(UserWarning, match=r"aaa"):
|
||||
warnings.warn("cccccccccc", UserWarning)
|
||||
warnings.warn("bbbbbbbbbb", UserWarning)
|
||||
warnings.warn("aaaaaaaaaa", UserWarning)
|
||||
|
||||
def test_none_of_multiple_warns(self):
|
||||
with pytest.raises(pytest.fail.Exception):
|
||||
with pytest.warns(UserWarning, match=r'aaa'):
|
||||
with pytest.warns(UserWarning, match=r"aaa"):
|
||||
warnings.warn("bbbbbbbbbb", UserWarning)
|
||||
warnings.warn("cccccccccc", UserWarning)
|
||||
|
||||
@@ -5,71 +5,76 @@ import _pytest._code
|
||||
import py
|
||||
import pytest
|
||||
from _pytest.nodes import Node, Item, FSCollector
|
||||
from _pytest.resultlog import generic_path, ResultLog, \
|
||||
pytest_configure, pytest_unconfigure
|
||||
from _pytest.resultlog import (
|
||||
generic_path,
|
||||
ResultLog,
|
||||
pytest_configure,
|
||||
pytest_unconfigure,
|
||||
)
|
||||
|
||||
|
||||
def test_generic_path(testdir):
|
||||
from _pytest.main import Session
|
||||
|
||||
config = testdir.parseconfig()
|
||||
session = Session(config)
|
||||
p1 = Node('a', config=config, session=session, nodeid='a')
|
||||
p1 = Node("a", config=config, session=session, nodeid="a")
|
||||
# assert p1.fspath is None
|
||||
p2 = Node('B', parent=p1)
|
||||
p3 = Node('()', parent=p2)
|
||||
item = Item('c', parent=p3)
|
||||
p2 = Node("B", parent=p1)
|
||||
p3 = Node("()", parent=p2)
|
||||
item = Item("c", parent=p3)
|
||||
|
||||
res = generic_path(item)
|
||||
assert res == 'a.B().c'
|
||||
assert res == "a.B().c"
|
||||
|
||||
p0 = FSCollector('proj/test', config=config, session=session)
|
||||
p1 = FSCollector('proj/test/a', parent=p0)
|
||||
p2 = Node('B', parent=p1)
|
||||
p3 = Node('()', parent=p2)
|
||||
p4 = Node('c', parent=p3)
|
||||
item = Item('[1]', parent=p4)
|
||||
p0 = FSCollector("proj/test", config=config, session=session)
|
||||
p1 = FSCollector("proj/test/a", parent=p0)
|
||||
p2 = Node("B", parent=p1)
|
||||
p3 = Node("()", parent=p2)
|
||||
p4 = Node("c", parent=p3)
|
||||
item = Item("[1]", parent=p4)
|
||||
|
||||
res = generic_path(item)
|
||||
assert res == 'test/a:B().c[1]'
|
||||
assert res == "test/a:B().c[1]"
|
||||
|
||||
|
||||
def test_write_log_entry():
|
||||
reslog = ResultLog(None, None)
|
||||
reslog.logfile = py.io.TextIO()
|
||||
reslog.write_log_entry('name', '.', '')
|
||||
reslog.write_log_entry("name", ".", "")
|
||||
entry = reslog.logfile.getvalue()
|
||||
assert entry[-1] == '\n'
|
||||
assert entry[-1] == "\n"
|
||||
entry_lines = entry.splitlines()
|
||||
assert len(entry_lines) == 1
|
||||
assert entry_lines[0] == '. name'
|
||||
assert entry_lines[0] == ". name"
|
||||
|
||||
reslog.logfile = py.io.TextIO()
|
||||
reslog.write_log_entry('name', 's', 'Skipped')
|
||||
reslog.write_log_entry("name", "s", "Skipped")
|
||||
entry = reslog.logfile.getvalue()
|
||||
assert entry[-1] == '\n'
|
||||
assert entry[-1] == "\n"
|
||||
entry_lines = entry.splitlines()
|
||||
assert len(entry_lines) == 2
|
||||
assert entry_lines[0] == 's name'
|
||||
assert entry_lines[1] == ' Skipped'
|
||||
assert entry_lines[0] == "s name"
|
||||
assert entry_lines[1] == " Skipped"
|
||||
|
||||
reslog.logfile = py.io.TextIO()
|
||||
reslog.write_log_entry('name', 's', 'Skipped\n')
|
||||
reslog.write_log_entry("name", "s", "Skipped\n")
|
||||
entry = reslog.logfile.getvalue()
|
||||
assert entry[-1] == '\n'
|
||||
assert entry[-1] == "\n"
|
||||
entry_lines = entry.splitlines()
|
||||
assert len(entry_lines) == 2
|
||||
assert entry_lines[0] == 's name'
|
||||
assert entry_lines[1] == ' Skipped'
|
||||
assert entry_lines[0] == "s name"
|
||||
assert entry_lines[1] == " Skipped"
|
||||
|
||||
reslog.logfile = py.io.TextIO()
|
||||
longrepr = ' tb1\n tb 2\nE tb3\nSome Error'
|
||||
reslog.write_log_entry('name', 'F', longrepr)
|
||||
longrepr = " tb1\n tb 2\nE tb3\nSome Error"
|
||||
reslog.write_log_entry("name", "F", longrepr)
|
||||
entry = reslog.logfile.getvalue()
|
||||
assert entry[-1] == '\n'
|
||||
assert entry[-1] == "\n"
|
||||
entry_lines = entry.splitlines()
|
||||
assert len(entry_lines) == 5
|
||||
assert entry_lines[0] == 'F name'
|
||||
assert entry_lines[1:] == [' ' + line for line in longrepr.splitlines()]
|
||||
assert entry_lines[0] == "F name"
|
||||
assert entry_lines[1:] == [" " + line for line in longrepr.splitlines()]
|
||||
|
||||
|
||||
class TestWithFunctionIntegration(object):
|
||||
@@ -98,7 +103,8 @@ class TestWithFunctionIntegration(object):
|
||||
assert "XXX" in "".join(lines[1:])
|
||||
|
||||
def test_log_test_outcomes(self, testdir):
|
||||
mod = testdir.makepyfile(test_mod="""
|
||||
mod = testdir.makepyfile(
|
||||
test_mod="""
|
||||
import pytest
|
||||
def test_pass(): pass
|
||||
def test_skip(): pytest.skip("hello")
|
||||
@@ -109,7 +115,8 @@ class TestWithFunctionIntegration(object):
|
||||
@pytest.mark.xfail
|
||||
def test_xpass(): pass
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
lines = self.getresultlog(testdir, mod)
|
||||
assert len(lines) >= 3
|
||||
assert lines[0].startswith(". ")
|
||||
@@ -123,11 +130,11 @@ class TestWithFunctionIntegration(object):
|
||||
tb = "".join(lines[4:8])
|
||||
assert tb.find('raise ValueError("FAIL")') != -1
|
||||
|
||||
assert lines[8].startswith('x ')
|
||||
assert lines[8].startswith("x ")
|
||||
tb = "".join(lines[8:14])
|
||||
assert tb.find('raise ValueError("XFAIL")') != -1
|
||||
|
||||
assert lines[14].startswith('X ')
|
||||
assert lines[14].startswith("X ")
|
||||
assert len(lines) == 15
|
||||
|
||||
@pytest.mark.parametrize("style", ("native", "long", "short"))
|
||||
@@ -143,16 +150,17 @@ class TestWithFunctionIntegration(object):
|
||||
entry = reslog.logfile.getvalue()
|
||||
entry_lines = entry.splitlines()
|
||||
|
||||
assert entry_lines[0].startswith('! ')
|
||||
assert entry_lines[0].startswith("! ")
|
||||
if style != "native":
|
||||
assert os.path.basename(__file__)[:-9] in entry_lines[0] # .pyc/class
|
||||
assert entry_lines[-1][0] == ' '
|
||||
assert 'ValueError' in entry
|
||||
assert entry_lines[-1][0] == " "
|
||||
assert "ValueError" in entry
|
||||
|
||||
|
||||
def test_generic(testdir, LineMatcher):
|
||||
testdir.plugins.append("resultlog")
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def test_pass():
|
||||
pass
|
||||
@@ -166,51 +174,55 @@ def test_generic(testdir, LineMatcher):
|
||||
@pytest.mark.xfail(run=False)
|
||||
def test_xfail_norun():
|
||||
assert 0
|
||||
""")
|
||||
"""
|
||||
)
|
||||
testdir.runpytest("--resultlog=result.log")
|
||||
lines = testdir.tmpdir.join("result.log").readlines(cr=0)
|
||||
LineMatcher(lines).fnmatch_lines([
|
||||
". *:test_pass",
|
||||
"F *:test_fail",
|
||||
"s *:test_skip",
|
||||
"x *:test_xfail",
|
||||
"x *:test_xfail_norun",
|
||||
])
|
||||
LineMatcher(lines).fnmatch_lines(
|
||||
[
|
||||
". *:test_pass",
|
||||
"F *:test_fail",
|
||||
"s *:test_skip",
|
||||
"x *:test_xfail",
|
||||
"x *:test_xfail_norun",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_makedir_for_resultlog(testdir, LineMatcher):
|
||||
"""--resultlog should automatically create directories for the log file"""
|
||||
testdir.plugins.append("resultlog")
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def test_pass():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
testdir.runpytest("--resultlog=path/to/result.log")
|
||||
lines = testdir.tmpdir.join("path/to/result.log").readlines(cr=0)
|
||||
LineMatcher(lines).fnmatch_lines([
|
||||
". *:test_pass",
|
||||
])
|
||||
LineMatcher(lines).fnmatch_lines([". *:test_pass"])
|
||||
|
||||
|
||||
def test_no_resultlog_on_slaves(testdir):
|
||||
config = testdir.parseconfig("-p", "resultlog", "--resultlog=resultlog")
|
||||
|
||||
assert not hasattr(config, '_resultlog')
|
||||
assert not hasattr(config, "_resultlog")
|
||||
pytest_configure(config)
|
||||
assert hasattr(config, '_resultlog')
|
||||
assert hasattr(config, "_resultlog")
|
||||
pytest_unconfigure(config)
|
||||
assert not hasattr(config, '_resultlog')
|
||||
assert not hasattr(config, "_resultlog")
|
||||
|
||||
config.slaveinput = {}
|
||||
pytest_configure(config)
|
||||
assert not hasattr(config, '_resultlog')
|
||||
assert not hasattr(config, "_resultlog")
|
||||
pytest_unconfigure(config)
|
||||
assert not hasattr(config, '_resultlog')
|
||||
assert not hasattr(config, "_resultlog")
|
||||
|
||||
|
||||
def test_failure_issue380(testdir):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import pytest
|
||||
class MyCollector(pytest.File):
|
||||
def collect(self):
|
||||
@@ -219,10 +231,13 @@ def test_failure_issue380(testdir):
|
||||
return "somestring"
|
||||
def pytest_collect_file(path, parent):
|
||||
return MyCollector(parent=parent, fspath=path)
|
||||
""")
|
||||
testdir.makepyfile("""
|
||||
"""
|
||||
)
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_func():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("--resultlog=log")
|
||||
assert result.ret == 2
|
||||
|
||||
@@ -8,7 +8,7 @@ import py
|
||||
import pytest
|
||||
import sys
|
||||
import types
|
||||
from _pytest import runner, main, outcomes
|
||||
from _pytest import runner, main, outcomes, reports
|
||||
|
||||
|
||||
class TestSetupState(object):
|
||||
@@ -30,11 +30,13 @@ class TestSetupState(object):
|
||||
ss.teardown_exact(item, None)
|
||||
|
||||
def test_setup_fails_and_failure_is_cached(self, testdir):
|
||||
item = testdir.getitem("""
|
||||
item = testdir.getitem(
|
||||
"""
|
||||
def setup_module(mod):
|
||||
raise ValueError(42)
|
||||
def test_func(): pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
ss = runner.SetupState()
|
||||
pytest.raises(ValueError, lambda: ss.prepare(item))
|
||||
pytest.raises(ValueError, lambda: ss.prepare(item))
|
||||
@@ -43,13 +45,13 @@ class TestSetupState(object):
|
||||
r = []
|
||||
|
||||
def fin1():
|
||||
r.append('fin1')
|
||||
r.append("fin1")
|
||||
|
||||
def fin2():
|
||||
raise Exception('oops')
|
||||
raise Exception("oops")
|
||||
|
||||
def fin3():
|
||||
r.append('fin3')
|
||||
r.append("fin3")
|
||||
|
||||
item = testdir.getitem("def test_func(): pass")
|
||||
ss = runner.SetupState()
|
||||
@@ -58,17 +60,17 @@ class TestSetupState(object):
|
||||
ss.addfinalizer(fin3, item)
|
||||
with pytest.raises(Exception) as err:
|
||||
ss._callfinalizers(item)
|
||||
assert err.value.args == ('oops',)
|
||||
assert r == ['fin3', 'fin1']
|
||||
assert err.value.args == ("oops",)
|
||||
assert r == ["fin3", "fin1"]
|
||||
|
||||
def test_teardown_multiple_fail(self, testdir):
|
||||
# Ensure the first exception is the one which is re-raised.
|
||||
# Ideally both would be reported however.
|
||||
def fin1():
|
||||
raise Exception('oops1')
|
||||
raise Exception("oops1")
|
||||
|
||||
def fin2():
|
||||
raise Exception('oops2')
|
||||
raise Exception("oops2")
|
||||
|
||||
item = testdir.getitem("def test_func(): pass")
|
||||
ss = runner.SetupState()
|
||||
@@ -76,15 +78,35 @@ class TestSetupState(object):
|
||||
ss.addfinalizer(fin2, item)
|
||||
with pytest.raises(Exception) as err:
|
||||
ss._callfinalizers(item)
|
||||
assert err.value.args == ('oops2',)
|
||||
assert err.value.args == ("oops2",)
|
||||
|
||||
def test_teardown_multiple_scopes_one_fails(self, testdir):
|
||||
module_teardown = []
|
||||
|
||||
def fin_func():
|
||||
raise Exception("oops1")
|
||||
|
||||
def fin_module():
|
||||
module_teardown.append("fin_module")
|
||||
|
||||
item = testdir.getitem("def test_func(): pass")
|
||||
ss = runner.SetupState()
|
||||
ss.addfinalizer(fin_module, item.listchain()[-2])
|
||||
ss.addfinalizer(fin_func, item)
|
||||
ss.prepare(item)
|
||||
with pytest.raises(Exception, match="oops1"):
|
||||
ss.teardown_exact(item, None)
|
||||
assert module_teardown
|
||||
|
||||
|
||||
class BaseFunctionalTests(object):
|
||||
def test_passfunction(self, testdir):
|
||||
reports = testdir.runitem("""
|
||||
reports = testdir.runitem(
|
||||
"""
|
||||
def test_func():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
rep = reports[1]
|
||||
assert rep.passed
|
||||
assert not rep.failed
|
||||
@@ -92,10 +114,12 @@ class BaseFunctionalTests(object):
|
||||
assert not rep.longrepr
|
||||
|
||||
def test_failfunction(self, testdir):
|
||||
reports = testdir.runitem("""
|
||||
reports = testdir.runitem(
|
||||
"""
|
||||
def test_func():
|
||||
assert 0
|
||||
""")
|
||||
"""
|
||||
)
|
||||
rep = reports[1]
|
||||
assert not rep.passed
|
||||
assert not rep.skipped
|
||||
@@ -105,11 +129,13 @@ class BaseFunctionalTests(object):
|
||||
# assert isinstance(rep.longrepr, ReprExceptionInfo)
|
||||
|
||||
def test_skipfunction(self, testdir):
|
||||
reports = testdir.runitem("""
|
||||
reports = testdir.runitem(
|
||||
"""
|
||||
import pytest
|
||||
def test_func():
|
||||
pytest.skip("hello")
|
||||
""")
|
||||
"""
|
||||
)
|
||||
rep = reports[1]
|
||||
assert not rep.failed
|
||||
assert not rep.passed
|
||||
@@ -123,13 +149,15 @@ class BaseFunctionalTests(object):
|
||||
# assert not rep.skipped.failurerepr
|
||||
|
||||
def test_skip_in_setup_function(self, testdir):
|
||||
reports = testdir.runitem("""
|
||||
reports = testdir.runitem(
|
||||
"""
|
||||
import pytest
|
||||
def setup_function(func):
|
||||
pytest.skip("hello")
|
||||
def test_func():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
print(reports)
|
||||
rep = reports[0]
|
||||
assert not rep.failed
|
||||
@@ -142,13 +170,15 @@ class BaseFunctionalTests(object):
|
||||
assert reports[1].passed # teardown
|
||||
|
||||
def test_failure_in_setup_function(self, testdir):
|
||||
reports = testdir.runitem("""
|
||||
reports = testdir.runitem(
|
||||
"""
|
||||
import pytest
|
||||
def setup_function(func):
|
||||
raise ValueError(42)
|
||||
def test_func():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
rep = reports[0]
|
||||
assert not rep.skipped
|
||||
assert not rep.passed
|
||||
@@ -157,13 +187,15 @@ class BaseFunctionalTests(object):
|
||||
assert len(reports) == 2
|
||||
|
||||
def test_failure_in_teardown_function(self, testdir):
|
||||
reports = testdir.runitem("""
|
||||
reports = testdir.runitem(
|
||||
"""
|
||||
import pytest
|
||||
def teardown_function(func):
|
||||
raise ValueError(42)
|
||||
def test_func():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
print(reports)
|
||||
assert len(reports) == 3
|
||||
rep = reports[2]
|
||||
@@ -175,17 +207,21 @@ class BaseFunctionalTests(object):
|
||||
# assert rep.longrepr.reprtraceback.reprentries
|
||||
|
||||
def test_custom_failure_repr(self, testdir):
|
||||
testdir.makepyfile(conftest="""
|
||||
testdir.makepyfile(
|
||||
conftest="""
|
||||
import pytest
|
||||
class Function(pytest.Function):
|
||||
def repr_failure(self, excinfo):
|
||||
return "hello"
|
||||
""")
|
||||
reports = testdir.runitem("""
|
||||
"""
|
||||
)
|
||||
reports = testdir.runitem(
|
||||
"""
|
||||
import pytest
|
||||
def test_func():
|
||||
assert 0
|
||||
""")
|
||||
"""
|
||||
)
|
||||
rep = reports[1]
|
||||
assert not rep.skipped
|
||||
assert not rep.passed
|
||||
@@ -196,28 +232,36 @@ class BaseFunctionalTests(object):
|
||||
# assert rep.failed.failurerepr == "hello"
|
||||
|
||||
def test_teardown_final_returncode(self, testdir):
|
||||
rec = testdir.inline_runsource("""
|
||||
rec = testdir.inline_runsource(
|
||||
"""
|
||||
def test_func():
|
||||
pass
|
||||
def teardown_function(func):
|
||||
raise ValueError(42)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
assert rec.ret == 1
|
||||
|
||||
def test_logstart_logfinish_hooks(self, testdir):
|
||||
rec = testdir.inline_runsource("""
|
||||
rec = testdir.inline_runsource(
|
||||
"""
|
||||
import pytest
|
||||
def test_func():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reps = rec.getcalls("pytest_runtest_logstart pytest_runtest_logfinish")
|
||||
assert [x._name for x in reps] == ['pytest_runtest_logstart', 'pytest_runtest_logfinish']
|
||||
assert [x._name for x in reps] == [
|
||||
"pytest_runtest_logstart",
|
||||
"pytest_runtest_logfinish",
|
||||
]
|
||||
for rep in reps:
|
||||
assert rep.nodeid == 'test_logstart_logfinish_hooks.py::test_func'
|
||||
assert rep.location == ('test_logstart_logfinish_hooks.py', 1, 'test_func')
|
||||
assert rep.nodeid == "test_logstart_logfinish_hooks.py::test_func"
|
||||
assert rep.location == ("test_logstart_logfinish_hooks.py", 1, "test_func")
|
||||
|
||||
def test_exact_teardown_issue90(self, testdir):
|
||||
rec = testdir.inline_runsource("""
|
||||
rec = testdir.inline_runsource(
|
||||
"""
|
||||
import pytest
|
||||
|
||||
class TestClass(object):
|
||||
@@ -238,7 +282,8 @@ class BaseFunctionalTests(object):
|
||||
traceback.format_exception(*excinfo)
|
||||
def teardown_function(func):
|
||||
raise ValueError(42)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reps = rec.getreports("pytest_runtest_logreport")
|
||||
print(reps)
|
||||
for i in range(2):
|
||||
@@ -256,7 +301,8 @@ class BaseFunctionalTests(object):
|
||||
|
||||
def test_exact_teardown_issue1206(self, testdir):
|
||||
"""issue shadowing error with wrong number of arguments on teardown_method."""
|
||||
rec = testdir.inline_runsource("""
|
||||
rec = testdir.inline_runsource(
|
||||
"""
|
||||
import pytest
|
||||
|
||||
class TestClass(object):
|
||||
@@ -265,18 +311,19 @@ class BaseFunctionalTests(object):
|
||||
|
||||
def test_method(self):
|
||||
assert True
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reps = rec.getreports("pytest_runtest_logreport")
|
||||
print(reps)
|
||||
assert len(reps) == 3
|
||||
#
|
||||
assert reps[0].nodeid.endswith("test_method")
|
||||
assert reps[0].passed
|
||||
assert reps[0].when == 'setup'
|
||||
assert reps[0].when == "setup"
|
||||
#
|
||||
assert reps[1].nodeid.endswith("test_method")
|
||||
assert reps[1].passed
|
||||
assert reps[1].when == 'call'
|
||||
assert reps[1].when == "call"
|
||||
#
|
||||
assert reps[2].nodeid.endswith("test_method")
|
||||
assert reps[2].failed
|
||||
@@ -285,22 +332,26 @@ class BaseFunctionalTests(object):
|
||||
# python3 error
|
||||
"TypeError: teardown_method() missing 2 required positional arguments: 'y' and 'z'",
|
||||
# python2 error
|
||||
'TypeError: teardown_method() takes exactly 4 arguments (2 given)'
|
||||
"TypeError: teardown_method() takes exactly 4 arguments (2 given)",
|
||||
)
|
||||
|
||||
def test_failure_in_setup_function_ignores_custom_repr(self, testdir):
|
||||
testdir.makepyfile(conftest="""
|
||||
testdir.makepyfile(
|
||||
conftest="""
|
||||
import pytest
|
||||
class Function(pytest.Function):
|
||||
def repr_failure(self, excinfo):
|
||||
assert 0
|
||||
""")
|
||||
reports = testdir.runitem("""
|
||||
"""
|
||||
)
|
||||
reports = testdir.runitem(
|
||||
"""
|
||||
def setup_function(func):
|
||||
raise ValueError(42)
|
||||
def test_func():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
assert len(reports) == 2
|
||||
rep = reports[0]
|
||||
print(rep)
|
||||
@@ -314,10 +365,12 @@ class BaseFunctionalTests(object):
|
||||
|
||||
def test_systemexit_does_not_bail_out(self, testdir):
|
||||
try:
|
||||
reports = testdir.runitem("""
|
||||
reports = testdir.runitem(
|
||||
"""
|
||||
def test_func():
|
||||
raise SystemExit(42)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
except SystemExit:
|
||||
pytest.fail("runner did not catch SystemExit")
|
||||
rep = reports[1]
|
||||
@@ -326,11 +379,13 @@ class BaseFunctionalTests(object):
|
||||
|
||||
def test_exit_propagates(self, testdir):
|
||||
try:
|
||||
testdir.runitem("""
|
||||
testdir.runitem(
|
||||
"""
|
||||
import pytest
|
||||
def test_func():
|
||||
raise pytest.exit.Exception()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
except pytest.exit.Exception:
|
||||
pass
|
||||
else:
|
||||
@@ -341,14 +396,17 @@ class TestExecutionNonForked(BaseFunctionalTests):
|
||||
def getrunner(self):
|
||||
def f(item):
|
||||
return runner.runtestprotocol(item, log=False)
|
||||
|
||||
return f
|
||||
|
||||
def test_keyboardinterrupt_propagates(self, testdir):
|
||||
try:
|
||||
testdir.runitem("""
|
||||
testdir.runitem(
|
||||
"""
|
||||
def test_func():
|
||||
raise KeyboardInterrupt("fake")
|
||||
""")
|
||||
"""
|
||||
)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
else:
|
||||
@@ -364,11 +422,13 @@ class TestExecutionForked(BaseFunctionalTests):
|
||||
return boxed.forked_run_report
|
||||
|
||||
def test_suicide(self, testdir):
|
||||
reports = testdir.runitem("""
|
||||
reports = testdir.runitem(
|
||||
"""
|
||||
def test_func():
|
||||
import os
|
||||
os.kill(os.getpid(), 15)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
rep = reports[0]
|
||||
assert rep.failed
|
||||
assert rep.when == "???"
|
||||
@@ -376,12 +436,14 @@ class TestExecutionForked(BaseFunctionalTests):
|
||||
|
||||
class TestSessionReports(object):
|
||||
def test_collect_result(self, testdir):
|
||||
col = testdir.getmodulecol("""
|
||||
col = testdir.getmodulecol(
|
||||
"""
|
||||
def test_func1():
|
||||
pass
|
||||
class TestClass(object):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
rep = runner.collect_one_node(col)
|
||||
assert not rep.failed
|
||||
assert not rep.skipped
|
||||
@@ -397,16 +459,18 @@ class TestSessionReports(object):
|
||||
|
||||
|
||||
reporttypes = [
|
||||
runner.BaseReport,
|
||||
runner.TestReport,
|
||||
runner.TeardownErrorReport,
|
||||
runner.CollectReport,
|
||||
reports.BaseReport,
|
||||
reports.TestReport,
|
||||
reports.TeardownErrorReport,
|
||||
reports.CollectReport,
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('reporttype', reporttypes, ids=[x.__name__ for x in reporttypes])
|
||||
@pytest.mark.parametrize(
|
||||
"reporttype", reporttypes, ids=[x.__name__ for x in reporttypes]
|
||||
)
|
||||
def test_report_extra_parameters(reporttype):
|
||||
if hasattr(inspect, 'signature'):
|
||||
if hasattr(inspect, "signature"):
|
||||
args = list(inspect.signature(reporttype.__init__).parameters.keys())[1:]
|
||||
else:
|
||||
args = inspect.getargspec(reporttype.__init__)[0][1:]
|
||||
@@ -416,23 +480,25 @@ def test_report_extra_parameters(reporttype):
|
||||
|
||||
|
||||
def test_callinfo():
|
||||
ci = runner.CallInfo(lambda: 0, '123')
|
||||
ci = runner.CallInfo(lambda: 0, "123")
|
||||
assert ci.when == "123"
|
||||
assert ci.result == 0
|
||||
assert "result" in repr(ci)
|
||||
ci = runner.CallInfo(lambda: 0 / 0, '123')
|
||||
ci = runner.CallInfo(lambda: 0 / 0, "123")
|
||||
assert ci.when == "123"
|
||||
assert not hasattr(ci, 'result')
|
||||
assert not hasattr(ci, "result")
|
||||
assert ci.excinfo
|
||||
assert "exc" in repr(ci)
|
||||
|
||||
|
||||
# design question: do we want general hooks in python files?
|
||||
# then something like the following functional tests makes sense
|
||||
|
||||
|
||||
@pytest.mark.xfail
|
||||
def test_runtest_in_module_ordering(testdir):
|
||||
p1 = testdir.makepyfile("""
|
||||
p1 = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def pytest_runtest_setup(item): # runs after class-level!
|
||||
item.function.mylist.append("module")
|
||||
@@ -455,22 +521,21 @@ def test_runtest_in_module_ordering(testdir):
|
||||
assert mylist == ['class', 'module'], mylist
|
||||
def pytest_runtest_teardown(item):
|
||||
del item.function.mylist
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest(p1)
|
||||
result.stdout.fnmatch_lines([
|
||||
"*2 passed*"
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*2 passed*"])
|
||||
|
||||
|
||||
def test_outcomeexception_exceptionattributes():
|
||||
outcome = outcomes.OutcomeException('test')
|
||||
outcome = outcomes.OutcomeException("test")
|
||||
assert outcome.args[0] == outcome.msg
|
||||
|
||||
|
||||
def test_outcomeexception_passes_except_Exception():
|
||||
with pytest.raises(outcomes.OutcomeException):
|
||||
try:
|
||||
raise outcomes.OutcomeException('test')
|
||||
raise outcomes.OutcomeException("test")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@@ -493,72 +558,76 @@ def test_pytest_fail():
|
||||
|
||||
|
||||
def test_pytest_exit_msg(testdir):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import pytest
|
||||
|
||||
def pytest_configure(config):
|
||||
pytest.exit('oh noes')
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stderr.fnmatch_lines([
|
||||
"Exit: oh noes",
|
||||
])
|
||||
result.stderr.fnmatch_lines(["Exit: oh noes"])
|
||||
|
||||
|
||||
def test_pytest_fail_notrace(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def test_hello():
|
||||
pytest.fail("hello", pytrace=False)
|
||||
def teardown_function(function):
|
||||
pytest.fail("world", pytrace=False)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
"world",
|
||||
"hello",
|
||||
])
|
||||
assert 'def teardown_function' not in result.stdout.str()
|
||||
result.stdout.fnmatch_lines(["world", "hello"])
|
||||
assert "def teardown_function" not in result.stdout.str()
|
||||
|
||||
|
||||
@pytest.mark.parametrize('str_prefix', ['u', ''])
|
||||
@pytest.mark.parametrize("str_prefix", ["u", ""])
|
||||
def test_pytest_fail_notrace_non_ascii(testdir, str_prefix):
|
||||
"""Fix pytest.fail with pytrace=False with non-ascii characters (#1178).
|
||||
|
||||
This tests with native and unicode strings containing non-ascii chars.
|
||||
"""
|
||||
testdir.makepyfile(u"""
|
||||
testdir.makepyfile(
|
||||
u"""
|
||||
# coding: utf-8
|
||||
import pytest
|
||||
|
||||
def test_hello():
|
||||
pytest.fail(%s'oh oh: ☺', pytrace=False)
|
||||
""" % str_prefix)
|
||||
"""
|
||||
% str_prefix
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
if sys.version_info[0] >= 3:
|
||||
result.stdout.fnmatch_lines(['*test_hello*', "oh oh: ☺"])
|
||||
result.stdout.fnmatch_lines(["*test_hello*", "oh oh: ☺"])
|
||||
else:
|
||||
result.stdout.fnmatch_lines(['*test_hello*', "oh oh: *"])
|
||||
assert 'def test_hello' not in result.stdout.str()
|
||||
result.stdout.fnmatch_lines(["*test_hello*", "oh oh: *"])
|
||||
assert "def test_hello" not in result.stdout.str()
|
||||
|
||||
|
||||
def test_pytest_no_tests_collected_exit_status(testdir):
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines('*collected 0 items*')
|
||||
result.stdout.fnmatch_lines("*collected 0 items*")
|
||||
assert result.ret == main.EXIT_NOTESTSCOLLECTED
|
||||
|
||||
testdir.makepyfile(test_foo="""
|
||||
testdir.makepyfile(
|
||||
test_foo="""
|
||||
def test_foo():
|
||||
assert 1
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines('*collected 1 item*')
|
||||
result.stdout.fnmatch_lines('*1 passed*')
|
||||
result.stdout.fnmatch_lines("*collected 1 item*")
|
||||
result.stdout.fnmatch_lines("*1 passed*")
|
||||
assert result.ret == main.EXIT_OK
|
||||
|
||||
result = testdir.runpytest('-k nonmatch')
|
||||
result.stdout.fnmatch_lines('*collected 1 item*')
|
||||
result.stdout.fnmatch_lines('*1 deselected*')
|
||||
result = testdir.runpytest("-k nonmatch")
|
||||
result.stdout.fnmatch_lines("*collected 1 item*")
|
||||
result.stdout.fnmatch_lines("*1 deselected*")
|
||||
assert result.ret == main.EXIT_NOTESTSCOLLECTED
|
||||
|
||||
|
||||
@@ -592,9 +661,12 @@ def test_importorskip(monkeypatch):
|
||||
mod = types.ModuleType("hello123")
|
||||
mod.__version__ = "1.3"
|
||||
monkeypatch.setitem(sys.modules, "hello123", mod)
|
||||
pytest.raises(pytest.skip.Exception, """
|
||||
pytest.raises(
|
||||
pytest.skip.Exception,
|
||||
"""
|
||||
pytest.importorskip("hello123", minversion="1.3.1")
|
||||
""")
|
||||
""",
|
||||
)
|
||||
mod2 = pytest.importorskip("hello123", minversion="1.3")
|
||||
assert mod2 == mod
|
||||
except pytest.skip.Exception:
|
||||
@@ -610,12 +682,15 @@ def test_importorskip_imports_last_module_part():
|
||||
def test_importorskip_dev_module(monkeypatch):
|
||||
try:
|
||||
mod = types.ModuleType("mockmodule")
|
||||
mod.__version__ = '0.13.0.dev-43290'
|
||||
monkeypatch.setitem(sys.modules, 'mockmodule', mod)
|
||||
mod2 = pytest.importorskip('mockmodule', minversion='0.12.0')
|
||||
mod.__version__ = "0.13.0.dev-43290"
|
||||
monkeypatch.setitem(sys.modules, "mockmodule", mod)
|
||||
mod2 = pytest.importorskip("mockmodule", minversion="0.12.0")
|
||||
assert mod2 == mod
|
||||
pytest.raises(pytest.skip.Exception, """
|
||||
pytest.importorskip('mockmodule1', minversion='0.14.0')""")
|
||||
pytest.raises(
|
||||
pytest.skip.Exception,
|
||||
"""
|
||||
pytest.importorskip('mockmodule1', minversion='0.14.0')""",
|
||||
)
|
||||
except pytest.skip.Exception:
|
||||
print(_pytest._code.ExceptionInfo())
|
||||
pytest.fail("spurious skip")
|
||||
@@ -623,26 +698,31 @@ def test_importorskip_dev_module(monkeypatch):
|
||||
|
||||
def test_importorskip_module_level(testdir):
|
||||
"""importorskip must be able to skip entire modules when used at module level"""
|
||||
testdir.makepyfile('''
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
foobarbaz = pytest.importorskip("foobarbaz")
|
||||
|
||||
def test_foo():
|
||||
pass
|
||||
''')
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(['*collected 0 items / 1 skipped*'])
|
||||
result.stdout.fnmatch_lines(["*collected 0 items / 1 skipped*"])
|
||||
|
||||
|
||||
def test_pytest_cmdline_main(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def test_hello():
|
||||
assert 1
|
||||
if __name__ == '__main__':
|
||||
pytest.cmdline.main([__file__])
|
||||
""")
|
||||
"""
|
||||
)
|
||||
import subprocess
|
||||
|
||||
popen = subprocess.Popen([sys.executable, str(p)], stdout=subprocess.PIPE)
|
||||
popen.communicate()
|
||||
ret = popen.wait()
|
||||
@@ -650,7 +730,8 @@ def test_pytest_cmdline_main(testdir):
|
||||
|
||||
|
||||
def test_unicode_in_longrepr(testdir):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
# -*- coding: utf-8 -*-
|
||||
import pytest
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
@@ -659,52 +740,61 @@ def test_unicode_in_longrepr(testdir):
|
||||
rep = outcome.get_result()
|
||||
if rep.when == "call":
|
||||
rep.longrepr = u'ä'
|
||||
""")
|
||||
testdir.makepyfile("""
|
||||
"""
|
||||
)
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_out():
|
||||
assert 0
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
assert result.ret == 1
|
||||
assert "UnicodeEncodeError" not in result.stderr.str()
|
||||
|
||||
|
||||
def test_failure_in_setup(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def setup_module():
|
||||
0/0
|
||||
def test_func():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("--tb=line")
|
||||
assert "def setup_module" not in result.stdout.str()
|
||||
|
||||
|
||||
def test_makereport_getsource(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_foo():
|
||||
if False: pass
|
||||
else: assert False
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
assert 'INTERNALERROR' not in result.stdout.str()
|
||||
result.stdout.fnmatch_lines(['*else: assert False*'])
|
||||
assert "INTERNALERROR" not in result.stdout.str()
|
||||
result.stdout.fnmatch_lines(["*else: assert False*"])
|
||||
|
||||
|
||||
def test_makereport_getsource_dynamic_code(testdir, monkeypatch):
|
||||
"""Test that exception in dynamically generated code doesn't break getting the source line."""
|
||||
import inspect
|
||||
|
||||
original_findsource = inspect.findsource
|
||||
|
||||
def findsource(obj, *args, **kwargs):
|
||||
# Can be triggered by dynamically created functions
|
||||
if obj.__name__ == 'foo':
|
||||
if obj.__name__ == "foo":
|
||||
raise IndexError()
|
||||
return original_findsource(obj, *args, **kwargs)
|
||||
|
||||
monkeypatch.setattr(inspect, 'findsource', findsource)
|
||||
monkeypatch.setattr(inspect, "findsource", findsource)
|
||||
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
|
||||
@pytest.fixture
|
||||
@@ -713,9 +803,10 @@ def test_makereport_getsource_dynamic_code(testdir, monkeypatch):
|
||||
|
||||
def test_fix(foo):
|
||||
assert False
|
||||
""")
|
||||
result = testdir.runpytest('-vv')
|
||||
assert 'INTERNALERROR' not in result.stdout.str()
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("-vv")
|
||||
assert "INTERNALERROR" not in result.stdout.str()
|
||||
result.stdout.fnmatch_lines(["*test_fix*", "*fixture*'missing'*not found*"])
|
||||
|
||||
|
||||
@@ -725,19 +816,20 @@ def test_store_except_info_on_error():
|
||||
"""
|
||||
# Simulate item that might raise a specific exception, depending on `raise_error` class var
|
||||
class ItemMightRaise(object):
|
||||
nodeid = 'item_that_raises'
|
||||
nodeid = "item_that_raises"
|
||||
raise_error = True
|
||||
|
||||
def runtest(self):
|
||||
if self.raise_error:
|
||||
raise IndexError('TEST')
|
||||
raise IndexError("TEST")
|
||||
|
||||
try:
|
||||
runner.pytest_runtest_call(ItemMightRaise())
|
||||
except IndexError:
|
||||
pass
|
||||
# Check that exception info is stored on sys
|
||||
assert sys.last_type is IndexError
|
||||
assert sys.last_value.args[0] == 'TEST'
|
||||
assert sys.last_value.args[0] == "TEST"
|
||||
assert sys.last_traceback
|
||||
|
||||
# The next run should clear the exception info stored by the previous run
|
||||
@@ -750,8 +842,11 @@ def test_store_except_info_on_error():
|
||||
|
||||
def test_current_test_env_var(testdir, monkeypatch):
|
||||
pytest_current_test_vars = []
|
||||
monkeypatch.setattr(sys, 'pytest_current_test_vars', pytest_current_test_vars, raising=False)
|
||||
testdir.makepyfile('''
|
||||
monkeypatch.setattr(
|
||||
sys, "pytest_current_test_vars", pytest_current_test_vars, raising=False
|
||||
)
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
import sys
|
||||
import os
|
||||
@@ -764,13 +859,17 @@ def test_current_test_env_var(testdir, monkeypatch):
|
||||
|
||||
def test(fix):
|
||||
sys.pytest_current_test_vars.append(('call', os.environ['PYTEST_CURRENT_TEST']))
|
||||
''')
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest_inprocess()
|
||||
assert result.ret == 0
|
||||
test_id = 'test_current_test_env_var.py::test'
|
||||
test_id = "test_current_test_env_var.py::test"
|
||||
assert pytest_current_test_vars == [
|
||||
('setup', test_id + ' (setup)'), ('call', test_id + ' (call)'), ('teardown', test_id + ' (teardown)')]
|
||||
assert 'PYTEST_CURRENT_TEST' not in os.environ
|
||||
("setup", test_id + " (setup)"),
|
||||
("call", test_id + " (call)"),
|
||||
("teardown", test_id + " (teardown)"),
|
||||
]
|
||||
assert "PYTEST_CURRENT_TEST" not in os.environ
|
||||
|
||||
|
||||
class TestReportContents(object):
|
||||
@@ -782,24 +881,29 @@ class TestReportContents(object):
|
||||
return lambda item: runner.runtestprotocol(item, log=False)
|
||||
|
||||
def test_longreprtext_pass(self, testdir):
|
||||
reports = testdir.runitem("""
|
||||
reports = testdir.runitem(
|
||||
"""
|
||||
def test_func():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
rep = reports[1]
|
||||
assert rep.longreprtext == ''
|
||||
assert rep.longreprtext == ""
|
||||
|
||||
def test_longreprtext_failure(self, testdir):
|
||||
reports = testdir.runitem("""
|
||||
reports = testdir.runitem(
|
||||
"""
|
||||
def test_func():
|
||||
x = 1
|
||||
assert x == 4
|
||||
""")
|
||||
"""
|
||||
)
|
||||
rep = reports[1]
|
||||
assert 'assert 1 == 4' in rep.longreprtext
|
||||
assert "assert 1 == 4" in rep.longreprtext
|
||||
|
||||
def test_captured_text(self, testdir):
|
||||
reports = testdir.runitem("""
|
||||
reports = testdir.runitem(
|
||||
"""
|
||||
import pytest
|
||||
import sys
|
||||
|
||||
@@ -816,21 +920,24 @@ class TestReportContents(object):
|
||||
sys.stdout.write('call: stdout\\n')
|
||||
sys.stderr.write('call: stderr\\n')
|
||||
assert 0
|
||||
""")
|
||||
"""
|
||||
)
|
||||
setup, call, teardown = reports
|
||||
assert setup.capstdout == 'setup: stdout\n'
|
||||
assert call.capstdout == 'setup: stdout\ncall: stdout\n'
|
||||
assert teardown.capstdout == 'setup: stdout\ncall: stdout\nteardown: stdout\n'
|
||||
assert setup.capstdout == "setup: stdout\n"
|
||||
assert call.capstdout == "setup: stdout\ncall: stdout\n"
|
||||
assert teardown.capstdout == "setup: stdout\ncall: stdout\nteardown: stdout\n"
|
||||
|
||||
assert setup.capstderr == 'setup: stderr\n'
|
||||
assert call.capstderr == 'setup: stderr\ncall: stderr\n'
|
||||
assert teardown.capstderr == 'setup: stderr\ncall: stderr\nteardown: stderr\n'
|
||||
assert setup.capstderr == "setup: stderr\n"
|
||||
assert call.capstderr == "setup: stderr\ncall: stderr\n"
|
||||
assert teardown.capstderr == "setup: stderr\ncall: stderr\nteardown: stderr\n"
|
||||
|
||||
def test_no_captured_text(self, testdir):
|
||||
reports = testdir.runitem("""
|
||||
reports = testdir.runitem(
|
||||
"""
|
||||
def test_func():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
rep = reports[1]
|
||||
assert rep.capstdout == ''
|
||||
assert rep.capstderr == ''
|
||||
assert rep.capstdout == ""
|
||||
assert rep.capstderr == ""
|
||||
|
||||
@@ -7,7 +7,8 @@ import pytest
|
||||
|
||||
|
||||
def test_module_and_function_setup(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
reprec = testdir.inline_runsource(
|
||||
"""
|
||||
modlevel = []
|
||||
def setup_module(module):
|
||||
assert not modlevel
|
||||
@@ -30,7 +31,8 @@ def test_module_and_function_setup(testdir):
|
||||
def test_module(self):
|
||||
assert modlevel[0] == 42
|
||||
assert not hasattr(test_modlevel, 'answer')
|
||||
""")
|
||||
"""
|
||||
)
|
||||
rep = reprec.matchreport("test_modlevel")
|
||||
assert rep.passed
|
||||
rep = reprec.matchreport("test_module")
|
||||
@@ -38,7 +40,8 @@ def test_module_and_function_setup(testdir):
|
||||
|
||||
|
||||
def test_module_setup_failure_no_teardown(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
reprec = testdir.inline_runsource(
|
||||
"""
|
||||
values = []
|
||||
def setup_module(module):
|
||||
values.append(1)
|
||||
@@ -49,14 +52,16 @@ def test_module_setup_failure_no_teardown(testdir):
|
||||
|
||||
def teardown_module(module):
|
||||
values.append(2)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec.assertoutcome(failed=1)
|
||||
calls = reprec.getcalls("pytest_runtest_setup")
|
||||
assert calls[0].item.module.values == [1]
|
||||
|
||||
|
||||
def test_setup_function_failure_no_teardown(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
reprec = testdir.inline_runsource(
|
||||
"""
|
||||
modlevel = []
|
||||
def setup_function(function):
|
||||
modlevel.append(1)
|
||||
@@ -67,13 +72,15 @@ def test_setup_function_failure_no_teardown(testdir):
|
||||
|
||||
def test_func():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
calls = reprec.getcalls("pytest_runtest_setup")
|
||||
assert calls[0].item.module.modlevel == [1]
|
||||
|
||||
|
||||
def test_class_setup(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
reprec = testdir.inline_runsource(
|
||||
"""
|
||||
class TestSimpleClassSetup(object):
|
||||
clslevel = []
|
||||
def setup_class(cls):
|
||||
@@ -92,12 +99,14 @@ def test_class_setup(testdir):
|
||||
def test_cleanup():
|
||||
assert not TestSimpleClassSetup.clslevel
|
||||
assert not TestInheritedClassSetupStillWorks.clslevel
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec.assertoutcome(passed=1 + 2 + 1)
|
||||
|
||||
|
||||
def test_class_setup_failure_no_teardown(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
reprec = testdir.inline_runsource(
|
||||
"""
|
||||
class TestSimpleClassSetup(object):
|
||||
clslevel = []
|
||||
def setup_class(cls):
|
||||
@@ -111,12 +120,14 @@ def test_class_setup_failure_no_teardown(testdir):
|
||||
|
||||
def test_cleanup():
|
||||
assert not TestSimpleClassSetup.clslevel
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec.assertoutcome(failed=1, passed=1)
|
||||
|
||||
|
||||
def test_method_setup(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
reprec = testdir.inline_runsource(
|
||||
"""
|
||||
class TestSetupMethod(object):
|
||||
def setup_method(self, meth):
|
||||
self.methsetup = meth
|
||||
@@ -128,12 +139,14 @@ def test_method_setup(testdir):
|
||||
|
||||
def test_other(self):
|
||||
assert self.methsetup == self.test_other
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec.assertoutcome(passed=2)
|
||||
|
||||
|
||||
def test_method_setup_failure_no_teardown(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
reprec = testdir.inline_runsource(
|
||||
"""
|
||||
class TestMethodSetup(object):
|
||||
clslevel = []
|
||||
def setup_method(self, method):
|
||||
@@ -148,12 +161,14 @@ def test_method_setup_failure_no_teardown(testdir):
|
||||
|
||||
def test_cleanup():
|
||||
assert TestMethodSetup.clslevel == [1]
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec.assertoutcome(failed=1, passed=1)
|
||||
|
||||
|
||||
def test_method_generator_setup(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
reprec = testdir.inline_runsource(
|
||||
"""
|
||||
class TestSetupTeardownOnInstance(object):
|
||||
def setup_class(cls):
|
||||
cls.classsetup = True
|
||||
@@ -171,12 +186,14 @@ def test_method_generator_setup(testdir):
|
||||
assert self.classsetup
|
||||
assert self.methsetup == self.test_generate
|
||||
assert value == 5
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec.assertoutcome(passed=1, failed=1)
|
||||
|
||||
|
||||
def test_func_generator_setup(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
reprec = testdir.inline_runsource(
|
||||
"""
|
||||
import sys
|
||||
|
||||
def setup_module(mod):
|
||||
@@ -199,13 +216,15 @@ def test_func_generator_setup(testdir):
|
||||
assert x == [1]
|
||||
yield check
|
||||
assert x == [1]
|
||||
""")
|
||||
"""
|
||||
)
|
||||
rep = reprec.matchreport("test_one", names="pytest_runtest_logreport")
|
||||
assert rep.passed
|
||||
|
||||
|
||||
def test_method_setup_uses_fresh_instances(testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
reprec = testdir.inline_runsource(
|
||||
"""
|
||||
class TestSelfState1(object):
|
||||
memory = []
|
||||
def test_hello(self):
|
||||
@@ -213,12 +232,14 @@ def test_method_setup_uses_fresh_instances(testdir):
|
||||
|
||||
def test_afterhello(self):
|
||||
assert self != self.memory[0]
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec.assertoutcome(passed=2, failed=0)
|
||||
|
||||
|
||||
def test_setup_that_skips_calledagain(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def setup_module(mod):
|
||||
pytest.skip("x")
|
||||
@@ -226,13 +247,15 @@ def test_setup_that_skips_calledagain(testdir):
|
||||
pass
|
||||
def test_function2():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(p)
|
||||
reprec.assertoutcome(skipped=2)
|
||||
|
||||
|
||||
def test_setup_fails_again_on_all_tests(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def setup_module(mod):
|
||||
raise ValueError(42)
|
||||
@@ -240,13 +263,15 @@ def test_setup_fails_again_on_all_tests(testdir):
|
||||
pass
|
||||
def test_function2():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(p)
|
||||
reprec.assertoutcome(failed=2)
|
||||
|
||||
|
||||
def test_setup_funcarg_setup_when_outer_scope_fails(testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def setup_module(mod):
|
||||
raise ValueError(42)
|
||||
@@ -257,25 +282,34 @@ def test_setup_funcarg_setup_when_outer_scope_fails(testdir):
|
||||
pass
|
||||
def test_function2(hello):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest(p)
|
||||
result.stdout.fnmatch_lines([
|
||||
"*function1*",
|
||||
"*ValueError*42*",
|
||||
"*function2*",
|
||||
"*ValueError*42*",
|
||||
"*2 error*"
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*function1*",
|
||||
"*ValueError*42*",
|
||||
"*function2*",
|
||||
"*ValueError*42*",
|
||||
"*2 error*",
|
||||
]
|
||||
)
|
||||
assert "xyz43" not in result.stdout.str()
|
||||
|
||||
|
||||
@pytest.mark.parametrize('arg', ['', 'arg'])
|
||||
def test_setup_teardown_function_level_with_optional_argument(testdir, monkeypatch, arg):
|
||||
@pytest.mark.parametrize("arg", ["", "arg"])
|
||||
def test_setup_teardown_function_level_with_optional_argument(
|
||||
testdir, monkeypatch, arg
|
||||
):
|
||||
"""parameter to setup/teardown xunit-style functions parameter is now optional (#1728)."""
|
||||
import sys
|
||||
|
||||
trace_setups_teardowns = []
|
||||
monkeypatch.setattr(sys, 'trace_setups_teardowns', trace_setups_teardowns, raising=False)
|
||||
p = testdir.makepyfile("""
|
||||
monkeypatch.setattr(
|
||||
sys, "trace_setups_teardowns", trace_setups_teardowns, raising=False
|
||||
)
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
import sys
|
||||
|
||||
@@ -296,24 +330,23 @@ def test_setup_teardown_function_level_with_optional_argument(testdir, monkeypat
|
||||
|
||||
def test_method_1(self): pass
|
||||
def test_method_2(self): pass
|
||||
""".format(arg=arg))
|
||||
""".format(
|
||||
arg=arg
|
||||
)
|
||||
)
|
||||
result = testdir.inline_run(p)
|
||||
result.assertoutcome(passed=4)
|
||||
|
||||
expected = [
|
||||
'setup_module',
|
||||
|
||||
'setup_function',
|
||||
'teardown_function',
|
||||
'setup_function',
|
||||
'teardown_function',
|
||||
|
||||
'setup_method',
|
||||
'teardown_method',
|
||||
|
||||
'setup_method',
|
||||
'teardown_method',
|
||||
|
||||
'teardown_module',
|
||||
"setup_module",
|
||||
"setup_function",
|
||||
"teardown_function",
|
||||
"setup_function",
|
||||
"teardown_function",
|
||||
"setup_method",
|
||||
"teardown_method",
|
||||
"setup_method",
|
||||
"teardown_method",
|
||||
"teardown_module",
|
||||
]
|
||||
assert trace_setups_teardowns == expected
|
||||
|
||||
@@ -7,7 +7,8 @@ from _pytest.main import EXIT_NOTESTSCOLLECTED
|
||||
|
||||
class SessionTests(object):
|
||||
def test_basic_testitem_events(self, testdir):
|
||||
tfile = testdir.makepyfile("""
|
||||
tfile = testdir.makepyfile(
|
||||
"""
|
||||
def test_one():
|
||||
pass
|
||||
def test_one_one():
|
||||
@@ -17,7 +18,8 @@ class SessionTests(object):
|
||||
class TestClass(object):
|
||||
def test_two(self, someargs):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(tfile)
|
||||
passed, skipped, failed = reprec.listoutcomes()
|
||||
assert len(skipped) == 0
|
||||
@@ -37,26 +39,31 @@ class SessionTests(object):
|
||||
# assert colreports[1].report.failed
|
||||
|
||||
def test_nested_import_error(self, testdir):
|
||||
tfile = testdir.makepyfile("""
|
||||
tfile = testdir.makepyfile(
|
||||
"""
|
||||
import import_fails
|
||||
def test_this():
|
||||
assert import_fails.a == 1
|
||||
""", import_fails="""
|
||||
""",
|
||||
import_fails="""
|
||||
import does_not_work
|
||||
a = 1
|
||||
""")
|
||||
""",
|
||||
)
|
||||
reprec = testdir.inline_run(tfile)
|
||||
values = reprec.getfailedcollections()
|
||||
assert len(values) == 1
|
||||
out = str(values[0].longrepr)
|
||||
assert out.find('does_not_work') != -1
|
||||
assert out.find("does_not_work") != -1
|
||||
|
||||
def test_raises_output(self, testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
reprec = testdir.inline_runsource(
|
||||
"""
|
||||
import pytest
|
||||
def test_raises_doesnt():
|
||||
pytest.raises(ValueError, int, "3")
|
||||
""")
|
||||
"""
|
||||
)
|
||||
passed, skipped, failed = reprec.listoutcomes()
|
||||
assert len(failed) == 1
|
||||
out = failed[0].longrepr.reprcrash.message
|
||||
@@ -65,13 +72,15 @@ class SessionTests(object):
|
||||
pytest.fail("incorrect raises() output")
|
||||
|
||||
def test_generator_yields_None(self, testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
reprec = testdir.inline_runsource(
|
||||
"""
|
||||
def test_1():
|
||||
yield None
|
||||
""")
|
||||
"""
|
||||
)
|
||||
failures = reprec.getfailedcollections()
|
||||
out = failures[0].longrepr.reprcrash.message
|
||||
i = out.find('TypeError')
|
||||
i = out.find("TypeError")
|
||||
assert i != -1
|
||||
|
||||
def test_syntax_error_module(self, testdir):
|
||||
@@ -79,29 +88,36 @@ class SessionTests(object):
|
||||
values = reprec.getfailedcollections()
|
||||
assert len(values) == 1
|
||||
out = str(values[0].longrepr)
|
||||
assert out.find(str('not python')) != -1
|
||||
assert out.find(str("not python")) != -1
|
||||
|
||||
def test_exit_first_problem(self, testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
reprec = testdir.inline_runsource(
|
||||
"""
|
||||
def test_one(): assert 0
|
||||
def test_two(): assert 0
|
||||
""", '--exitfirst')
|
||||
""",
|
||||
"--exitfirst",
|
||||
)
|
||||
passed, skipped, failed = reprec.countoutcomes()
|
||||
assert failed == 1
|
||||
assert passed == skipped == 0
|
||||
|
||||
def test_maxfail(self, testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
reprec = testdir.inline_runsource(
|
||||
"""
|
||||
def test_one(): assert 0
|
||||
def test_two(): assert 0
|
||||
def test_three(): assert 0
|
||||
""", '--maxfail=2')
|
||||
""",
|
||||
"--maxfail=2",
|
||||
)
|
||||
passed, skipped, failed = reprec.countoutcomes()
|
||||
assert failed == 2
|
||||
assert passed == skipped == 0
|
||||
|
||||
def test_broken_repr(self, testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
class BrokenRepr1(object):
|
||||
foo=0
|
||||
@@ -117,21 +133,30 @@ class SessionTests(object):
|
||||
t = BrokenRepr1()
|
||||
assert t.foo == 1
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(p)
|
||||
passed, skipped, failed = reprec.listoutcomes()
|
||||
assert len(failed) == 1
|
||||
out = failed[0].longrepr.reprcrash.message
|
||||
assert out.find("""[Exception("Ha Ha fooled you, I'm a broken repr().") raised in repr()]""") != -1 # '
|
||||
assert (
|
||||
out.find(
|
||||
"""[Exception("Ha Ha fooled you, I'm a broken repr().") raised in repr()]"""
|
||||
)
|
||||
!= -1
|
||||
) # '
|
||||
|
||||
def test_skip_file_by_conftest(self, testdir):
|
||||
testdir.makepyfile(conftest="""
|
||||
testdir.makepyfile(
|
||||
conftest="""
|
||||
import pytest
|
||||
def pytest_collect_file():
|
||||
pytest.skip("intentional")
|
||||
""", test_file="""
|
||||
""",
|
||||
test_file="""
|
||||
def test_one(): pass
|
||||
""")
|
||||
""",
|
||||
)
|
||||
try:
|
||||
reprec = testdir.inline_run(testdir.tmpdir)
|
||||
except pytest.skip.Exception:
|
||||
@@ -142,9 +167,9 @@ class SessionTests(object):
|
||||
|
||||
|
||||
class TestNewSession(SessionTests):
|
||||
|
||||
def test_order_of_execution(self, testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
reprec = testdir.inline_runsource(
|
||||
"""
|
||||
values = []
|
||||
def test_1():
|
||||
values.append(1)
|
||||
@@ -162,7 +187,8 @@ class TestNewSession(SessionTests):
|
||||
self.reslist.append(3)
|
||||
def test_4(self):
|
||||
assert self.reslist == [1,2,1,2,3]
|
||||
""")
|
||||
"""
|
||||
)
|
||||
passed, skipped, failed = reprec.countoutcomes()
|
||||
assert failed == skipped == 0
|
||||
assert passed == 7
|
||||
@@ -182,9 +208,9 @@ class TestNewSession(SessionTests):
|
||||
pass
|
||||
""",
|
||||
test_three="xxxdsadsadsadsa",
|
||||
__init__=""
|
||||
__init__="",
|
||||
)
|
||||
reprec = testdir.inline_run('--collect-only', p.dirpath())
|
||||
reprec = testdir.inline_run("--collect-only", p.dirpath())
|
||||
|
||||
itemstarted = reprec.getcalls("pytest_itemcollected")
|
||||
assert len(itemstarted) == 3
|
||||
@@ -214,9 +240,12 @@ class TestNewSession(SessionTests):
|
||||
|
||||
|
||||
def test_plugin_specify(testdir):
|
||||
pytest.raises(ImportError, """
|
||||
pytest.raises(
|
||||
ImportError,
|
||||
"""
|
||||
testdir.parseconfig("-p", "nqweotexistent")
|
||||
""")
|
||||
""",
|
||||
)
|
||||
# pytest.raises(ImportError,
|
||||
# "config.do_configure(config)"
|
||||
# )
|
||||
@@ -224,7 +253,7 @@ def test_plugin_specify(testdir):
|
||||
|
||||
def test_plugin_already_exists(testdir):
|
||||
config = testdir.parseconfig("-p", "terminal")
|
||||
assert config.option.plugins == ['terminal']
|
||||
assert config.option.plugins == ["terminal"]
|
||||
config._do_configure()
|
||||
config._ensure_unconfigure()
|
||||
|
||||
@@ -241,21 +270,26 @@ def test_exclude(testdir):
|
||||
|
||||
|
||||
def test_deselect(testdir):
|
||||
testdir.makepyfile(test_a="""
|
||||
testdir.makepyfile(
|
||||
test_a="""
|
||||
import pytest
|
||||
def test_a1(): pass
|
||||
@pytest.mark.parametrize('b', range(3))
|
||||
def test_a2(b): pass
|
||||
""")
|
||||
result = testdir.runpytest("-v", "--deselect=test_a.py::test_a2[1]", "--deselect=test_a.py::test_a2[2]")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest(
|
||||
"-v", "--deselect=test_a.py::test_a2[1]", "--deselect=test_a.py::test_a2[2]"
|
||||
)
|
||||
assert result.ret == 0
|
||||
result.stdout.fnmatch_lines(["*2 passed, 2 deselected*"])
|
||||
for line in result.stdout.lines:
|
||||
assert not line.startswith(('test_a.py::test_a2[1]', 'test_a.py::test_a2[2]'))
|
||||
assert not line.startswith(("test_a.py::test_a2[1]", "test_a.py::test_a2[2]"))
|
||||
|
||||
|
||||
def test_sessionfinish_with_start(testdir):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import os
|
||||
values = []
|
||||
def pytest_sessionstart():
|
||||
@@ -265,35 +299,43 @@ def test_sessionfinish_with_start(testdir):
|
||||
def pytest_sessionfinish():
|
||||
assert values[0] == os.getcwd()
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
res = testdir.runpytest("--collect-only")
|
||||
assert res.ret == EXIT_NOTESTSCOLLECTED
|
||||
|
||||
|
||||
@pytest.mark.parametrize("path", ["root", "{relative}/root", "{environment}/root"])
|
||||
def test_rootdir_option_arg(testdir, monkeypatch, path):
|
||||
monkeypatch.setenv('PY_ROOTDIR_PATH', str(testdir.tmpdir))
|
||||
path = path.format(relative=str(testdir.tmpdir),
|
||||
environment='$PY_ROOTDIR_PATH')
|
||||
monkeypatch.setenv("PY_ROOTDIR_PATH", str(testdir.tmpdir))
|
||||
path = path.format(relative=str(testdir.tmpdir), environment="$PY_ROOTDIR_PATH")
|
||||
|
||||
rootdir = testdir.mkdir("root")
|
||||
rootdir.mkdir("tests")
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import os
|
||||
def test_one():
|
||||
assert 1
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
result = testdir.runpytest("--rootdir={}".format(path))
|
||||
result.stdout.fnmatch_lines(['*rootdir: {}/root, inifile:*'.format(testdir.tmpdir), "*1 passed*"])
|
||||
result.stdout.fnmatch_lines(
|
||||
["*rootdir: {}/root, inifile:*".format(testdir.tmpdir), "*1 passed*"]
|
||||
)
|
||||
|
||||
|
||||
def test_rootdir_wrong_option_arg(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import os
|
||||
def test_one():
|
||||
assert 1
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
result = testdir.runpytest("--rootdir=wrong_dir")
|
||||
result.stderr.fnmatch_lines(["*Directory *wrong_dir* not found. Check your '--rootdir' option.*"])
|
||||
result.stderr.fnmatch_lines(
|
||||
["*Directory *wrong_dir* not found. Check your '--rootdir' option.*"]
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -7,13 +7,16 @@ from _pytest.tmpdir import tmpdir
|
||||
|
||||
|
||||
def test_funcarg(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def pytest_generate_tests(metafunc):
|
||||
metafunc.addcall(id='a')
|
||||
metafunc.addcall(id='b')
|
||||
def test_func(tmpdir): pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
from _pytest.tmpdir import TempdirFactory
|
||||
|
||||
reprec = testdir.inline_run()
|
||||
calls = reprec.getcalls("pytest_runtest_setup")
|
||||
item = calls[0].item
|
||||
@@ -32,8 +35,8 @@ def test_funcarg(testdir):
|
||||
|
||||
|
||||
def test_ensuretemp(recwarn):
|
||||
d1 = pytest.ensuretemp('hello')
|
||||
d2 = pytest.ensuretemp('hello')
|
||||
d1 = pytest.ensuretemp("hello")
|
||||
d2 = pytest.ensuretemp("hello")
|
||||
assert d1 == d2
|
||||
assert d1.check(dir=1)
|
||||
|
||||
@@ -41,6 +44,7 @@ def test_ensuretemp(recwarn):
|
||||
class TestTempdirHandler(object):
|
||||
def test_mktemp(self, testdir):
|
||||
from _pytest.tmpdir import TempdirFactory
|
||||
|
||||
config = testdir.parseconfig()
|
||||
config.option.basetemp = testdir.mkdir("hello")
|
||||
t = TempdirFactory(config)
|
||||
@@ -56,33 +60,39 @@ class TestTempdirHandler(object):
|
||||
class TestConfigTmpdir(object):
|
||||
def test_getbasetemp_custom_removes_old(self, testdir):
|
||||
mytemp = testdir.tmpdir.join("xyz")
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
def test_1(tmpdir):
|
||||
pass
|
||||
""")
|
||||
testdir.runpytest(p, '--basetemp=%s' % mytemp)
|
||||
"""
|
||||
)
|
||||
testdir.runpytest(p, "--basetemp=%s" % mytemp)
|
||||
mytemp.check()
|
||||
mytemp.ensure("hello")
|
||||
|
||||
testdir.runpytest(p, '--basetemp=%s' % mytemp)
|
||||
testdir.runpytest(p, "--basetemp=%s" % mytemp)
|
||||
mytemp.check()
|
||||
assert not mytemp.join("hello").check()
|
||||
|
||||
|
||||
def test_basetemp(testdir):
|
||||
mytemp = testdir.tmpdir.mkdir("mytemp")
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def test_1():
|
||||
pytest.ensuretemp("hello")
|
||||
""")
|
||||
result = testdir.runpytest(p, '--basetemp=%s' % mytemp)
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest(p, "--basetemp=%s" % mytemp)
|
||||
assert result.ret == 0
|
||||
assert mytemp.join('hello').check()
|
||||
assert mytemp.join("hello").check()
|
||||
|
||||
|
||||
@pytest.mark.skipif(not hasattr(py.path.local, 'mksymlinkto'),
|
||||
reason="symlink not available on this platform")
|
||||
@pytest.mark.skipif(
|
||||
not hasattr(py.path.local, "mksymlinkto"),
|
||||
reason="symlink not available on this platform",
|
||||
)
|
||||
def test_tmpdir_always_is_realpath(testdir):
|
||||
# the reason why tmpdir should be a realpath is that
|
||||
# when you cd to it and do "os.getcwd()" you will anyway
|
||||
@@ -93,35 +103,41 @@ def test_tmpdir_always_is_realpath(testdir):
|
||||
realtemp = testdir.tmpdir.mkdir("myrealtemp")
|
||||
linktemp = testdir.tmpdir.join("symlinktemp")
|
||||
linktemp.mksymlinkto(realtemp)
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
def test_1(tmpdir):
|
||||
import os
|
||||
assert os.path.realpath(str(tmpdir)) == str(tmpdir)
|
||||
""")
|
||||
result = testdir.runpytest("-s", p, '--basetemp=%s/bt' % linktemp)
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("-s", p, "--basetemp=%s/bt" % linktemp)
|
||||
assert not result.ret
|
||||
|
||||
|
||||
def test_tmpdir_too_long_on_parametrization(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.mark.parametrize("arg", ["1"*1000])
|
||||
def test_some(arg, tmpdir):
|
||||
tmpdir.ensure("hello")
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=1)
|
||||
|
||||
|
||||
def test_tmpdir_factory(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.fixture(scope='session')
|
||||
def session_dir(tmpdir_factory):
|
||||
return tmpdir_factory.mktemp('data', numbered=False)
|
||||
def test_some(session_dir):
|
||||
session_dir.isdir()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=1)
|
||||
|
||||
@@ -130,59 +146,65 @@ def test_tmpdir_fallback_tox_env(testdir, monkeypatch):
|
||||
"""Test that tmpdir works even if environment variables required by getpass
|
||||
module are missing (#1010).
|
||||
"""
|
||||
monkeypatch.delenv('USER', raising=False)
|
||||
monkeypatch.delenv('USERNAME', raising=False)
|
||||
testdir.makepyfile("""
|
||||
monkeypatch.delenv("USER", raising=False)
|
||||
monkeypatch.delenv("USERNAME", raising=False)
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def test_some(tmpdir):
|
||||
assert tmpdir.isdir()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=1)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def break_getuser(monkeypatch):
|
||||
monkeypatch.setattr('os.getuid', lambda: -1)
|
||||
monkeypatch.setattr("os.getuid", lambda: -1)
|
||||
# taken from python 2.7/3.4
|
||||
for envvar in ('LOGNAME', 'USER', 'LNAME', 'USERNAME'):
|
||||
for envvar in ("LOGNAME", "USER", "LNAME", "USERNAME"):
|
||||
monkeypatch.delenv(envvar, raising=False)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("break_getuser")
|
||||
@pytest.mark.skipif(sys.platform.startswith('win'), reason='no os.getuid on windows')
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="no os.getuid on windows")
|
||||
def test_tmpdir_fallback_uid_not_found(testdir):
|
||||
"""Test that tmpdir works even if the current process's user id does not
|
||||
correspond to a valid user.
|
||||
"""
|
||||
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
def test_some(tmpdir):
|
||||
assert tmpdir.isdir()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=1)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("break_getuser")
|
||||
@pytest.mark.skipif(sys.platform.startswith('win'), reason='no os.getuid on windows')
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="no os.getuid on windows")
|
||||
def test_get_user_uid_not_found():
|
||||
"""Test that get_user() function works even if the current process's
|
||||
user id does not correspond to a valid user (e.g. running pytest in a
|
||||
Docker container with 'docker run -u'.
|
||||
"""
|
||||
from _pytest.tmpdir import get_user
|
||||
|
||||
assert get_user() is None
|
||||
|
||||
|
||||
@pytest.mark.skipif(not sys.platform.startswith('win'), reason='win only')
|
||||
@pytest.mark.skipif(not sys.platform.startswith("win"), reason="win only")
|
||||
def test_get_user(monkeypatch):
|
||||
"""Test that get_user() function works even if environment variables
|
||||
required by getpass module are missing from the environment on Windows
|
||||
(#1010).
|
||||
"""
|
||||
from _pytest.tmpdir import get_user
|
||||
monkeypatch.delenv('USER', raising=False)
|
||||
monkeypatch.delenv('USERNAME', raising=False)
|
||||
|
||||
monkeypatch.delenv("USER", raising=False)
|
||||
monkeypatch.delenv("USERNAME", raising=False)
|
||||
assert get_user() is None
|
||||
|
||||
@@ -5,21 +5,24 @@ import gc
|
||||
|
||||
|
||||
def test_simple_unittest(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
class MyTestCase(unittest.TestCase):
|
||||
def testpassing(self):
|
||||
self.assertEqual('foo', 'foo')
|
||||
def test_failing(self):
|
||||
self.assertEqual('foo', 'bar')
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(testpath)
|
||||
assert reprec.matchreport("testpassing").passed
|
||||
assert reprec.matchreport("test_failing").failed
|
||||
|
||||
|
||||
def test_runTest_method(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
class MyTestCaseWithRunTest(unittest.TestCase):
|
||||
def runTest(self):
|
||||
@@ -29,29 +32,35 @@ def test_runTest_method(testdir):
|
||||
self.assertEqual('foo', 'foo')
|
||||
def test_something(self):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("-v")
|
||||
result.stdout.fnmatch_lines("""
|
||||
result.stdout.fnmatch_lines(
|
||||
"""
|
||||
*MyTestCaseWithRunTest::runTest*
|
||||
*MyTestCaseWithoutRunTest::test_something*
|
||||
*2 passed*
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def test_isclasscheck_issue53(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
class _E(object):
|
||||
def __getattr__(self, tag):
|
||||
pass
|
||||
E = _E()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest(testpath)
|
||||
assert result.ret == EXIT_NOTESTSCOLLECTED
|
||||
|
||||
|
||||
def test_setup(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
class MyTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
@@ -64,15 +73,17 @@ def test_setup(testdir):
|
||||
def teardown_method(self, method):
|
||||
assert 0, "42"
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run("-s", testpath)
|
||||
assert reprec.matchreport("test_both", when="call").passed
|
||||
rep = reprec.matchreport("test_both", when="teardown")
|
||||
assert rep.failed and '42' in str(rep.longrepr)
|
||||
assert rep.failed and "42" in str(rep.longrepr)
|
||||
|
||||
|
||||
def test_setUpModule(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
values = []
|
||||
|
||||
def setUpModule():
|
||||
@@ -86,15 +97,15 @@ def test_setUpModule(testdir):
|
||||
|
||||
def test_world():
|
||||
assert values == [1]
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest(testpath)
|
||||
result.stdout.fnmatch_lines([
|
||||
"*2 passed*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*2 passed*"])
|
||||
|
||||
|
||||
def test_setUpModule_failing_no_teardown(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
values = []
|
||||
|
||||
def setUpModule():
|
||||
@@ -105,7 +116,8 @@ def test_setUpModule_failing_no_teardown(testdir):
|
||||
|
||||
def test_hello():
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(testpath)
|
||||
reprec.assertoutcome(passed=0, failed=1)
|
||||
call = reprec.getcalls("pytest_runtest_setup")[0]
|
||||
@@ -113,20 +125,23 @@ def test_setUpModule_failing_no_teardown(testdir):
|
||||
|
||||
|
||||
def test_new_instances(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
class MyTestCase(unittest.TestCase):
|
||||
def test_func1(self):
|
||||
self.x = 2
|
||||
def test_func2(self):
|
||||
assert not hasattr(self, 'x')
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(testpath)
|
||||
reprec.assertoutcome(passed=2)
|
||||
|
||||
|
||||
def test_teardown(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
class MyTestCase(unittest.TestCase):
|
||||
values = []
|
||||
@@ -137,7 +152,8 @@ def test_teardown(testdir):
|
||||
class Second(unittest.TestCase):
|
||||
def test_check(self):
|
||||
self.assertEqual(MyTestCase.values, [None])
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(testpath)
|
||||
passed, skipped, failed = reprec.countoutcomes()
|
||||
assert failed == 0, failed
|
||||
@@ -153,7 +169,8 @@ def test_teardown_issue1649(testdir):
|
||||
The TestCase will not be cleaned up if the test fails, because it
|
||||
would then exist in the stackframe.
|
||||
"""
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
class TestCaseObjectsShouldBeCleanedUp(unittest.TestCase):
|
||||
def setUp(self):
|
||||
@@ -161,15 +178,17 @@ def test_teardown_issue1649(testdir):
|
||||
def test_demo(self):
|
||||
pass
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
testdir.inline_run("-s", testpath)
|
||||
gc.collect()
|
||||
for obj in gc.get_objects():
|
||||
assert type(obj).__name__ != 'TestCaseObjectsShouldBeCleanedUp'
|
||||
assert type(obj).__name__ != "TestCaseObjectsShouldBeCleanedUp"
|
||||
|
||||
|
||||
def test_unittest_skip_issue148(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
|
||||
@unittest.skip("hello")
|
||||
@@ -182,33 +201,39 @@ def test_unittest_skip_issue148(testdir):
|
||||
@classmethod
|
||||
def tearDownClass(self):
|
||||
xxx
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(testpath)
|
||||
reprec.assertoutcome(skipped=1)
|
||||
|
||||
|
||||
def test_method_and_teardown_failing_reporting(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import unittest, pytest
|
||||
class TC(unittest.TestCase):
|
||||
def tearDown(self):
|
||||
assert 0, "down1"
|
||||
def test_method(self):
|
||||
assert False, "down2"
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("-s")
|
||||
assert result.ret == 1
|
||||
result.stdout.fnmatch_lines([
|
||||
"*tearDown*",
|
||||
"*assert 0*",
|
||||
"*test_method*",
|
||||
"*assert False*",
|
||||
"*1 failed*1 error*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*tearDown*",
|
||||
"*assert 0*",
|
||||
"*test_method*",
|
||||
"*assert False*",
|
||||
"*1 failed*1 error*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_setup_failure_is_shown(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
import pytest
|
||||
class TC(unittest.TestCase):
|
||||
@@ -217,19 +242,17 @@ def test_setup_failure_is_shown(testdir):
|
||||
def test_method(self):
|
||||
print ("never42")
|
||||
xyz
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("-s")
|
||||
assert result.ret == 1
|
||||
result.stdout.fnmatch_lines([
|
||||
"*setUp*",
|
||||
"*assert 0*down1*",
|
||||
"*1 failed*",
|
||||
])
|
||||
assert 'never42' not in result.stdout.str()
|
||||
result.stdout.fnmatch_lines(["*setUp*", "*assert 0*down1*", "*1 failed*"])
|
||||
assert "never42" not in result.stdout.str()
|
||||
|
||||
|
||||
def test_setup_setUpClass(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
import pytest
|
||||
class MyTestCase(unittest.TestCase):
|
||||
@@ -246,13 +269,15 @@ def test_setup_setUpClass(testdir):
|
||||
cls.x -= 1
|
||||
def test_teareddown():
|
||||
assert MyTestCase.x == 0
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(testpath)
|
||||
reprec.assertoutcome(passed=3)
|
||||
|
||||
|
||||
def test_setup_class(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
import pytest
|
||||
class MyTestCase(unittest.TestCase):
|
||||
@@ -267,14 +292,16 @@ def test_setup_class(testdir):
|
||||
cls.x -= 1
|
||||
def test_teareddown():
|
||||
assert MyTestCase.x == 0
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(testpath)
|
||||
reprec.assertoutcome(passed=3)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("type", ['Error', 'Failure'])
|
||||
@pytest.mark.parametrize("type", ["Error", "Failure"])
|
||||
def test_testcase_adderrorandfailure_defers(testdir, type):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
from unittest import TestCase
|
||||
import pytest
|
||||
class MyTestCase(TestCase):
|
||||
@@ -288,14 +315,17 @@ def test_testcase_adderrorandfailure_defers(testdir, type):
|
||||
pytest.fail("add%s should not raise")
|
||||
def test_hello(self):
|
||||
pass
|
||||
""" % (type, type))
|
||||
"""
|
||||
% (type, type)
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
assert 'should not raise' not in result.stdout.str()
|
||||
assert "should not raise" not in result.stdout.str()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("type", ['Error', 'Failure'])
|
||||
@pytest.mark.parametrize("type", ["Error", "Failure"])
|
||||
def test_testcase_custom_exception_info(testdir, type):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
from unittest import TestCase
|
||||
import py, pytest
|
||||
import _pytest._code
|
||||
@@ -316,36 +346,44 @@ def test_testcase_custom_exception_info(testdir, type):
|
||||
mp.undo()
|
||||
def test_hello(self):
|
||||
pass
|
||||
""" % locals())
|
||||
"""
|
||||
% locals()
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
"NOTE: Incompatible Exception Representation*",
|
||||
"*ZeroDivisionError*",
|
||||
"*1 failed*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"NOTE: Incompatible Exception Representation*",
|
||||
"*ZeroDivisionError*",
|
||||
"*1 failed*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_testcase_totally_incompatible_exception_info(testdir):
|
||||
item, = testdir.getitems("""
|
||||
item, = testdir.getitems(
|
||||
"""
|
||||
from unittest import TestCase
|
||||
class MyTestCase(TestCase):
|
||||
def test_hello(self):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
item.addError(None, 42)
|
||||
excinfo = item._excinfo.pop(0)
|
||||
assert 'ERROR: Unknown Incompatible' in str(excinfo.getrepr())
|
||||
assert "ERROR: Unknown Incompatible" in str(excinfo.getrepr())
|
||||
|
||||
|
||||
def test_module_level_pytestmark(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
import pytest
|
||||
pytestmark = pytest.mark.xfail
|
||||
class MyTestCase(unittest.TestCase):
|
||||
def test_func1(self):
|
||||
assert 0
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(testpath, "-s")
|
||||
reprec.assertoutcome(skipped=1)
|
||||
|
||||
@@ -355,30 +393,35 @@ class TestTrialUnittest(object):
|
||||
cls.ut = pytest.importorskip("twisted.trial.unittest")
|
||||
# on windows trial uses a socket for a reactor and apparently doesn't close it properly
|
||||
# https://twistedmatrix.com/trac/ticket/9227
|
||||
cls.ignore_unclosed_socket_warning = ('-W', 'always')
|
||||
cls.ignore_unclosed_socket_warning = ("-W", "always")
|
||||
|
||||
def test_trial_testcase_runtest_not_collected(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
from twisted.trial.unittest import TestCase
|
||||
|
||||
class TC(TestCase):
|
||||
def test_hello(self):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(*self.ignore_unclosed_socket_warning)
|
||||
reprec.assertoutcome(passed=1)
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
from twisted.trial.unittest import TestCase
|
||||
|
||||
class TC(TestCase):
|
||||
def runTest(self):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(*self.ignore_unclosed_socket_warning)
|
||||
reprec.assertoutcome(passed=1)
|
||||
|
||||
def test_trial_exceptions_with_skips(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
from twisted.trial import unittest
|
||||
import pytest
|
||||
class TC(unittest.TestCase):
|
||||
@@ -409,24 +452,31 @@ class TestTrialUnittest(object):
|
||||
pytest.skip("skip_in_setup_class")
|
||||
def test_method(self):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
from _pytest.compat import _is_unittest_unexpected_success_a_failure
|
||||
|
||||
should_fail = _is_unittest_unexpected_success_a_failure()
|
||||
result = testdir.runpytest("-rxs", *self.ignore_unclosed_socket_warning)
|
||||
result.stdout.fnmatch_lines_random([
|
||||
"*XFAIL*test_trial_todo*",
|
||||
"*trialselfskip*",
|
||||
"*skip_in_setup_class*",
|
||||
"*iwanto*",
|
||||
"*i2wanto*",
|
||||
"*sys.version_info*",
|
||||
"*skip_in_method*",
|
||||
"*1 failed*4 skipped*3 xfailed*" if should_fail else "*4 skipped*3 xfail*1 xpass*",
|
||||
])
|
||||
result.stdout.fnmatch_lines_random(
|
||||
[
|
||||
"*XFAIL*test_trial_todo*",
|
||||
"*trialselfskip*",
|
||||
"*skip_in_setup_class*",
|
||||
"*iwanto*",
|
||||
"*i2wanto*",
|
||||
"*sys.version_info*",
|
||||
"*skip_in_method*",
|
||||
"*1 failed*4 skipped*3 xfailed*"
|
||||
if should_fail
|
||||
else "*4 skipped*3 xfail*1 xpass*",
|
||||
]
|
||||
)
|
||||
assert result.ret == (1 if should_fail else 0)
|
||||
|
||||
def test_trial_error(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
from twisted.trial.unittest import TestCase
|
||||
from twisted.internet.defer import Deferred
|
||||
from twisted.internet import reactor
|
||||
@@ -460,81 +510,97 @@ class TestTrialUnittest(object):
|
||||
reactor.callLater(0.3, d.callback, None)
|
||||
return d
|
||||
# will crash both at test time and at teardown
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
"*ERRORS*",
|
||||
"*DelayedCalls*",
|
||||
"*test_four*",
|
||||
"*NameError*crash*",
|
||||
"*test_one*",
|
||||
"*NameError*crash*",
|
||||
"*test_three*",
|
||||
"*DelayedCalls*",
|
||||
"*test_two*",
|
||||
"*crash*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*ERRORS*",
|
||||
"*DelayedCalls*",
|
||||
"*test_four*",
|
||||
"*NameError*crash*",
|
||||
"*test_one*",
|
||||
"*NameError*crash*",
|
||||
"*test_three*",
|
||||
"*DelayedCalls*",
|
||||
"*test_two*",
|
||||
"*crash*",
|
||||
]
|
||||
)
|
||||
|
||||
def test_trial_pdb(self, testdir):
|
||||
p = testdir.makepyfile("""
|
||||
p = testdir.makepyfile(
|
||||
"""
|
||||
from twisted.trial import unittest
|
||||
import pytest
|
||||
class TC(unittest.TestCase):
|
||||
def test_hello(self):
|
||||
assert 0, "hellopdb"
|
||||
""")
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest(p)
|
||||
child.expect("hellopdb")
|
||||
child.sendeof()
|
||||
|
||||
def test_trial_testcase_skip_property(self, testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
from twisted.trial import unittest
|
||||
class MyTestCase(unittest.TestCase):
|
||||
skip = 'dont run'
|
||||
def test_func(self):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(testpath, "-s")
|
||||
reprec.assertoutcome(skipped=1)
|
||||
|
||||
def test_trial_testfunction_skip_property(self, testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
from twisted.trial import unittest
|
||||
class MyTestCase(unittest.TestCase):
|
||||
def test_func(self):
|
||||
pass
|
||||
test_func.skip = 'dont run'
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(testpath, "-s")
|
||||
reprec.assertoutcome(skipped=1)
|
||||
|
||||
def test_trial_testcase_todo_property(self, testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
from twisted.trial import unittest
|
||||
class MyTestCase(unittest.TestCase):
|
||||
todo = 'dont run'
|
||||
def test_func(self):
|
||||
assert 0
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(testpath, "-s")
|
||||
reprec.assertoutcome(skipped=1)
|
||||
|
||||
def test_trial_testfunction_todo_property(self, testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
from twisted.trial import unittest
|
||||
class MyTestCase(unittest.TestCase):
|
||||
def test_func(self):
|
||||
assert 0
|
||||
test_func.todo = 'dont run'
|
||||
""")
|
||||
reprec = testdir.inline_run(testpath, "-s", *self.ignore_unclosed_socket_warning)
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(
|
||||
testpath, "-s", *self.ignore_unclosed_socket_warning
|
||||
)
|
||||
reprec.assertoutcome(skipped=1)
|
||||
|
||||
|
||||
def test_djangolike_testcase(testdir):
|
||||
# contributed from Morten Breekevold
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
from unittest import TestCase, main
|
||||
|
||||
class DjangoLikeTestCase(TestCase):
|
||||
@@ -574,32 +640,38 @@ def test_djangolike_testcase(testdir):
|
||||
|
||||
def _post_teardown(self):
|
||||
print ("_post_teardown()")
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("-s")
|
||||
assert result.ret == 0
|
||||
result.stdout.fnmatch_lines([
|
||||
"*_pre_setup()*",
|
||||
"*setUp()*",
|
||||
"*test_thing()*",
|
||||
"*tearDown()*",
|
||||
"*_post_teardown()*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*_pre_setup()*",
|
||||
"*setUp()*",
|
||||
"*test_thing()*",
|
||||
"*tearDown()*",
|
||||
"*_post_teardown()*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_unittest_not_shown_in_traceback(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
class t(unittest.TestCase):
|
||||
def test_hello(self):
|
||||
x = 3
|
||||
self.assertEqual(x, 4)
|
||||
""")
|
||||
"""
|
||||
)
|
||||
res = testdir.runpytest()
|
||||
assert "failUnlessEqual" not in res.stdout.str()
|
||||
|
||||
|
||||
def test_unorderable_types(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
class TestJoinEmpty(unittest.TestCase):
|
||||
pass
|
||||
@@ -610,27 +682,31 @@ def test_unorderable_types(testdir):
|
||||
Test.__name__ = "TestFoo"
|
||||
return Test
|
||||
TestFoo = make_test()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
assert "TypeError" not in result.stdout.str()
|
||||
assert result.ret == EXIT_NOTESTSCOLLECTED
|
||||
|
||||
|
||||
def test_unittest_typerror_traceback(testdir):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
class TestJoinEmpty(unittest.TestCase):
|
||||
def test_hello(self, arg1):
|
||||
pass
|
||||
""")
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
assert "TypeError" in result.stdout.str()
|
||||
assert result.ret == 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize('runner', ['pytest', 'unittest'])
|
||||
@pytest.mark.parametrize("runner", ["pytest", "unittest"])
|
||||
def test_unittest_expected_failure_for_failing_test_is_xfail(testdir, runner):
|
||||
script = testdir.makepyfile("""
|
||||
script = testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
class MyTestCase(unittest.TestCase):
|
||||
@unittest.expectedFailure
|
||||
@@ -638,25 +714,23 @@ def test_unittest_expected_failure_for_failing_test_is_xfail(testdir, runner):
|
||||
assert False
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
""")
|
||||
if runner == 'pytest':
|
||||
"""
|
||||
)
|
||||
if runner == "pytest":
|
||||
result = testdir.runpytest("-rxX")
|
||||
result.stdout.fnmatch_lines([
|
||||
"*XFAIL*MyTestCase*test_failing_test_is_xfail*",
|
||||
"*1 xfailed*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
["*XFAIL*MyTestCase*test_failing_test_is_xfail*", "*1 xfailed*"]
|
||||
)
|
||||
else:
|
||||
result = testdir.runpython(script)
|
||||
result.stderr.fnmatch_lines([
|
||||
"*1 test in*",
|
||||
"*OK*(expected failures=1)*",
|
||||
])
|
||||
result.stderr.fnmatch_lines(["*1 test in*", "*OK*(expected failures=1)*"])
|
||||
assert result.ret == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize('runner', ['pytest', 'unittest'])
|
||||
@pytest.mark.parametrize("runner", ["pytest", "unittest"])
|
||||
def test_unittest_expected_failure_for_passing_test_is_fail(testdir, runner):
|
||||
script = testdir.makepyfile("""
|
||||
script = testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
class MyTestCase(unittest.TestCase):
|
||||
@unittest.expectedFailure
|
||||
@@ -664,31 +738,32 @@ def test_unittest_expected_failure_for_passing_test_is_fail(testdir, runner):
|
||||
assert True
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
""")
|
||||
"""
|
||||
)
|
||||
from _pytest.compat import _is_unittest_unexpected_success_a_failure
|
||||
|
||||
should_fail = _is_unittest_unexpected_success_a_failure()
|
||||
if runner == 'pytest':
|
||||
if runner == "pytest":
|
||||
result = testdir.runpytest("-rxX")
|
||||
result.stdout.fnmatch_lines([
|
||||
"*MyTestCase*test_passing_test_is_fail*",
|
||||
"*1 failed*" if should_fail else "*1 xpassed*",
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*MyTestCase*test_passing_test_is_fail*",
|
||||
"*1 failed*" if should_fail else "*1 xpassed*",
|
||||
]
|
||||
)
|
||||
else:
|
||||
result = testdir.runpython(script)
|
||||
result.stderr.fnmatch_lines([
|
||||
"*1 test in*",
|
||||
"*(unexpected successes=1)*",
|
||||
])
|
||||
result.stderr.fnmatch_lines(["*1 test in*", "*(unexpected successes=1)*"])
|
||||
|
||||
assert result.ret == (1 if should_fail else 0)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('fix_type, stmt', [
|
||||
('fixture', 'return'),
|
||||
('yield_fixture', 'yield'),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"fix_type, stmt", [("fixture", "return"), ("yield_fixture", "yield")]
|
||||
)
|
||||
def test_unittest_setup_interaction(testdir, fix_type, stmt):
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
import pytest
|
||||
class MyTestCase(unittest.TestCase):
|
||||
@@ -710,13 +785,17 @@ def test_unittest_setup_interaction(testdir, fix_type, stmt):
|
||||
|
||||
def test_classattr(self):
|
||||
assert self.__class__.hello == "world"
|
||||
""".format(fix_type=fix_type, stmt=stmt))
|
||||
""".format(
|
||||
fix_type=fix_type, stmt=stmt
|
||||
)
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines("*3 passed*")
|
||||
|
||||
|
||||
def test_non_unittest_no_setupclass_support(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
class TestFoo(object):
|
||||
x = 0
|
||||
|
||||
@@ -734,13 +813,15 @@ def test_non_unittest_no_setupclass_support(testdir):
|
||||
def test_not_teareddown():
|
||||
assert TestFoo.x == 0
|
||||
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(testpath)
|
||||
reprec.assertoutcome(passed=2)
|
||||
|
||||
|
||||
def test_no_teardown_if_setupclass_failed(testdir):
|
||||
testpath = testdir.makepyfile("""
|
||||
testpath = testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
|
||||
class MyTestCase(unittest.TestCase):
|
||||
@@ -760,63 +841,77 @@ def test_no_teardown_if_setupclass_failed(testdir):
|
||||
|
||||
def test_notTornDown():
|
||||
assert MyTestCase.x == 1
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run(testpath)
|
||||
reprec.assertoutcome(passed=1, failed=1)
|
||||
|
||||
|
||||
def test_issue333_result_clearing(testdir):
|
||||
testdir.makeconftest("""
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_runtest_call(item):
|
||||
yield
|
||||
assert 0
|
||||
""")
|
||||
testdir.makepyfile("""
|
||||
"""
|
||||
)
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import unittest
|
||||
class TestIt(unittest.TestCase):
|
||||
def test_func(self):
|
||||
0/0
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(failed=1)
|
||||
|
||||
|
||||
def test_unittest_raise_skip_issue748(testdir):
|
||||
testdir.makepyfile(test_foo="""
|
||||
testdir.makepyfile(
|
||||
test_foo="""
|
||||
import unittest
|
||||
|
||||
class MyTestCase(unittest.TestCase):
|
||||
def test_one(self):
|
||||
raise unittest.SkipTest('skipping due to reasons')
|
||||
""")
|
||||
result = testdir.runpytest("-v", '-rs')
|
||||
result.stdout.fnmatch_lines("""
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("-v", "-rs")
|
||||
result.stdout.fnmatch_lines(
|
||||
"""
|
||||
*SKIP*[1]*test_foo.py*skipping due to reasons*
|
||||
*1 skipped*
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def test_unittest_skip_issue1169(testdir):
|
||||
testdir.makepyfile(test_foo="""
|
||||
testdir.makepyfile(
|
||||
test_foo="""
|
||||
import unittest
|
||||
|
||||
class MyTestCase(unittest.TestCase):
|
||||
@unittest.skip("skipping due to reasons")
|
||||
def test_skip(self):
|
||||
self.fail()
|
||||
""")
|
||||
result = testdir.runpytest("-v", '-rs')
|
||||
result.stdout.fnmatch_lines("""
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("-v", "-rs")
|
||||
result.stdout.fnmatch_lines(
|
||||
"""
|
||||
*SKIP*[1]*skipping due to reasons*
|
||||
*1 skipped*
|
||||
""")
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def test_class_method_containing_test_issue1558(testdir):
|
||||
testdir.makepyfile(test_foo="""
|
||||
testdir.makepyfile(
|
||||
test_foo="""
|
||||
import unittest
|
||||
|
||||
class MyTestCase(unittest.TestCase):
|
||||
@@ -825,6 +920,72 @@ def test_class_method_containing_test_issue1558(testdir):
|
||||
def test_should_not_run(self):
|
||||
pass
|
||||
test_should_not_run.__test__ = False
|
||||
""")
|
||||
"""
|
||||
)
|
||||
reprec = testdir.inline_run()
|
||||
reprec.assertoutcome(passed=1)
|
||||
|
||||
|
||||
@pytest.mark.issue(3498)
|
||||
@pytest.mark.parametrize(
|
||||
"base", ["six.moves.builtins.object", "unittest.TestCase", "unittest2.TestCase"]
|
||||
)
|
||||
def test_usefixtures_marker_on_unittest(base, testdir):
|
||||
module = base.rsplit(".", 1)[0]
|
||||
pytest.importorskip(module)
|
||||
testdir.makepyfile(
|
||||
conftest="""
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def fixture1(request, monkeypatch):
|
||||
monkeypatch.setattr(request.instance, 'fixture1', True )
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def fixture2(request, monkeypatch):
|
||||
monkeypatch.setattr(request.instance, 'fixture2', True )
|
||||
|
||||
def node_and_marks(item):
|
||||
print(item.nodeid)
|
||||
for mark in item.iter_markers():
|
||||
print(" ", mark)
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def my_marks(request):
|
||||
node_and_marks(request.node)
|
||||
|
||||
def pytest_collection_modifyitems(items):
|
||||
for item in items:
|
||||
node_and_marks(item)
|
||||
|
||||
"""
|
||||
)
|
||||
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
import {module}
|
||||
|
||||
class Tests({base}):
|
||||
fixture1 = False
|
||||
fixture2 = False
|
||||
|
||||
@pytest.mark.usefixtures("fixture1")
|
||||
def test_one(self):
|
||||
assert self.fixture1
|
||||
assert not self.fixture2
|
||||
|
||||
@pytest.mark.usefixtures("fixture1", "fixture2")
|
||||
def test_two(self):
|
||||
assert self.fixture1
|
||||
assert self.fixture2
|
||||
|
||||
|
||||
""".format(
|
||||
module=module, base=base
|
||||
)
|
||||
)
|
||||
|
||||
result = testdir.runpytest("-s")
|
||||
result.assert_outcomes(passed=2)
|
||||
|
||||
@@ -6,7 +6,7 @@ import sys
|
||||
import pytest
|
||||
|
||||
|
||||
WARNINGS_SUMMARY_HEADER = 'warnings summary'
|
||||
WARNINGS_SUMMARY_HEADER = "warnings summary"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -16,48 +16,52 @@ def pyfile_with_warnings(testdir, request):
|
||||
"""
|
||||
testdir.syspathinsert()
|
||||
test_name = request.function.__name__
|
||||
module_name = test_name.lstrip('test_') + '_module'
|
||||
testdir.makepyfile(**{
|
||||
module_name: '''
|
||||
module_name = test_name.lstrip("test_") + "_module"
|
||||
testdir.makepyfile(
|
||||
**{
|
||||
module_name: """
|
||||
import warnings
|
||||
def foo():
|
||||
warnings.warn(UserWarning("user warning"))
|
||||
warnings.warn(RuntimeWarning("runtime warning"))
|
||||
return 1
|
||||
''',
|
||||
test_name: '''
|
||||
""",
|
||||
test_name: """
|
||||
import {module_name}
|
||||
def test_func():
|
||||
assert {module_name}.foo() == 1
|
||||
'''.format(module_name=module_name)
|
||||
})
|
||||
""".format(
|
||||
module_name=module_name
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.filterwarnings('always')
|
||||
@pytest.mark.filterwarnings("always")
|
||||
def test_normal_flow(testdir, pyfile_with_warnings):
|
||||
"""
|
||||
Check that the warnings section is displayed, containing test node ids followed by
|
||||
all warnings generated by that test node.
|
||||
"""
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
'*== %s ==*' % WARNINGS_SUMMARY_HEADER,
|
||||
|
||||
'*test_normal_flow.py::test_func',
|
||||
|
||||
'*normal_flow_module.py:3: UserWarning: user warning',
|
||||
'* warnings.warn(UserWarning("user warning"))',
|
||||
|
||||
'*normal_flow_module.py:4: RuntimeWarning: runtime warning',
|
||||
'* warnings.warn(RuntimeWarning("runtime warning"))',
|
||||
'* 1 passed, 2 warnings*',
|
||||
])
|
||||
assert result.stdout.str().count('test_normal_flow.py::test_func') == 1
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*== %s ==*" % WARNINGS_SUMMARY_HEADER,
|
||||
"*test_normal_flow.py::test_func",
|
||||
"*normal_flow_module.py:3: UserWarning: user warning",
|
||||
'* warnings.warn(UserWarning("user warning"))',
|
||||
"*normal_flow_module.py:4: RuntimeWarning: runtime warning",
|
||||
'* warnings.warn(RuntimeWarning("runtime warning"))',
|
||||
"* 1 passed, 2 warnings*",
|
||||
]
|
||||
)
|
||||
assert result.stdout.str().count("test_normal_flow.py::test_func") == 1
|
||||
|
||||
|
||||
@pytest.mark.filterwarnings('always')
|
||||
@pytest.mark.filterwarnings("always")
|
||||
def test_setup_teardown_warnings(testdir, pyfile_with_warnings):
|
||||
testdir.makepyfile('''
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import warnings
|
||||
import pytest
|
||||
|
||||
@@ -69,57 +73,64 @@ def test_setup_teardown_warnings(testdir, pyfile_with_warnings):
|
||||
|
||||
def test_func(fix):
|
||||
pass
|
||||
''')
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
'*== %s ==*' % WARNINGS_SUMMARY_HEADER,
|
||||
|
||||
'*test_setup_teardown_warnings.py:6: UserWarning: warning during setup',
|
||||
'*warnings.warn(UserWarning("warning during setup"))',
|
||||
|
||||
'*test_setup_teardown_warnings.py:8: UserWarning: warning during teardown',
|
||||
'*warnings.warn(UserWarning("warning during teardown"))',
|
||||
'* 1 passed, 2 warnings*',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*== %s ==*" % WARNINGS_SUMMARY_HEADER,
|
||||
"*test_setup_teardown_warnings.py:6: UserWarning: warning during setup",
|
||||
'*warnings.warn(UserWarning("warning during setup"))',
|
||||
"*test_setup_teardown_warnings.py:8: UserWarning: warning during teardown",
|
||||
'*warnings.warn(UserWarning("warning during teardown"))',
|
||||
"* 1 passed, 2 warnings*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('method', ['cmdline', 'ini'])
|
||||
@pytest.mark.parametrize("method", ["cmdline", "ini"])
|
||||
def test_as_errors(testdir, pyfile_with_warnings, method):
|
||||
args = ('-W', 'error') if method == 'cmdline' else ()
|
||||
if method == 'ini':
|
||||
testdir.makeini('''
|
||||
args = ("-W", "error") if method == "cmdline" else ()
|
||||
if method == "ini":
|
||||
testdir.makeini(
|
||||
"""
|
||||
[pytest]
|
||||
filterwarnings= error
|
||||
''')
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest(*args)
|
||||
result.stdout.fnmatch_lines([
|
||||
'E UserWarning: user warning',
|
||||
'as_errors_module.py:3: UserWarning',
|
||||
'* 1 failed in *',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"E UserWarning: user warning",
|
||||
"as_errors_module.py:3: UserWarning",
|
||||
"* 1 failed in *",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('method', ['cmdline', 'ini'])
|
||||
@pytest.mark.parametrize("method", ["cmdline", "ini"])
|
||||
def test_ignore(testdir, pyfile_with_warnings, method):
|
||||
args = ('-W', 'ignore') if method == 'cmdline' else ()
|
||||
if method == 'ini':
|
||||
testdir.makeini('''
|
||||
args = ("-W", "ignore") if method == "cmdline" else ()
|
||||
if method == "ini":
|
||||
testdir.makeini(
|
||||
"""
|
||||
[pytest]
|
||||
filterwarnings= ignore
|
||||
''')
|
||||
"""
|
||||
)
|
||||
|
||||
result = testdir.runpytest(*args)
|
||||
result.stdout.fnmatch_lines([
|
||||
'* 1 passed in *',
|
||||
])
|
||||
result.stdout.fnmatch_lines(["* 1 passed in *"])
|
||||
assert WARNINGS_SUMMARY_HEADER not in result.stdout.str()
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 0),
|
||||
reason='warnings message is unicode is ok in python3')
|
||||
@pytest.mark.filterwarnings('always')
|
||||
@pytest.mark.skipif(
|
||||
sys.version_info < (3, 0), reason="warnings message is unicode is ok in python3"
|
||||
)
|
||||
@pytest.mark.filterwarnings("always")
|
||||
def test_unicode(testdir, pyfile_with_warnings):
|
||||
testdir.makepyfile('''
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
# -*- coding: utf8 -*-
|
||||
import warnings
|
||||
import pytest
|
||||
@@ -132,21 +143,29 @@ def test_unicode(testdir, pyfile_with_warnings):
|
||||
|
||||
def test_func(fix):
|
||||
pass
|
||||
''')
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
'*== %s ==*' % WARNINGS_SUMMARY_HEADER,
|
||||
'*test_unicode.py:8: UserWarning: \u6d4b\u8bd5*',
|
||||
'* 1 passed, 1 warnings*',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*== %s ==*" % WARNINGS_SUMMARY_HEADER,
|
||||
"*test_unicode.py:8: UserWarning: \u6d4b\u8bd5*",
|
||||
"* 1 passed, 1 warnings*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info >= (3, 0),
|
||||
reason='warnings message is broken as it is not str instance')
|
||||
@pytest.mark.skipif(
|
||||
sys.version_info >= (3, 0),
|
||||
reason="warnings message is broken as it is not str instance",
|
||||
)
|
||||
def test_py2_unicode(testdir, pyfile_with_warnings):
|
||||
if getattr(sys, "pypy_version_info", ())[:2] == (5, 9) and sys.platform.startswith('win'):
|
||||
if getattr(sys, "pypy_version_info", ())[:2] == (5, 9) and sys.platform.startswith(
|
||||
"win"
|
||||
):
|
||||
pytest.xfail("fails with unicode error on PyPy2 5.9 and Windows (#2905)")
|
||||
testdir.makepyfile('''
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
# -*- coding: utf8 -*-
|
||||
import warnings
|
||||
import pytest
|
||||
@@ -160,41 +179,48 @@ def test_py2_unicode(testdir, pyfile_with_warnings):
|
||||
@pytest.mark.filterwarnings('always')
|
||||
def test_func(fix):
|
||||
pass
|
||||
''')
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
'*== %s ==*' % WARNINGS_SUMMARY_HEADER,
|
||||
|
||||
'*test_py2_unicode.py:8: UserWarning: \\u6d4b\\u8bd5',
|
||||
'*warnings.warn(u"\u6d4b\u8bd5")',
|
||||
'*warnings.py:*: UnicodeWarning: Warning is using unicode non*',
|
||||
'* 1 passed, 2 warnings*',
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*== %s ==*" % WARNINGS_SUMMARY_HEADER,
|
||||
"*test_py2_unicode.py:8: UserWarning: \\u6d4b\\u8bd5",
|
||||
'*warnings.warn(u"\u6d4b\u8bd5")',
|
||||
"*warnings.py:*: UnicodeWarning: Warning is using unicode non*",
|
||||
"* 1 passed, 2 warnings*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_py2_unicode_ascii(testdir):
|
||||
"""Ensure that our warning about 'unicode warnings containing non-ascii messages'
|
||||
does not trigger with ascii-convertible messages"""
|
||||
testdir.makeini('[pytest]')
|
||||
testdir.makepyfile('''
|
||||
testdir.makeini("[pytest]")
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
import warnings
|
||||
|
||||
@pytest.mark.filterwarnings('always')
|
||||
def test_func():
|
||||
warnings.warn(u"hello")
|
||||
''')
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
'*== %s ==*' % WARNINGS_SUMMARY_HEADER,
|
||||
'*warnings.warn(u"hello")',
|
||||
'* 1 passed, 1 warnings in*'
|
||||
])
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*== %s ==*" % WARNINGS_SUMMARY_HEADER,
|
||||
'*warnings.warn(u"hello")',
|
||||
"* 1 passed, 1 warnings in*",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_works_with_filterwarnings(testdir):
|
||||
"""Ensure our warnings capture does not mess with pre-installed filters (#2430)."""
|
||||
testdir.makepyfile('''
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import warnings
|
||||
|
||||
class MyWarning(Warning):
|
||||
@@ -209,24 +235,26 @@ def test_works_with_filterwarnings(testdir):
|
||||
assert False
|
||||
except MyWarning:
|
||||
assert True
|
||||
''')
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines([
|
||||
'*== 1 passed in *',
|
||||
])
|
||||
result.stdout.fnmatch_lines(["*== 1 passed in *"])
|
||||
|
||||
|
||||
@pytest.mark.parametrize('default_config', ['ini', 'cmdline'])
|
||||
@pytest.mark.parametrize("default_config", ["ini", "cmdline"])
|
||||
def test_filterwarnings_mark(testdir, default_config):
|
||||
"""
|
||||
Test ``filterwarnings`` mark works and takes precedence over command line and ini options.
|
||||
"""
|
||||
if default_config == 'ini':
|
||||
testdir.makeini("""
|
||||
if default_config == "ini":
|
||||
testdir.makeini(
|
||||
"""
|
||||
[pytest]
|
||||
filterwarnings = always
|
||||
""")
|
||||
testdir.makepyfile("""
|
||||
"""
|
||||
)
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import warnings
|
||||
import pytest
|
||||
|
||||
@@ -240,19 +268,22 @@ def test_filterwarnings_mark(testdir, default_config):
|
||||
|
||||
def test_show_warning():
|
||||
warnings.warn(RuntimeWarning())
|
||||
""")
|
||||
result = testdir.runpytest('-W always' if default_config == 'cmdline' else '')
|
||||
result.stdout.fnmatch_lines(['*= 1 failed, 2 passed, 1 warnings in *'])
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("-W always" if default_config == "cmdline" else "")
|
||||
result.stdout.fnmatch_lines(["*= 1 failed, 2 passed, 1 warnings in *"])
|
||||
|
||||
|
||||
def test_non_string_warning_argument(testdir):
|
||||
"""Non-str argument passed to warning breaks pytest (#2956)"""
|
||||
testdir.makepyfile("""
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import warnings
|
||||
import pytest
|
||||
|
||||
def test():
|
||||
warnings.warn(UserWarning(1, u'foo'))
|
||||
""")
|
||||
result = testdir.runpytest('-W', 'always')
|
||||
result.stdout.fnmatch_lines(['*= 1 passed, 1 warnings in *'])
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest("-W", "always")
|
||||
result.stdout.fnmatch_lines(["*= 1 passed, 1 warnings in *"])
|
||||
|
||||
Reference in New Issue
Block a user