Skip to content

Commit 43e5e25

Browse files
authored
Merge pull request #1114 from newrelic/mute-flakey-tests
Retry flakey tests
2 parents f233c6f + 2323a71 commit 43e5e25

File tree

3 files changed

+37
-7
lines changed

3 files changed

+37
-7
lines changed

tests/agent_features/test_priority_sampling.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
override_application_settings,
1919
reset_core_stats_engine,
2020
)
21+
from testing_support.util import retry
2122

2223
from newrelic.api.application import application_instance as application
2324
from newrelic.api.background_task import BackgroundTask
@@ -29,6 +30,7 @@ def test_priority_used_in_transaction_events(first_transaction_saved):
2930
first_priority = 1 if first_transaction_saved else 0
3031
second_priority = 0 if first_transaction_saved else 1
3132

33+
@retry(attempts=5, wait=2) # This test is flakey so add a retry.
3234
@reset_core_stats_engine()
3335
def _test():
3436
# Stats engine
@@ -61,6 +63,7 @@ def test_priority_used_in_transaction_error_events(first_transaction_saved):
6163
first_priority = 1 if first_transaction_saved else 0
6264
second_priority = 0 if first_transaction_saved else 1
6365

66+
@retry(attempts=5, wait=2) # This test is flakey so add a retry.
6467
@reset_core_stats_engine()
6568
def _test():
6669
with BackgroundTask(application(), name="T1") as txn:

tests/agent_streaming/test_infinite_tracing.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
import pytest
1919
from testing_support.fixtures import override_generic_settings
20-
from testing_support.util import conditional_decorator
20+
from testing_support.util import conditional_decorator, retry
2121
from testing_support.validators.validate_metric_payload import validate_metric_payload
2222

2323
from newrelic.common.streaming_utils import StreamBuffer
@@ -281,9 +281,8 @@ def condition(*args, **kwargs):
281281
_create_channel = StreamingRpc.create_channel
282282

283283
def create_channel(self, *args, **kwargs):
284-
ret = _create_channel(self, *args, **kwargs)
284+
_create_channel(self, *args, **kwargs)
285285
connect_event.set()
286-
return ret
287286

288287
monkeypatch.setattr(StreamingRpc, "condition", condition)
289288
monkeypatch.setattr(StreamingRpc, "create_channel", create_channel)
@@ -356,6 +355,7 @@ def test_no_data_loss_on_reconnect(mock_grpc_server, app, buffer_empty_event, ba
356355

357356
span = Span(intrinsics={}, agent_attributes={}, user_attributes={})
358357

358+
@retry(attempts=5, wait=2) # This test is flakey so add a retry.
359359
@override_generic_settings(
360360
settings,
361361
{

tests/testing_support/util.py

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,15 @@
1414

1515
import re
1616
import socket
17+
import time
18+
from functools import wraps
19+
1720

1821
def _to_int(version_str):
19-
m = re.match(r'\d+', version_str)
22+
m = re.match(r"\d+", version_str)
2023
return int(m.group(0)) if m else 0
2124

25+
2226
def version2tuple(version_str):
2327
"""Convert version, even if it contains non-numeric chars.
2428
@@ -27,32 +31,55 @@ def version2tuple(version_str):
2731
2832
"""
2933

30-
parts = version_str.split('.')[:2]
34+
parts = version_str.split(".")[:2]
3135
return tuple(map(_to_int, parts))
3236

37+
3338
def instance_hostname(hostname):
34-
if hostname == 'localhost' or hostname == "127.0.0.1":
39+
if hostname in ["localhost", "127.0.0.1"]:
3540
hostname = socket.gethostname()
3641
return hostname
3742

43+
3844
def get_open_port():
3945
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
4046
s.bind(("", 0))
4147
port = s.getsockname()[1]
4248
s.close()
4349
return port
4450

51+
4552
def conditional_decorator(condition, decorator):
4653
"""Applies a decorator if the condition is true. Accepts 0 argument callables for the condition."""
54+
4755
def _conditional_decorator(func):
4856
if callable(condition):
4957
condition_eval = condition()
5058
else:
5159
condition_eval = condition
52-
60+
5361
if condition_eval:
5462
return decorator(func)
5563
else:
5664
return func
5765

5866
return _conditional_decorator
67+
68+
69+
def retry(attempts=5, wait=5):
70+
def decorator(test_func):
71+
@wraps(test_func)
72+
def wrapper(*args, **kwargs):
73+
retry_count = 1
74+
while retry_count < attempts:
75+
try:
76+
return test_func(*args, **kwargs)
77+
except AssertionError as assert_error:
78+
time.sleep(wait)
79+
retry_count += 1
80+
# Preserve original traceback in case assertion fails.
81+
return test_func(*args, **kwargs)
82+
83+
return wrapper
84+
85+
return decorator

0 commit comments

Comments
 (0)