-
Notifications
You must be signed in to change notification settings - Fork 13
/
pytest.py
130 lines (102 loc) · 4.1 KB
/
pytest.py
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
from __future__ import absolute_import
from inspect import getsourcefile
from os.path import abspath
from _pytest._code.code import TerminalRepr, Traceback
from _pytest import fixtures
from _pytest.fixtures import FuncFixtureInfo
from _pytest.main import Session
from _pytest.python import Module
import py.path
import pytest
from ..example import SybilFailure
from .. import example
example_module_path = abspath(getsourcefile(example))
class SybilFailureRepr(TerminalRepr):
def __init__(self, item, message):
self.item = item
self.message = message
def toterminal(self, tw):
tw.line()
for line in self.message.splitlines():
tw.line(line)
tw.line()
tw.write(self.item.parent.name, bold=True, red=True)
tw.line(":%s: SybilFailure" % self.item.example.line)
class SybilItem(pytest.Item):
def __init__(self, parent, sybil, example):
name = 'line:{},column:{}'.format(example.line, example.column)
super(SybilItem, self).__init__(name, parent)
self.example = example
self.request_fixtures(sybil.fixtures)
def request_fixtures(self, names):
# pytest fixtures dance:
fm = self.session._fixturemanager
closure = fm.getfixtureclosure(names, self)
try:
initialnames, names_closure, arg2fixturedefs = closure
except ValueError: # pragma: no cover
# pytest < 3.7
names_closure, arg2fixturedefs = closure
fixtureinfo = FuncFixtureInfo(names, names_closure, arg2fixturedefs)
else:
# pyest >= 3.7
fixtureinfo = FuncFixtureInfo(names, initialnames, names_closure, arg2fixturedefs)
self._fixtureinfo = fixtureinfo
self.funcargs = {}
self._request = fixtures.FixtureRequest(self)
def reportinfo(self):
info = '%s line=%i column=%i' % (
self.fspath.basename, self.example.line, self.example.column
)
return py.path.local(self.example.document.path), self.example.line, info
def getparent(self, cls):
if cls is Module:
return self.parent
if cls is Session:
return self.session
def setup(self):
fixtures.fillfixtures(self)
for name, fixture in self.funcargs.items():
self.example.namespace[name] = fixture
def runtest(self):
self.example.evaluate()
def _prunetraceback(self, excinfo):
# Messier than it could be because slicing a list subclass in
# Python 2 returns a list, not an instance of the subclass.
tb = excinfo.traceback.cut(path=example_module_path)
tb = tb[1]
if getattr(tb, '_rawentry', None) is not None:
excinfo.traceback = Traceback(tb._rawentry, excinfo)
def repr_failure(self, excinfo):
if isinstance(excinfo.value, SybilFailure):
return SybilFailureRepr(self, str(excinfo.value))
return super(SybilItem, self).repr_failure(excinfo)
class SybilFile(pytest.File):
def __init__(self, fspath, parent, sybil):
super(SybilFile, self).__init__(fspath, parent)
self.sybil = sybil
def collect(self):
self.document = self.sybil.parse(self.fspath.strpath)
for example in self.document:
try:
from_parent = SybilItem.from_parent
except AttributeError:
yield SybilItem(self, self.sybil, example)
else:
yield from_parent(self, sybil=self.sybil, example=example)
def setup(self):
if self.sybil.setup:
self.sybil.setup(self.document.namespace)
def teardown(self):
if self.sybil.teardown:
self.sybil.teardown(self.document.namespace)
def pytest_integration(sybil, class_=SybilFile):
def pytest_collect_file(parent, path):
if sybil.should_test_path(path):
try:
from_parent = class_.from_parent
except AttributeError:
return class_(path, parent, sybil)
else:
return from_parent(parent, fspath=path, sybil=sybil)
return pytest_collect_file