2012-07-07 22:09:53 +08:00
|
|
|
import os
|
2013-05-29 06:11:12 +08:00
|
|
|
import stat
|
2011-05-19 04:31:10 +08:00
|
|
|
import sys
|
2011-07-26 10:40:38 +08:00
|
|
|
import zipfile
|
2011-05-19 04:31:10 +08:00
|
|
|
import py
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
ast = pytest.importorskip("ast")
|
2011-09-21 14:12:37 +08:00
|
|
|
if sys.platform.startswith("java"):
|
|
|
|
# XXX should be xfail
|
|
|
|
pytest.skip("assert rewrite does currently not work on jython")
|
2011-05-19 04:31:10 +08:00
|
|
|
|
2011-05-27 01:01:34 +08:00
|
|
|
from _pytest.assertion import util
|
2012-07-07 23:01:44 +08:00
|
|
|
from _pytest.assertion.rewrite import rewrite_asserts, PYTEST_TAG
|
2011-05-19 04:31:10 +08:00
|
|
|
|
|
|
|
|
|
|
|
def setup_module(mod):
|
2011-05-27 01:01:34 +08:00
|
|
|
mod._old_reprcompare = util._reprcompare
|
2011-05-19 04:31:10 +08:00
|
|
|
py.code._reprcompare = None
|
|
|
|
|
|
|
|
def teardown_module(mod):
|
2011-05-27 01:01:34 +08:00
|
|
|
util._reprcompare = mod._old_reprcompare
|
2011-05-19 04:31:10 +08:00
|
|
|
del mod._old_reprcompare
|
|
|
|
|
|
|
|
|
2011-05-20 05:53:13 +08:00
|
|
|
def rewrite(src):
|
|
|
|
tree = ast.parse(src)
|
|
|
|
rewrite_asserts(tree)
|
|
|
|
return tree
|
|
|
|
|
2011-05-19 04:31:10 +08:00
|
|
|
def getmsg(f, extra_ns=None, must_pass=False):
|
|
|
|
"""Rewrite the assertions in f, run it, and get the failure message."""
|
|
|
|
src = '\n'.join(py.code.Code(f).source().lines)
|
2011-05-20 05:53:13 +08:00
|
|
|
mod = rewrite(src)
|
2011-05-19 04:31:10 +08:00
|
|
|
code = compile(mod, "<test>", "exec")
|
|
|
|
ns = {}
|
|
|
|
if extra_ns is not None:
|
|
|
|
ns.update(extra_ns)
|
2011-05-25 07:28:05 +08:00
|
|
|
py.builtin.exec_(code, ns)
|
2011-05-19 04:31:10 +08:00
|
|
|
func = ns[f.__name__]
|
|
|
|
try:
|
|
|
|
func()
|
|
|
|
except AssertionError:
|
|
|
|
if must_pass:
|
|
|
|
pytest.fail("shouldn't have raised")
|
|
|
|
s = str(sys.exc_info()[1])
|
|
|
|
if not s.startswith("assert"):
|
|
|
|
return "AssertionError: " + s
|
|
|
|
return s
|
|
|
|
else:
|
|
|
|
if not must_pass:
|
|
|
|
pytest.fail("function didn't raise at all")
|
|
|
|
|
|
|
|
|
|
|
|
class TestAssertionRewrite:
|
|
|
|
|
2011-05-20 05:53:13 +08:00
|
|
|
def test_place_initial_imports(self):
|
2011-05-20 22:44:36 +08:00
|
|
|
s = """'Doc string'\nother = stuff"""
|
2011-05-20 05:53:13 +08:00
|
|
|
m = rewrite(s)
|
|
|
|
assert isinstance(m.body[0], ast.Expr)
|
|
|
|
assert isinstance(m.body[0].value, ast.Str)
|
2011-05-27 01:01:34 +08:00
|
|
|
for imp in m.body[1:3]:
|
2011-05-20 05:53:13 +08:00
|
|
|
assert isinstance(imp, ast.Import)
|
2011-05-25 06:21:58 +08:00
|
|
|
assert imp.lineno == 2
|
|
|
|
assert imp.col_offset == 0
|
2011-05-27 01:01:34 +08:00
|
|
|
assert isinstance(m.body[3], ast.Assign)
|
2011-05-20 22:44:36 +08:00
|
|
|
s = """from __future__ import with_statement\nother_stuff"""
|
2011-05-20 05:53:13 +08:00
|
|
|
m = rewrite(s)
|
|
|
|
assert isinstance(m.body[0], ast.ImportFrom)
|
2011-05-27 01:01:34 +08:00
|
|
|
for imp in m.body[1:3]:
|
2011-05-20 05:53:13 +08:00
|
|
|
assert isinstance(imp, ast.Import)
|
2011-05-25 06:21:58 +08:00
|
|
|
assert imp.lineno == 2
|
|
|
|
assert imp.col_offset == 0
|
2011-05-27 01:01:34 +08:00
|
|
|
assert isinstance(m.body[3], ast.Expr)
|
2011-05-20 22:44:36 +08:00
|
|
|
s = """'doc string'\nfrom __future__ import with_statement\nother"""
|
2011-05-20 05:53:13 +08:00
|
|
|
m = rewrite(s)
|
|
|
|
assert isinstance(m.body[0], ast.Expr)
|
|
|
|
assert isinstance(m.body[0].value, ast.Str)
|
|
|
|
assert isinstance(m.body[1], ast.ImportFrom)
|
2011-05-27 01:01:34 +08:00
|
|
|
for imp in m.body[2:4]:
|
2011-05-20 05:53:13 +08:00
|
|
|
assert isinstance(imp, ast.Import)
|
2011-05-25 06:21:58 +08:00
|
|
|
assert imp.lineno == 3
|
|
|
|
assert imp.col_offset == 0
|
2011-05-27 01:01:34 +08:00
|
|
|
assert isinstance(m.body[4], ast.Expr)
|
2011-06-28 23:39:11 +08:00
|
|
|
s = """from . import relative\nother_stuff"""
|
|
|
|
m = rewrite(s)
|
|
|
|
for imp in m.body[0:2]:
|
|
|
|
assert isinstance(imp, ast.Import)
|
|
|
|
assert imp.lineno == 1
|
|
|
|
assert imp.col_offset == 0
|
|
|
|
assert isinstance(m.body[3], ast.Expr)
|
2011-05-20 05:53:13 +08:00
|
|
|
|
2011-05-25 06:30:35 +08:00
|
|
|
def test_dont_rewrite(self):
|
|
|
|
s = """'PYTEST_DONT_REWRITE'\nassert 14"""
|
|
|
|
m = rewrite(s)
|
|
|
|
assert len(m.body) == 2
|
|
|
|
assert isinstance(m.body[0].value, ast.Str)
|
|
|
|
assert isinstance(m.body[1], ast.Assert)
|
|
|
|
assert m.body[1].msg is None
|
|
|
|
|
2011-05-19 04:31:10 +08:00
|
|
|
def test_name(self):
|
|
|
|
def f():
|
|
|
|
assert False
|
|
|
|
assert getmsg(f) == "assert False"
|
|
|
|
def f():
|
|
|
|
f = False
|
|
|
|
assert f
|
|
|
|
assert getmsg(f) == "assert False"
|
|
|
|
def f():
|
2013-10-12 21:39:22 +08:00
|
|
|
assert a_global # noqa
|
2013-01-11 01:59:08 +08:00
|
|
|
assert getmsg(f, {"a_global" : False}) == "assert False"
|
|
|
|
def f():
|
|
|
|
assert sys == 42
|
|
|
|
assert getmsg(f, {"sys" : sys}) == "assert sys == 42"
|
|
|
|
def f():
|
2013-10-12 21:39:22 +08:00
|
|
|
assert cls == 42 # noqa
|
2013-01-11 01:59:08 +08:00
|
|
|
class X(object):
|
|
|
|
pass
|
|
|
|
assert getmsg(f, {"cls" : X}) == "assert cls == 42"
|
2011-05-19 04:31:10 +08:00
|
|
|
|
|
|
|
def test_assert_already_has_message(self):
|
|
|
|
def f():
|
|
|
|
assert False, "something bad!"
|
2014-08-24 00:14:25 +08:00
|
|
|
assert getmsg(f) == "AssertionError: something bad!\nassert False"
|
|
|
|
|
|
|
|
def test_assertion_message(self, testdir):
|
|
|
|
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*",
|
|
|
|
])
|
|
|
|
|
|
|
|
def test_assertion_message_multiline(self, testdir):
|
|
|
|
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*",
|
|
|
|
])
|
|
|
|
|
|
|
|
def test_assertion_message_tuple(self, testdir):
|
|
|
|
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*",
|
|
|
|
])
|
|
|
|
|
|
|
|
def test_assertion_message_expr(self, testdir):
|
|
|
|
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*",
|
|
|
|
])
|
2011-05-19 04:31:10 +08:00
|
|
|
|
2014-10-07 07:01:21 +08:00
|
|
|
def test_assertion_message_escape(self, testdir):
|
|
|
|
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",
|
|
|
|
])
|
|
|
|
|
2011-05-19 04:31:10 +08:00
|
|
|
def test_boolop(self):
|
|
|
|
def f():
|
|
|
|
f = g = False
|
|
|
|
assert f and g
|
|
|
|
assert getmsg(f) == "assert (False)"
|
|
|
|
def f():
|
|
|
|
f = True
|
|
|
|
g = False
|
|
|
|
assert f and g
|
|
|
|
assert getmsg(f) == "assert (True and False)"
|
|
|
|
def f():
|
|
|
|
f = False
|
|
|
|
g = True
|
|
|
|
assert f and g
|
|
|
|
assert getmsg(f) == "assert (False)"
|
|
|
|
def f():
|
|
|
|
f = g = False
|
|
|
|
assert f or g
|
|
|
|
assert getmsg(f) == "assert (False or False)"
|
2011-06-29 09:21:22 +08:00
|
|
|
def f():
|
|
|
|
f = g = False
|
|
|
|
assert not f and not g
|
|
|
|
getmsg(f, must_pass=True)
|
2011-08-30 22:34:21 +08:00
|
|
|
def x():
|
|
|
|
return False
|
|
|
|
def f():
|
|
|
|
assert x() and x()
|
|
|
|
assert getmsg(f, {"x" : x}) == "assert (x())"
|
|
|
|
def f():
|
|
|
|
assert False or x()
|
|
|
|
assert getmsg(f, {"x" : x}) == "assert (False or x())"
|
2011-10-15 04:26:13 +08:00
|
|
|
def f():
|
|
|
|
assert 1 in {} and 2 in {}
|
|
|
|
assert getmsg(f) == "assert (1 in {})"
|
|
|
|
def f():
|
|
|
|
x = 1
|
|
|
|
y = 2
|
|
|
|
assert x in {1 : None} and y in {}
|
|
|
|
assert getmsg(f) == "assert (1 in {1: None} and 2 in {})"
|
2011-05-19 04:31:10 +08:00
|
|
|
def f():
|
|
|
|
f = True
|
|
|
|
g = False
|
|
|
|
assert f or g
|
|
|
|
getmsg(f, must_pass=True)
|
2011-07-11 17:57:47 +08:00
|
|
|
def f():
|
|
|
|
f = g = h = lambda: True
|
|
|
|
assert f() and g() and h()
|
|
|
|
getmsg(f, must_pass=True)
|
|
|
|
|
2011-05-19 04:31:10 +08:00
|
|
|
def test_short_circut_evaluation(self):
|
|
|
|
def f():
|
2013-10-12 21:39:22 +08:00
|
|
|
assert True or explode # noqa
|
2011-05-19 04:31:10 +08:00
|
|
|
getmsg(f, must_pass=True)
|
2011-06-29 09:21:22 +08:00
|
|
|
def f():
|
|
|
|
x = 1
|
|
|
|
assert x == 1 or x == 2
|
|
|
|
getmsg(f, must_pass=True)
|
2011-05-19 04:31:10 +08:00
|
|
|
|
|
|
|
def test_unary_op(self):
|
|
|
|
def f():
|
|
|
|
x = True
|
|
|
|
assert not x
|
|
|
|
assert getmsg(f) == "assert not True"
|
|
|
|
def f():
|
|
|
|
x = 0
|
|
|
|
assert ~x + 1
|
|
|
|
assert getmsg(f) == "assert (~0 + 1)"
|
|
|
|
def f():
|
|
|
|
x = 3
|
|
|
|
assert -x + x
|
|
|
|
assert getmsg(f) == "assert (-3 + 3)"
|
|
|
|
def f():
|
|
|
|
x = 0
|
|
|
|
assert +x + x
|
|
|
|
assert getmsg(f) == "assert (+0 + 0)"
|
|
|
|
|
|
|
|
def test_binary_op(self):
|
|
|
|
def f():
|
|
|
|
x = 1
|
|
|
|
y = -1
|
|
|
|
assert x + y
|
|
|
|
assert getmsg(f) == "assert (1 + -1)"
|
2012-05-04 01:49:30 +08:00
|
|
|
def f():
|
|
|
|
assert not 5 % 4
|
|
|
|
assert getmsg(f) == "assert not (5 % 4)"
|
2011-05-19 04:31:10 +08:00
|
|
|
|
2014-10-27 16:31:33 +08:00
|
|
|
def test_boolop_percent(self):
|
2014-10-13 16:26:18 +08:00
|
|
|
def f():
|
2014-10-27 16:31:33 +08:00
|
|
|
assert 3 % 2 and False
|
|
|
|
assert getmsg(f) == "assert ((3 % 2) and False)"
|
2014-10-13 16:26:18 +08:00
|
|
|
def f():
|
2014-10-27 16:31:33 +08:00
|
|
|
assert False or 4 % 2
|
|
|
|
assert getmsg(f) == "assert (False or (4 % 2))"
|
2014-10-13 16:26:18 +08:00
|
|
|
|
2011-05-19 04:31:10 +08:00
|
|
|
def test_call(self):
|
|
|
|
def g(a=42, *args, **kwargs):
|
|
|
|
return False
|
|
|
|
ns = {"g" : g}
|
|
|
|
def f():
|
|
|
|
assert g()
|
2011-06-13 11:41:58 +08:00
|
|
|
assert getmsg(f, ns) == """assert g()"""
|
2011-05-19 04:31:10 +08:00
|
|
|
def f():
|
|
|
|
assert g(1)
|
2011-06-13 11:41:58 +08:00
|
|
|
assert getmsg(f, ns) == """assert g(1)"""
|
2011-05-19 04:31:10 +08:00
|
|
|
def f():
|
|
|
|
assert g(1, 2)
|
2011-06-13 11:41:58 +08:00
|
|
|
assert getmsg(f, ns) == """assert g(1, 2)"""
|
2011-05-19 04:31:10 +08:00
|
|
|
def f():
|
|
|
|
assert g(1, g=42)
|
2011-06-13 11:41:58 +08:00
|
|
|
assert getmsg(f, ns) == """assert g(1, g=42)"""
|
2011-05-19 04:31:10 +08:00
|
|
|
def f():
|
|
|
|
assert g(1, 3, g=23)
|
2011-06-13 11:41:58 +08:00
|
|
|
assert getmsg(f, ns) == """assert g(1, 3, g=23)"""
|
2011-07-15 00:46:32 +08:00
|
|
|
def f():
|
|
|
|
seq = [1, 2, 3]
|
|
|
|
assert g(*seq)
|
|
|
|
assert getmsg(f, ns) == """assert g(*[1, 2, 3])"""
|
2011-07-15 00:45:42 +08:00
|
|
|
def f():
|
|
|
|
x = "a"
|
|
|
|
assert g(**{x : 2})
|
|
|
|
assert getmsg(f, ns) == """assert g(**{'a': 2})"""
|
2011-05-19 04:31:10 +08:00
|
|
|
|
|
|
|
def test_attribute(self):
|
|
|
|
class X(object):
|
|
|
|
g = 3
|
2013-01-11 01:59:08 +08:00
|
|
|
ns = {"x" : X}
|
2011-05-19 04:31:10 +08:00
|
|
|
def f():
|
2013-10-12 21:39:22 +08:00
|
|
|
assert not x.g # noqa
|
2011-05-19 04:31:10 +08:00
|
|
|
assert getmsg(f, ns) == """assert not 3
|
|
|
|
+ where 3 = x.g"""
|
|
|
|
def f():
|
2013-10-12 21:39:22 +08:00
|
|
|
x.a = False # noqa
|
|
|
|
assert x.a # noqa
|
2011-06-13 11:41:58 +08:00
|
|
|
assert getmsg(f, ns) == """assert x.a"""
|
2011-05-19 04:31:10 +08:00
|
|
|
|
|
|
|
def test_comparisons(self):
|
|
|
|
def f():
|
|
|
|
a, b = range(2)
|
|
|
|
assert b < a
|
|
|
|
assert getmsg(f) == """assert 1 < 0"""
|
|
|
|
def f():
|
|
|
|
a, b, c = range(3)
|
|
|
|
assert a > b > c
|
|
|
|
assert getmsg(f) == """assert 0 > 1"""
|
|
|
|
def f():
|
|
|
|
a, b, c = range(3)
|
|
|
|
assert a < b > c
|
|
|
|
assert getmsg(f) == """assert 1 > 2"""
|
|
|
|
def f():
|
|
|
|
a, b, c = range(3)
|
|
|
|
assert a < b <= c
|
|
|
|
getmsg(f, must_pass=True)
|
2011-05-20 07:56:48 +08:00
|
|
|
def f():
|
|
|
|
a, b, c = range(3)
|
|
|
|
assert a < b
|
|
|
|
assert b < c
|
|
|
|
getmsg(f, must_pass=True)
|
2011-05-19 04:31:10 +08:00
|
|
|
|
|
|
|
def test_len(self):
|
|
|
|
def f():
|
2011-05-25 07:30:18 +08:00
|
|
|
l = list(range(10))
|
2011-05-19 04:31:10 +08:00
|
|
|
assert len(l) == 11
|
|
|
|
assert getmsg(f).startswith("""assert 10 == 11
|
|
|
|
+ where 10 = len([""")
|
|
|
|
|
|
|
|
def test_custom_reprcompare(self, monkeypatch):
|
|
|
|
def my_reprcompare(op, left, right):
|
|
|
|
return "42"
|
2011-05-27 01:01:34 +08:00
|
|
|
monkeypatch.setattr(util, "_reprcompare", my_reprcompare)
|
2011-05-19 04:31:10 +08:00
|
|
|
def f():
|
|
|
|
assert 42 < 3
|
|
|
|
assert getmsg(f) == "assert 42"
|
|
|
|
def my_reprcompare(op, left, right):
|
|
|
|
return "%s %s %s" % (left, op, right)
|
2011-05-27 01:01:34 +08:00
|
|
|
monkeypatch.setattr(util, "_reprcompare", my_reprcompare)
|
2011-05-19 04:31:10 +08:00
|
|
|
def f():
|
|
|
|
assert 1 < 3 < 5 <= 4 < 7
|
|
|
|
assert getmsg(f) == "assert 5 <= 4"
|
2011-05-25 07:15:08 +08:00
|
|
|
|
|
|
|
def test_assert_raising_nonzero_in_comparison(self):
|
|
|
|
def f():
|
|
|
|
class A(object):
|
|
|
|
def __nonzero__(self):
|
|
|
|
raise ValueError(42)
|
|
|
|
def __lt__(self, other):
|
|
|
|
return A()
|
|
|
|
def __repr__(self):
|
|
|
|
return "<MY42 object>"
|
|
|
|
def myany(x):
|
|
|
|
return False
|
|
|
|
assert myany(A() < 0)
|
|
|
|
assert "<MY42 object> < 0" in getmsg(f)
|
2011-07-13 06:09:14 +08:00
|
|
|
|
2011-07-20 10:42:00 +08:00
|
|
|
def test_formatchar(self):
|
|
|
|
def f():
|
|
|
|
assert "%test" == "test"
|
|
|
|
assert getmsg(f).startswith("assert '%test' == 'test'")
|
|
|
|
|
2014-08-19 02:07:38 +08:00
|
|
|
def test_custom_repr(self):
|
|
|
|
def f():
|
|
|
|
class Foo(object):
|
|
|
|
a = 1
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
return "\n{ \n~ \n}"
|
|
|
|
f = Foo()
|
|
|
|
assert 0 == f.a
|
|
|
|
assert r"where 1 = \n{ \n~ \n}.a" in util._format_lines([getmsg(f)])[0]
|
|
|
|
|
2011-07-13 06:09:14 +08:00
|
|
|
|
|
|
|
class TestRewriteOnImport:
|
|
|
|
|
2011-07-26 10:40:38 +08:00
|
|
|
def test_pycache_is_a_file(self, testdir):
|
|
|
|
testdir.tmpdir.join("__pycache__").write("Hello")
|
|
|
|
testdir.makepyfile("""
|
2013-06-08 05:30:10 +08:00
|
|
|
def test_rewritten():
|
|
|
|
assert "@py_builtins" in globals()""")
|
2011-07-26 10:40:38 +08:00
|
|
|
assert testdir.runpytest().ret == 0
|
|
|
|
|
2013-05-29 06:11:12 +08:00
|
|
|
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("""
|
2013-06-08 05:30:10 +08:00
|
|
|
def test_rewritten():
|
|
|
|
assert "@py_builtins" in globals()""")
|
2013-05-29 06:11:12 +08:00
|
|
|
try:
|
|
|
|
assert testdir.runpytest().ret == 0
|
|
|
|
finally:
|
|
|
|
cache.chmod(old_mode)
|
|
|
|
|
2011-07-26 10:40:38 +08:00
|
|
|
def test_zipfile(self, testdir):
|
|
|
|
z = testdir.tmpdir.join("myzip.zip")
|
|
|
|
z_fn = str(z)
|
|
|
|
f = zipfile.ZipFile(z_fn, "w")
|
|
|
|
try:
|
|
|
|
f.writestr("test_gum/__init__.py", "")
|
|
|
|
f.writestr("test_gum/test_lizard.py", "")
|
|
|
|
finally:
|
|
|
|
f.close()
|
|
|
|
z.chmod(256)
|
|
|
|
testdir.makepyfile("""
|
2013-06-08 05:30:10 +08:00
|
|
|
import sys
|
|
|
|
sys.path.append(%r)
|
|
|
|
import test_gum.test_lizard""" % (z_fn,))
|
2011-07-26 10:40:38 +08:00
|
|
|
assert testdir.runpytest().ret == 0
|
|
|
|
|
2011-07-13 06:09:14 +08:00
|
|
|
def test_readonly(self, testdir):
|
|
|
|
sub = testdir.mkdir("testing")
|
2011-07-20 11:56:34 +08:00
|
|
|
sub.join("test_readonly.py").write(
|
|
|
|
py.builtin._totext("""
|
2011-07-13 06:09:14 +08:00
|
|
|
def test_rewritten():
|
2011-07-20 11:41:58 +08:00
|
|
|
assert "@py_builtins" in globals()
|
2013-06-08 05:30:10 +08:00
|
|
|
""").encode("utf-8"), "wb")
|
2013-05-29 06:11:12 +08:00
|
|
|
old_mode = sub.stat().mode
|
2011-07-13 06:09:14 +08:00
|
|
|
sub.chmod(320)
|
2013-05-29 06:11:12 +08:00
|
|
|
try:
|
|
|
|
assert testdir.runpytest().ret == 0
|
|
|
|
finally:
|
|
|
|
sub.chmod(old_mode)
|
2011-07-14 02:33:54 +08:00
|
|
|
|
|
|
|
def test_dont_write_bytecode(self, testdir, monkeypatch):
|
|
|
|
testdir.makepyfile("""
|
2013-06-08 05:30:10 +08:00
|
|
|
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__))""")
|
2011-07-14 02:33:54 +08:00
|
|
|
monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", "1")
|
|
|
|
assert testdir.runpytest().ret == 0
|
2011-08-29 22:13:00 +08:00
|
|
|
|
2012-05-22 22:20:58 +08:00
|
|
|
@pytest.mark.skipif('"__pypy__" in sys.modules')
|
2011-08-29 22:13:00 +08:00
|
|
|
def test_pyc_vs_pyo(self, testdir, monkeypatch):
|
|
|
|
testdir.makepyfile("""
|
2012-10-22 17:14:18 +08:00
|
|
|
import pytest
|
|
|
|
def test_optimized():
|
|
|
|
"hello"
|
|
|
|
assert test_optimized.__doc__ is None"""
|
|
|
|
)
|
2011-08-29 22:13:00 +08:00
|
|
|
p = py.path.local.make_numbered_dir(prefix="runpytest-", keep=None,
|
|
|
|
rootdir=testdir.tmpdir)
|
|
|
|
tmp = "--basetemp=%s" % p
|
|
|
|
monkeypatch.setenv("PYTHONOPTIMIZE", "2")
|
2012-10-22 17:14:18 +08:00
|
|
|
monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", raising=False)
|
2011-08-29 22:13:00 +08:00
|
|
|
assert testdir.runpybin("py.test", tmp).ret == 0
|
2012-07-07 23:01:44 +08:00
|
|
|
tagged = "test_pyc_vs_pyo." + PYTEST_TAG
|
|
|
|
assert tagged + ".pyo" in os.listdir("__pycache__")
|
2011-08-29 22:13:00 +08:00
|
|
|
monkeypatch.undo()
|
2012-10-22 17:14:18 +08:00
|
|
|
monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", raising=False)
|
2011-08-29 22:13:00 +08:00
|
|
|
assert testdir.runpybin("py.test", tmp).ret == 1
|
2012-07-07 23:01:44 +08:00
|
|
|
assert tagged + ".pyc" in os.listdir("__pycache__")
|
2011-08-30 12:12:07 +08:00
|
|
|
|
|
|
|
def test_package(self, testdir):
|
|
|
|
pkg = testdir.tmpdir.join("pkg")
|
|
|
|
pkg.mkdir()
|
|
|
|
pkg.join("__init__.py").ensure()
|
|
|
|
pkg.join("test_blah.py").write("""
|
|
|
|
def test_rewritten():
|
|
|
|
assert "@py_builtins" in globals()""")
|
|
|
|
assert testdir.runpytest().ret == 0
|
2011-09-21 05:53:07 +08:00
|
|
|
|
|
|
|
def test_translate_newlines(self, testdir):
|
|
|
|
content = "def test_rewritten():\r\n assert '@py_builtins' in globals()"
|
|
|
|
b = content.encode("utf-8")
|
|
|
|
testdir.tmpdir.join("test_newlines.py").write(b, "wb")
|
|
|
|
assert testdir.runpytest().ret == 0
|
2013-03-08 23:44:41 +08:00
|
|
|
|
2014-01-29 20:11:40 +08:00
|
|
|
@pytest.mark.skipif(sys.version_info < (3,3),
|
|
|
|
reason='packages without __init__.py not supported on python 2')
|
2014-01-22 21:32:22 +08:00
|
|
|
def test_package_without__init__py(self, testdir):
|
|
|
|
pkg = testdir.mkdir('a_package_without_init_py')
|
2014-01-29 17:20:13 +08:00
|
|
|
pkg.join('module.py').ensure()
|
2014-01-22 21:32:22 +08:00
|
|
|
testdir.makepyfile("import a_package_without_init_py.module")
|
|
|
|
assert testdir.runpytest().ret == 0
|
2013-08-02 04:11:18 +08:00
|
|
|
|
|
|
|
class TestAssertionRewriteHookDetails(object):
|
|
|
|
def test_loader_is_package_false_for_module(self, testdir):
|
|
|
|
testdir.makepyfile(test_fun="""
|
|
|
|
def test_loader():
|
|
|
|
assert not __loader__.is_package(__name__)
|
|
|
|
""")
|
|
|
|
result = testdir.runpytest()
|
|
|
|
result.stdout.fnmatch_lines([
|
|
|
|
"* 1 passed*",
|
|
|
|
])
|
|
|
|
|
|
|
|
def test_loader_is_package_true_for_package(self, testdir):
|
|
|
|
testdir.makepyfile(test_fun="""
|
|
|
|
def test_loader():
|
|
|
|
assert not __loader__.is_package(__name__)
|
|
|
|
|
|
|
|
def test_fun():
|
|
|
|
assert __loader__.is_package('fun')
|
|
|
|
|
|
|
|
def test_missing():
|
|
|
|
assert not __loader__.is_package('pytest_not_there')
|
|
|
|
""")
|
2013-10-12 21:39:22 +08:00
|
|
|
testdir.mkpydir('fun')
|
2013-08-02 04:11:18 +08:00
|
|
|
result = testdir.runpytest()
|
|
|
|
result.stdout.fnmatch_lines([
|
|
|
|
'* 3 passed*',
|
|
|
|
])
|
|
|
|
|
2013-03-08 23:44:41 +08:00
|
|
|
@pytest.mark.skipif("sys.version_info[0] >= 3")
|
2013-11-19 18:18:51 +08:00
|
|
|
@pytest.mark.xfail("hasattr(sys, 'pypy_translation_info')")
|
2013-03-08 23:44:41 +08:00
|
|
|
def test_assume_ascii(self, testdir):
|
2013-11-19 18:18:51 +08:00
|
|
|
content = "u'\xe2\x99\xa5\x01\xfe'"
|
2013-03-08 23:44:41 +08:00
|
|
|
testdir.tmpdir.join("test_encoding.py").write(content, "wb")
|
|
|
|
res = testdir.runpytest()
|
|
|
|
assert res.ret != 0
|
|
|
|
assert "SyntaxError: Non-ASCII character" in res.stdout.str()
|
2013-08-01 21:43:42 +08:00
|
|
|
|
2013-10-06 03:03:04 +08:00
|
|
|
@pytest.mark.skipif("sys.version_info[0] >= 3")
|
|
|
|
def test_detect_coding_cookie(self, testdir):
|
2014-03-29 03:11:33 +08:00
|
|
|
testdir.makepyfile(test_cookie="""
|
2014-03-29 00:44:18 +08:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
u"St\xc3\xa4d"
|
|
|
|
def test_rewritten():
|
2014-03-29 03:11:33 +08:00
|
|
|
assert "@py_builtins" in globals()""")
|
2013-10-06 03:16:08 +08:00
|
|
|
assert testdir.runpytest().ret == 0
|
|
|
|
|
|
|
|
@pytest.mark.skipif("sys.version_info[0] >= 3")
|
|
|
|
def test_detect_coding_cookie_second_line(self, testdir):
|
2014-03-29 03:11:33 +08:00
|
|
|
testdir.makepyfile(test_cookie="""
|
2014-03-29 00:44:18 +08:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
u"St\xc3\xa4d"
|
|
|
|
def test_rewritten():
|
2014-03-29 03:11:33 +08:00
|
|
|
assert "@py_builtins" in globals()""")
|
2013-10-06 03:03:04 +08:00
|
|
|
assert testdir.runpytest().ret == 0
|
2013-08-01 21:43:42 +08:00
|
|
|
|
2013-10-06 03:20:32 +08:00
|
|
|
@pytest.mark.skipif("sys.version_info[0] >= 3")
|
|
|
|
def test_detect_coding_cookie_crlf(self, testdir):
|
2014-03-29 03:11:33 +08:00
|
|
|
testdir.makepyfile(test_cookie="""
|
2014-03-29 00:44:18 +08:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
u"St\xc3\xa4d"
|
|
|
|
def test_rewritten():
|
2014-03-29 03:11:33 +08:00
|
|
|
assert "@py_builtins" in globals()""")
|
2013-10-06 03:20:32 +08:00
|
|
|
assert testdir.runpytest().ret == 0
|
|
|
|
|
2014-03-28 15:33:12 +08:00
|
|
|
def test_sys_meta_path_munged(self, testdir):
|
2014-03-28 16:03:52 +08:00
|
|
|
testdir.makepyfile("""
|
|
|
|
def test_meta_path():
|
|
|
|
import sys; sys.meta_path = []""")
|
2014-03-28 15:33:12 +08:00
|
|
|
assert testdir.runpytest().ret == 0
|
|
|
|
|
2013-08-01 21:43:42 +08:00
|
|
|
def test_write_pyc(self, testdir, tmpdir, monkeypatch):
|
|
|
|
from _pytest.assertion.rewrite import _write_pyc
|
|
|
|
from _pytest.assertion import AssertionState
|
|
|
|
try:
|
|
|
|
import __builtin__ as b
|
|
|
|
except ImportError:
|
|
|
|
import builtins as b
|
|
|
|
config = testdir.parseconfig([])
|
|
|
|
state = AssertionState(config, "rewrite")
|
|
|
|
source_path = tmpdir.ensure("source.py")
|
|
|
|
pycpath = tmpdir.join("pyc").strpath
|
2014-09-02 04:51:27 +08:00
|
|
|
assert _write_pyc(state, [1], source_path.stat(), pycpath)
|
2013-08-01 21:43:42 +08:00
|
|
|
def open(*args):
|
|
|
|
e = IOError()
|
|
|
|
e.errno = 10
|
|
|
|
raise e
|
|
|
|
monkeypatch.setattr(b, "open", open)
|
2014-09-02 04:51:27 +08:00
|
|
|
assert not _write_pyc(state, [1], source_path.stat(), pycpath)
|
2013-10-10 23:40:31 +08:00
|
|
|
|
|
|
|
def test_resources_provider_for_loader(self, testdir):
|
|
|
|
"""
|
|
|
|
Attempts to load resources from a package should succeed normally,
|
|
|
|
even when the AssertionRewriteHook is used to load the modules.
|
|
|
|
|
|
|
|
See #366 for details.
|
|
|
|
"""
|
|
|
|
pytest.importorskip("pkg_resources")
|
|
|
|
|
|
|
|
testdir.mkpydir('testpkg')
|
|
|
|
contents = {
|
|
|
|
'testpkg/test_pkg': """
|
|
|
|
import pkg_resources
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
from _pytest.assertion.rewrite import AssertionRewritingHook
|
|
|
|
|
|
|
|
def test_load_resource():
|
|
|
|
assert isinstance(__loader__, AssertionRewritingHook)
|
|
|
|
res = pkg_resources.resource_string(__name__, 'resource.txt')
|
2013-10-11 06:01:56 +08:00
|
|
|
res = res.decode('ascii')
|
2013-10-10 23:40:31 +08:00
|
|
|
assert res == 'Load me please.'
|
|
|
|
""",
|
|
|
|
}
|
|
|
|
testdir.makepyfile(**contents)
|
|
|
|
testdir.maketxtfile(**{'testpkg/resource': "Load me please."})
|
|
|
|
|
|
|
|
result = testdir.runpytest()
|
|
|
|
result.stdout.fnmatch_lines([
|
|
|
|
'* 1 passed*',
|
|
|
|
])
|
2014-08-03 05:01:28 +08:00
|
|
|
|
|
|
|
def test_read_pyc(self, tmpdir):
|
|
|
|
"""
|
|
|
|
Ensure that the `_read_pyc` can properly deal with corrupted pyc files.
|
|
|
|
In those circumstances it should just give up instead of generating
|
|
|
|
an exception that is propagated to the caller.
|
|
|
|
"""
|
|
|
|
import py_compile
|
|
|
|
from _pytest.assertion.rewrite import _read_pyc
|
|
|
|
|
|
|
|
source = tmpdir.join('source.py')
|
|
|
|
pyc = source + 'c'
|
|
|
|
|
|
|
|
source.write('def test(): pass')
|
|
|
|
py_compile.compile(str(source), str(pyc))
|
|
|
|
|
|
|
|
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')
|
|
|
|
|
|
|
|
assert _read_pyc(source, str(pyc)) is None # no error
|
2015-03-04 23:21:27 +08:00
|
|
|
|
|
|
|
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(py.std.textwrap.dedent("""
|
|
|
|
[pytest]
|
|
|
|
python_files = *.py
|
|
|
|
"""))
|
|
|
|
|
|
|
|
testdir.makepyfile(test_fun="""
|
|
|
|
import sys
|
|
|
|
try:
|
|
|
|
from imp import reload
|
|
|
|
except ImportError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
def test_loader():
|
|
|
|
import file
|
|
|
|
assert sys.modules["file"] is reload(file)
|
|
|
|
""")
|
|
|
|
result = testdir.runpytest('-s')
|
|
|
|
result.stdout.fnmatch_lines([
|
|
|
|
"* 1 passed*",
|
|
|
|
])
|