1 # Copyright (c) Microsoft Corporation. All rights reserved.
2 # Licensed under the MIT License.
4 from collections import namedtuple
7 class TestPath(namedtuple('TestPath', 'root relfile func sub')):
8 """Where to find a single test."""
10 def __new__(cls, root, relfile, func, sub=None):
11 self = super(TestPath, cls).__new__(
13 str(root) if root else None,
14 str(relfile) if relfile else None,
15 str(func) if func else None,
16 [str(s) for s in sub] if sub else None,
20 def __init__(self, *args, **kwargs):
22 raise TypeError('missing id')
23 if self.relfile is None:
24 raise TypeError('missing kind')
25 # self.func may be None (e.g. for doctests).
26 # self.sub may be None.
29 class ParentInfo(namedtuple('ParentInfo', 'id kind name root parentid')):
31 KINDS = ('folder', 'file', 'suite', 'function', 'subtest')
33 def __new__(cls, id, kind, name, root=None, parentid=None):
34 self = super(ParentInfo, cls).__new__(
36 str(id) if id else None,
37 str(kind) if kind else None,
38 str(name) if name else None,
39 str(root) if root else None,
40 str(parentid) if parentid else None,
44 def __init__(self, *args, **kwargs):
46 raise TypeError('missing id')
48 raise TypeError('missing kind')
49 if self.kind not in self.KINDS:
50 raise ValueError('unsupported kind {!r}'.format(self.kind))
52 raise TypeError('missing name')
54 if self.parentid is not None or self.kind != 'folder':
55 raise TypeError('missing root')
56 elif self.parentid is None:
57 raise TypeError('missing parentid')
60 class TestInfo(namedtuple('TestInfo', 'id name path source markers parentid kind')):
61 """Info for a single test."""
63 MARKERS = ('skip', 'skip-if', 'expected-failure')
64 KINDS = ('function', 'doctest')
66 def __new__(cls, id, name, path, source, markers, parentid, kind='function'):
67 self = super(TestInfo, cls).__new__(
69 str(id) if id else None,
70 str(name) if name else None,
72 str(source) if source else None,
73 [str(marker) for marker in markers or ()],
74 str(parentid) if parentid else None,
75 str(kind) if kind else None,
79 def __init__(self, *args, **kwargs):
81 raise TypeError('missing id')
83 raise TypeError('missing name')
85 raise TypeError('missing path')
86 if self.source is None:
87 raise TypeError('missing source')
89 srcfile, _, lineno = self.source.rpartition(':')
90 if not srcfile or not lineno or int(lineno) < 0:
91 raise ValueError('bad source {!r}'.format(self.source))
93 badmarkers = [m for m in self.markers if m not in self.MARKERS]
95 raise ValueError('unsupported markers {!r}'.format(badmarkers))
96 if self.parentid is None:
97 raise TypeError('missing parentid')
99 raise TypeError('missing kind')
100 elif self.kind not in self.KINDS:
101 raise ValueError('unsupported kind {!r}'.format(self.kind))
106 return self.path.root
110 return self.source.rpartition(':')[0]
114 return int(self.source.rpartition(':')[-1])