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
|
from flaky.defaults import default_flaky_attributes
def flaky(max_runs=None, min_passes=None, rerun_filter=None):
"""
Decorator used to mark a test as "flaky".
:param max_runs:
The maximum number of times the decorated test will be run.
:type max_runs:
`int`
:param min_passes:
The minimum number of times the test must pass to be a success.
:type min_passes:
`int`
:param rerun_filter:
Filter function to decide whether a test should be rerun if it fails.
Function signature is as follows:
(err, name, test, plugin) -> should_rerun
- err (`tuple` of `class`, :class:`Exception`, `traceback`):
Information about the test failure (from sys.exc_info())
- name (`unicode`):
The test name
- test (:class:`Function`):
The test that has raised an error
- plugin (:class:`FlakyPytestPlugin`):
The flaky plugin. Has a :prop:`stream` that can be written to in
order to add to the Flaky Report.
:type rerun_filter:
`callable`
:return:
A wrapper function that includes attributes describing the flaky test.
:rtype:
`callable`
"""
# In case @flaky is applied to a function or class without arguments
# (and without parentheses), max_runs will refer to the wrapped object.
# In this case, the default value can be used.
wrapped = None
if hasattr(max_runs, '__call__'):
wrapped, max_runs = max_runs, None
attrib = default_flaky_attributes(max_runs, min_passes, rerun_filter)
def wrapper(wrapped_object):
for name, value in attrib.items():
setattr(wrapped_object, name, value)
return wrapped_object
return wrapper(wrapped) if wrapped is not None else wrapper
|