22
22
"monitor_test_if" : (True , "monitor_force_test" , lambda x : bool (x ), False ),
23
23
}
24
24
PYTEST_MONITOR_DEPRECATED_MARKERS = {}
25
- PYTEST_MONITOR_ITEM_LOC_MEMBER = "_location" if tuple (pytest .__version__ .split ("." )) < ("5" , "3" ) else "location"
25
+ PYTEST_MONITOR_ITEM_LOC_MEMBER = (
26
+ "_location" if tuple (pytest .__version__ .split ("." )) < ("5" , "3" ) else "location"
27
+ )
26
28
27
29
PYTEST_MONITORING_ENABLED = True
28
30
@@ -44,7 +46,9 @@ def pytest_addoption(parser):
44
46
help = "Set this option to distinguish parametrized tests given their values."
45
47
" This requires the parameters to be stringifiable." ,
46
48
)
47
- group .addoption ("--no-monitor" , action = "store_true" , dest = "mtr_none" , help = "Disable all traces" )
49
+ group .addoption (
50
+ "--no-monitor" , action = "store_true" , dest = "mtr_none" , help = "Disable all traces"
51
+ )
48
52
group .addoption (
49
53
"--remote-server" ,
50
54
action = "store" ,
@@ -68,13 +72,15 @@ def pytest_addoption(parser):
68
72
"--force-component" ,
69
73
action = "store" ,
70
74
dest = "mtr_force_component" ,
71
- help = "Force the component to be set at the given value for the all tests run" " in this session." ,
75
+ help = "Force the component to be set at the given value for the all tests run"
76
+ " in this session." ,
72
77
)
73
78
group .addoption (
74
79
"--component-prefix" ,
75
80
action = "store" ,
76
81
dest = "mtr_component_prefix" ,
77
- help = "Prefix each found components with the given value (applies to all tests" " run in this session)." ,
82
+ help = "Prefix each found components with the given value (applies to all tests"
83
+ " run in this session)." ,
78
84
)
79
85
group .addoption (
80
86
"--no-gc" ,
@@ -99,10 +105,13 @@ def pytest_addoption(parser):
99
105
100
106
101
107
def pytest_configure (config ):
102
- config .addinivalue_line ("markers" , "monitor_skip_test: mark test to be executed but not monitored." )
108
+ config .addinivalue_line (
109
+ "markers" , "monitor_skip_test: mark test to be executed but not monitored."
110
+ )
103
111
config .addinivalue_line (
104
112
"markers" ,
105
- "monitor_skip_test_if(cond): mark test to be executed but " "not monitored if cond is verified." ,
113
+ "monitor_skip_test_if(cond): mark test to be executed but "
114
+ "not monitored if cond is verified." ,
106
115
)
107
116
config .addinivalue_line (
108
117
"markers" ,
@@ -126,14 +135,24 @@ def pytest_runtest_setup(item):
126
135
"""
127
136
if not PYTEST_MONITORING_ENABLED :
128
137
return
129
- item_markers = {mark .name : mark for mark in item .iter_markers () if mark and mark .name .startswith ("monitor_" )}
138
+ item_markers = {
139
+ mark .name : mark
140
+ for mark in item .iter_markers ()
141
+ if mark and mark .name .startswith ("monitor_" )
142
+ }
130
143
mark_to_del = []
131
144
for set_marker in item_markers .keys ():
132
145
if set_marker not in PYTEST_MONITOR_VALID_MARKERS :
133
- warnings .warn ("Nothing known about marker {}. Marker will be dropped." .format (set_marker ))
146
+ warnings .warn (
147
+ "Nothing known about marker {}. Marker will be dropped." .format (
148
+ set_marker
149
+ )
150
+ )
134
151
mark_to_del .append (set_marker )
135
152
if set_marker in PYTEST_MONITOR_DEPRECATED_MARKERS :
136
- warnings .warn (f"Marker { set_marker } is deprecated. Consider upgrading your tests" )
153
+ warnings .warn (
154
+ f"Marker { set_marker } is deprecated. Consider upgrading your tests"
155
+ )
137
156
138
157
for marker in mark_to_del :
139
158
del item_markers [marker ]
@@ -201,11 +220,20 @@ def wrapped_function():
201
220
pyfuncitem .obj (** testargs )
202
221
except Exception :
203
222
raise
204
- except BaseException :
205
- raise
223
+ except BaseException as e :
224
+ # this is a workaround to fix the faulty behavior of the memory profiler
225
+ # that only catches Exceptions but should catch BaseExceptions instead
226
+ # actually BaseExceptions should be raised here, but without modifications
227
+ # of the memory profiler (like proposed in PR
228
+ # https://github.com/CFMTech/pytest-monitor/pull/82 ) this problem
229
+ # can just be worked around like so (BaseException can only come through
230
+ # this way)
231
+ return e
206
232
207
233
def prof ():
208
- m = memory_profiler .memory_usage ((wrapped_function , ()), max_iterations = 1 , max_usage = True , retval = True )
234
+ m = memory_profiler .memory_usage (
235
+ (wrapped_function , ()), max_iterations = 1 , max_usage = True , retval = True
236
+ )
209
237
if isinstance (m [1 ], BaseException ): # Do we have any outcome?
210
238
raise m [1 ]
211
239
memuse = m [0 ][0 ] if type (m [0 ]) is list else m [0 ]
@@ -214,9 +242,13 @@ def prof():
214
242
215
243
if not PYTEST_MONITORING_ENABLED :
216
244
try :
217
- wrapped_function ()
245
+ # this is a workaround to fix the faulty behavior of the memory profiler
246
+ # that only catches Exceptions but should catch BaseExceptions instead
247
+ e = wrapped_function ()
248
+ if isinstance (e , BaseException ):
249
+ raise e
218
250
except BaseException :
219
- raise
251
+ raise
220
252
else :
221
253
if not pyfuncitem .session .config .option .mtr_disable_gc :
222
254
gc .collect ()
@@ -236,12 +268,26 @@ def pytest_sessionstart(session):
236
268
Instantiate a monitor session to save collected metrics.
237
269
We yield at the end to let pytest pursue the execution.
238
270
"""
239
- if session .config .option .mtr_force_component and session .config .option .mtr_component_prefix :
240
- raise pytest .UsageError ("Invalid usage: --force-component and --component-prefix are incompatible options!" )
241
- if session .config .option .mtr_no_db and not session .config .option .mtr_remote and not session .config .option .mtr_none :
242
- warnings .warn ("pytest-monitor: No storage specified but monitoring is requested. Disabling monitoring." )
271
+ if (
272
+ session .config .option .mtr_force_component
273
+ and session .config .option .mtr_component_prefix
274
+ ):
275
+ raise pytest .UsageError (
276
+ "Invalid usage: --force-component and --component-prefix are incompatible options!"
277
+ )
278
+ if (
279
+ session .config .option .mtr_no_db
280
+ and not session .config .option .mtr_remote
281
+ and not session .config .option .mtr_none
282
+ ):
283
+ warnings .warn (
284
+ "pytest-monitor: No storage specified but monitoring is requested. Disabling monitoring."
285
+ )
243
286
session .config .option .mtr_none = True
244
- component = session .config .option .mtr_force_component or session .config .option .mtr_component_prefix
287
+ component = (
288
+ session .config .option .mtr_force_component
289
+ or session .config .option .mtr_component_prefix
290
+ )
245
291
if session .config .option .mtr_component_prefix :
246
292
component += ".{user_component}"
247
293
if not component :
@@ -251,13 +297,17 @@ def pytest_sessionstart(session):
251
297
if (session .config .option .mtr_none or session .config .option .mtr_no_db )
252
298
else session .config .option .mtr_db_out
253
299
)
254
- remote = None if session .config .option .mtr_none else session .config .option .mtr_remote
300
+ remote = (
301
+ None if session .config .option .mtr_none else session .config .option .mtr_remote
302
+ )
255
303
session .pytest_monitor = PyTestMonitorSession (
256
304
db = db , remote = remote , component = component , scope = session .config .option .mtr_scope
257
305
)
258
306
global PYTEST_MONITORING_ENABLED
259
307
PYTEST_MONITORING_ENABLED = not session .config .option .mtr_none
260
- session .pytest_monitor .compute_info (session .config .option .mtr_description , session .config .option .mtr_tags )
308
+ session .pytest_monitor .compute_info (
309
+ session .config .option .mtr_description , session .config .option .mtr_tags
310
+ )
261
311
yield
262
312
263
313
@@ -298,7 +348,9 @@ def _prf_tracer(request):
298
348
ptimes_a = request .session .pytest_monitor .process .cpu_times ()
299
349
yield
300
350
ptimes_b = request .session .pytest_monitor .process .cpu_times ()
301
- if not request .node .monitor_skip_test and getattr (request .node , "monitor_results" , False ):
351
+ if not request .node .monitor_skip_test and getattr (
352
+ request .node , "monitor_results" , False
353
+ ):
302
354
item_name = request .node .originalname or request .node .name
303
355
item_loc = getattr (request .node , PYTEST_MONITOR_ITEM_LOC_MEMBER )[0 ]
304
356
request .session .pytest_monitor .add_test_info (
0 commit comments