1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
|
# mypy: allow-untyped-defs
from __future__ import annotations
import re
import sys
from types import FrameType
from unittest import mock
from _pytest._code import Code
from _pytest._code import ExceptionInfo
from _pytest._code import Frame
from _pytest._code import Source
from _pytest._code.code import ExceptionChainRepr
from _pytest._code.code import ReprFuncArgs
import pytest
def test_ne() -> None:
code1 = Code(compile('foo = "bar"', "", "exec"))
assert code1 == code1
code2 = Code(compile('foo = "baz"', "", "exec"))
assert code2 != code1
def test_code_gives_back_name_for_not_existing_file() -> None:
name = "abc-123"
co_code = compile("pass\n", name, "exec")
assert co_code.co_filename == name
code = Code(co_code)
assert str(code.path) == name
assert code.fullsource is None
def test_code_from_function_with_class() -> None:
class A:
pass
with pytest.raises(TypeError):
Code.from_function(A)
def x() -> None:
raise NotImplementedError()
def test_code_fullsource() -> None:
code = Code.from_function(x)
full = code.fullsource
assert "test_code_fullsource()" in str(full)
def test_code_source() -> None:
code = Code.from_function(x)
src = code.source()
expected = """def x() -> None:
raise NotImplementedError()"""
assert str(src) == expected
def test_frame_getsourcelineno_myself() -> None:
def func() -> FrameType:
return sys._getframe(0)
f = Frame(func())
source, lineno = f.code.fullsource, f.lineno
assert source is not None
assert source[lineno].startswith(" return sys._getframe(0)")
def test_getstatement_empty_fullsource() -> None:
def func() -> FrameType:
return sys._getframe(0)
f = Frame(func())
with mock.patch.object(f.code.__class__, "fullsource", None):
assert f.statement == Source("")
def test_code_from_func() -> None:
co = Code.from_function(test_frame_getsourcelineno_myself)
assert co.firstlineno
assert co.path
def test_unicode_handling() -> None:
value = "ąć".encode()
def f() -> None:
raise ValueError(value)
excinfo = pytest.raises(ValueError, f)
str(excinfo)
def test_code_getargs() -> None:
def f1(x):
raise NotImplementedError()
c1 = Code.from_function(f1)
assert c1.getargs(var=True) == ("x",)
def f2(x, *y):
raise NotImplementedError()
c2 = Code.from_function(f2)
assert c2.getargs(var=True) == ("x", "y")
def f3(x, **z):
raise NotImplementedError()
c3 = Code.from_function(f3)
assert c3.getargs(var=True) == ("x", "z")
def f4(x, *y, **z):
raise NotImplementedError()
c4 = Code.from_function(f4)
assert c4.getargs(var=True) == ("x", "y", "z")
def test_frame_getargs() -> None:
def f1(x) -> FrameType:
return sys._getframe(0)
fr1 = Frame(f1("a"))
assert fr1.getargs(var=True) == [("x", "a")]
def f2(x, *y) -> FrameType:
return sys._getframe(0)
fr2 = Frame(f2("a", "b", "c"))
assert fr2.getargs(var=True) == [("x", "a"), ("y", ("b", "c"))]
def f3(x, **z) -> FrameType:
return sys._getframe(0)
fr3 = Frame(f3("a", b="c"))
assert fr3.getargs(var=True) == [("x", "a"), ("z", {"b": "c"})]
def f4(x, *y, **z) -> FrameType:
return sys._getframe(0)
fr4 = Frame(f4("a", "b", c="d"))
assert fr4.getargs(var=True) == [("x", "a"), ("y", ("b",)), ("z", {"c": "d"})]
class TestExceptionInfo:
def test_bad_getsource(self) -> None:
try:
if False:
pass
else:
assert False
except AssertionError:
exci = ExceptionInfo.from_current()
assert exci.getrepr()
def test_from_current_with_missing(self) -> None:
with pytest.raises(AssertionError, match="no current exception"):
ExceptionInfo.from_current()
class TestTracebackEntry:
def test_getsource(self) -> None:
try:
if False:
pass
else:
assert False
except AssertionError:
exci = ExceptionInfo.from_current()
entry = exci.traceback[0]
source = entry.getsource()
assert source is not None
assert len(source) == 6
assert "assert False" in source[5]
def test_tb_entry_str(self):
try:
assert False
except AssertionError:
exci = ExceptionInfo.from_current()
pattern = r" File '.*test_code.py':\d+ in test_tb_entry_str\n assert False"
entry = str(exci.traceback[0])
assert re.match(pattern, entry)
class TestReprFuncArgs:
def test_not_raise_exception_with_mixed_encoding(self, tw_mock) -> None:
args = [("unicode_string", "São Paulo"), ("utf8_string", b"S\xc3\xa3o Paulo")]
r = ReprFuncArgs(args)
r.toterminal(tw_mock)
assert (
tw_mock.lines[0]
== r"unicode_string = São Paulo, utf8_string = b'S\xc3\xa3o Paulo'"
)
def test_ExceptionChainRepr():
"""Test ExceptionChainRepr, especially with regard to being hashable."""
try:
raise ValueError()
except ValueError:
excinfo1 = ExceptionInfo.from_current()
excinfo2 = ExceptionInfo.from_current()
repr1 = excinfo1.getrepr()
repr2 = excinfo2.getrepr()
assert repr1 != repr2
assert isinstance(repr1, ExceptionChainRepr)
assert hash(repr1) != hash(repr2)
assert repr1 is not excinfo1.getrepr()
|