-
Notifications
You must be signed in to change notification settings - Fork 24
/
exemptions.py
159 lines (134 loc) · 4.67 KB
/
exemptions.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
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
from collections import defaultdict
from datetime import date
import re
import warnings
import pytest
def load(rules):
"""Marks tests as xfail based on test name and ID.
Parses the exemptions section of the conf file and returns a two level dict with format:
{<test_name>:
{<test_id>: (<exemption expiration>, <exemption reason>)
...
}
...
}
Examples:
>>> load([
... {
... 'test_name': 'test_foo',
... 'test_param_id': 'foo-id',
... 'expiration_day': date(2050, 1, 1),
... 'reason': 'in prod never allow foo'
... }
... ]) == {'test_foo': {'foo-id': ('2050-01-01', 'in prod never allow foo')}}
True
>>> load([
... {
... 'test_name': '*test_foo',
... 'test_param_id': 'foo-id',
... 'expiration_day': date(2050, 1, 1),
... 'reason': 'in prod never allow foo'
... }
... ]) == {'*test_foo': {'foo-id': ('2050-01-01', 'in prod never allow foo')}}
True
>>> load([
... {
... 'test_name': 'test_foo',
... 'test_param_id': 'foo-id',
... 'expiration_day': date(2050, 1, 1),
... 'reason': 'in prod never allow foo'
... },
... {
... 'test_name': 'test_foo',
... 'test_param_id': 'bar-id',
... 'expiration_day': date(2050, 1, 1),
... 'reason': 'in prod never allow bar'
... }
... ]) == {
... 'test_foo': {
... 'foo-id': ('2050-01-01', 'in prod never allow foo'),
... 'bar-id': ('2050-01-01', 'in prod never allow bar')}}
True
Duplicate test name and IDs are ignored with a warning:
>>> load([
... {
... 'test_name': 'test_foo',
... 'test_param_id': 'foo-id',
... 'expiration_day': date(2050, 1, 1),
... 'reason': 'in prod never allow foo'
... },
... {
... 'test_name': 'test_foo',
... 'test_param_id': 'foo-id',
... 'expiration_day': date(2051, 1, 1),
... 'reason': 'in prod never allow foo another'
... }
... ]) == {'test_foo': {'foo-id': ('2050-01-01', 'in prod never allow foo')}}
True
>>> # UserWarning: Exemptions: test_name: test_foo | test_id: foo-id | Skipping duplicate test name and ID
Does not check that test name and IDs exist (since names might not
be collected and IDs can require an HTTP call).
"""
processed_rules = defaultdict(dict)
if not rules:
return processed_rules
for rule in rules:
test_name, test_id = rule["test_name"], rule["test_param_id"]
expiration, reason = rule["expiration_day"], rule["reason"]
if expiration < date.today():
warnings.warn(
"Exemptions: test_name: {} | test_id: {} | Skipping rule with expiration day in the past {!r}".format(
test_name, test_id, expiration
)
)
continue
if test_id in processed_rules[test_name]:
warnings.warn(
"Exemptions: test_name: {} | test_id: {} | Skipping duplicate test name and ID".format(
test_name, test_id
)
)
continue
processed_rules[test_name][test_id] = (str(expiration), reason)
return processed_rules
def add_xfail_marker(item):
"""
Adds xfail markers for test names and ids specified in the exemptions conf.
"""
if not item.get_closest_marker("parametrize"):
warnings.warn(
"Skipping exemption checks for test without resource name {!r}".format(
item.name
)
)
return
test_exemptions = item.config.custom_config.exemptions.get(item.originalname, None)
test_id = item.name
try:
# test_admin_user_is_inactive[gsuiteuser@example.com]
test_id = item.name.split("[")[1][:-1]
except IndexError:
warnings.warn(
"Exemption check failed: was unable to parse parametrized test name:",
item.name,
)
return
if test_exemptions:
if test_id in test_exemptions:
expiration, reason = test_exemptions[test_id]
item.add_marker(
pytest.mark.xfail(reason=reason, strict=True, expiration=expiration)
)
return
# Check for any substring matchers
for exemption_test_id in test_exemptions:
if exemption_test_id.startswith("*"):
substring = exemption_test_id[1:]
if re.search(substring, test_id):
expiration, reason = test_exemptions[exemption_test_id]
item.add_marker(
pytest.mark.xfail(
reason=reason, strict=True, expiration=expiration
)
)
return