Skip to content

Instantly share code, notes, and snippets.

@adiroiban
Created March 24, 2018 22:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adiroiban/9e42ededc114eed3f59ead3e2968aa0f to your computer and use it in GitHub Desktop.
Save adiroiban/9e42ededc114eed3f59ead3e2968aa0f to your computer and use it in GitHub Desktop.
flaky decorator
def flaky(count=3, os_version=None):
"""
A decorator generator to retry a test if it fails in one of the OS from
`os_version`.
When `os_version` is None it will retry on any OS.
It will not work with any tests.
The setUp and tearDown is only called once and not called between
retries.
The cleanups are called between retries.
"""
def decorator(test_item):
"""
This is the actual decorator.
"""
@wraps(test_item)
def wrapper(self):
"""
Wrap the test method to execute it multiple times.
"""
error = None
for _ in range(count): # pragma: no branch
try:
test_item(self)
# All good. Stop trying.
return
except AssertionError as error: # noqa:cover
if (
os_version and
ServerTestCase.os_version not in os_version
):
# The current OS is not targed as flaky, so fail
# right away.
raise error
try:
# Run cleanup and try again.
self.callCleanup()
except Exception:
"""
Just ignore any cleanup error which occurred for a
failed tests.
If the tests succeeds, the cleanup is not called
from here, but as part of the normal test run.
"""
# Let the other thread to execute.
time.sleep(0.5)
# We tried 3 times and still got a failure.
raise error # noqa:cover
return wrapper
return decorator
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment