Skip to content

Commit 5430ee2

Browse files
committed
add a required reason parameter
1 parent e7da55b commit 5430ee2

19 files changed

+48
-66
lines changed

CONTRIBUTING.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -406,10 +406,10 @@ If you are running one of the `no-responder` tests, omit the `run-server` step.
406406

407407
## Handling flaky tests
408408

409-
We have a custom ``flaky`` decorator in [test/asynchronous/utils.py](test/asynchronous/utils.py) that can be used for
410-
tests that are ``flaky``. By default the decorator only applies when not running on CPython on Linux, since other
411-
runtimes tend to have more variation. When using the ``flaky`` decorator, open a corresponding ticket and
412-
a comment with the ticket number.
409+
We have a custom `flaky` decorator in [test/asynchronous/utils.py](test/asynchronous/utils.py) that can be used for
410+
tests that are `flaky`. By default the decorator only applies when not running on CPython on Linux, since other
411+
runtimes tend to have more variation. When using the `flaky` decorator, open a corresponding ticket and
412+
a use the ticket number as the "reason" parameter to the decorator, e.g. `@flaky(reason="PYTHON-1234")`.
413413

414414
## Specification Tests
415415

test/asynchronous/test_client_bulk_write.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -627,8 +627,7 @@ async def asyncSetUp(self):
627627

628628
@async_client_context.require_version_min(8, 0, 0, -24)
629629
@async_client_context.require_failCommand_fail_point
630-
# PYTHON-5290
631-
@flaky(max_runs=3, affects_cpython_linux=True)
630+
@flaky(reason="PYTHON-5290", max_runs=3, affects_cpython_linux=True)
632631
async def test_timeout_in_multi_batch_bulk_write(self):
633632
if sys.platform != "linux":
634633
self.skipTest("PYTHON-3522 CSOT test runs too slow on Windows and MacOS")

test/asynchronous/test_csot.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
class TestCSOT(AsyncIntegrationTest):
4545
RUN_ON_LOAD_BALANCER = True
4646

47-
@flaky # PYTHON-3522
47+
@flaky(reason="PYTHON-3522")
4848
async def test_timeout_nested(self):
4949
coll = self.db.coll
5050
self.assertEqual(_csot.get_timeout(), None)
@@ -82,7 +82,7 @@ async def test_timeout_nested(self):
8282
self.assertEqual(_csot.get_rtt(), 0.0)
8383

8484
@async_client_context.require_change_streams
85-
@flaky # PYTHON-3522
85+
@flaky(reason="PYTHON-3522")
8686
async def test_change_stream_can_resume_after_timeouts(self):
8787
coll = self.db.test
8888
await coll.insert_one({})

test/asynchronous/test_cursor.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,7 +1416,7 @@ async def test_to_list_length(self):
14161416
docs = await c.to_list(3)
14171417
self.assertEqual(len(docs), 2)
14181418

1419-
@flaky # PYTHON-3522
1419+
@flaky(reason="PYTHON-3522")
14201420
async def test_to_list_csot_applied(self):
14211421
client = await self.async_single_client(timeoutMS=500, w=1)
14221422
coll = client.pymongo.test
@@ -1458,7 +1458,7 @@ async def test_command_cursor_to_list_length(self):
14581458
self.assertEqual(len(await result.to_list(1)), 1)
14591459

14601460
@async_client_context.require_failCommand_blockConnection
1461-
@flaky # PYTHON-3522
1461+
@flaky(reason="PYTHON-3522")
14621462
async def test_command_cursor_to_list_csot_applied(self):
14631463
client = await self.async_single_client(timeoutMS=500, w=1)
14641464
coll = client.pymongo.test

test/asynchronous/test_encryption.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3262,7 +3262,7 @@ async def test_kms_retry(self):
32623262
class TestAutomaticDecryptionKeys(AsyncEncryptionIntegrationTest):
32633263
@async_client_context.require_no_standalone
32643264
@async_client_context.require_version_min(7, 0, -1)
3265-
@flaky # PYTHON-4982
3265+
@flaky(reason="PYTHON-4982")
32663266
async def asyncSetUp(self):
32673267
await super().asyncSetUp()
32683268
self.key1_document = json_data("etc", "data", "keys", "key1-document.json")

test/asynchronous/test_retryable_writes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ class TestPoolPausedError(AsyncIntegrationTest):
497497
@async_client_context.require_failCommand_blockConnection
498498
@async_client_context.require_retryable_writes
499499
@client_knobs(heartbeat_frequency=0.05, min_heartbeat_interval=0.05)
500-
@flaky # PYTHON-5291
500+
@flaky(reason="PYTHON-5291")
501501
async def test_pool_paused_error_is_retryable(self):
502502
cmap_listener = CMAPListener()
503503
cmd_listener = OvertCommandListener()

test/asynchronous/test_server_selection_in_window.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ async def frequencies(self, client, listener, n_finds=10):
138138

139139
@async_client_context.require_failCommand_appName
140140
@async_client_context.require_multiple_mongoses
141-
@flaky # PYTHON-3689
141+
@flaky(reason="PYTHON-3689")
142142
async def test_load_balancing(self):
143143
listener = OvertCommandListener()
144144
cmap_listener = CMAPListener()

test/asynchronous/test_srv_polling.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ def final_callback():
255255
# Nodelist should reflect new valid DNS resolver response.
256256
await self.assert_nodelist_change(response_final, client)
257257

258-
@flaky # PYTHON-5315
258+
@flaky(reason="PYTHON-5315")
259259
async def test_recover_from_initially_empty_seedlist(self):
260260
def empty_seedlist():
261261
return []

test/asynchronous/unified_format.py

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1390,23 +1390,17 @@ async def run_scenario(self, spec, uri=None):
13901390

13911391
# Handle flaky tests.
13921392
flaky_tests = [
1393-
# PYTHON-5170
1394-
".*test_discovery_and_monitoring.*",
1395-
# PYTHON-5174
1396-
".*Driver_extends_timeout_while_streaming",
1397-
# PYTHON-5315
1398-
".*TestSrvPolling.test_recover_from_initially_.*",
1399-
# PYTHON-4987
1400-
".*UnknownTransactionCommitResult_labels_to_connection_errors",
1401-
# PYTHON-3689
1402-
".*TestProse.test_load_balancing",
1403-
# PYTHON-3522
1404-
".*csot.*",
1393+
("PYTHON-5170", ".*test_discovery_and_monitoring.*"),
1394+
("PYTHON-5174", ".*Driver_extends_timeout_while_streaming"),
1395+
("PYTHON-5315", ".*TestSrvPolling.test_recover_from_initially_.*"),
1396+
("PYTHON-4987", ".*UnknownTransactionCommitResult_labels_to_connection_errors"),
1397+
("PYTHON-3689", ".*TestProse.test_load_balancing"),
1398+
("PYTHON-3522", ".*csot.*"),
14051399
]
1406-
for flaky_test in flaky_tests:
1400+
for reason, flaky_test in flaky_tests:
14071401
if re.match(flaky_test, self.id()) is not None:
14081402
func_name = self.id()
1409-
options = dict(reset_func=self.asyncSetUp, func_name=func_name)
1403+
options = dict(reason=reason, reset_func=self.asyncSetUp, func_name=func_name)
14101404
if "csot" in func_name.lower():
14111405
options["max_runs"] = 3
14121406
options["affects_cpython_linux"] = True

test/asynchronous/utils.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,8 @@ async def async_joinall(tasks):
159159

160160

161161
def flaky(
162-
func=None,
163162
*,
163+
reason=None,
164164
max_runs=2,
165165
min_passes=1,
166166
delay=1,
@@ -170,6 +170,7 @@ def flaky(
170170
):
171171
"""Decorate a test as flaky.
172172
173+
:param reason: the reason why the test is flaky
173174
:param max_runs: the maximum number of runs before raising an error
174175
:param min_passes: the minimum number of passing runs
175176
:param delay: the delay in seconds between retries
@@ -178,6 +179,8 @@ def flaky(
178179
:param reset_func: a function to call before retrying
179180
180181
"""
182+
if reason is None:
183+
raise ValueError("flaky requires a reason input")
181184
is_cpython_linux = sys.platform == "linux" and sys.implementation.name == "cpython"
182185
disable_flaky = "DISABLE_FLAKY" in os.environ
183186
if disable_flaky or (is_cpython_linux and not affects_cpython_linux):
@@ -198,7 +201,7 @@ async def wrapper(*args, **kwargs):
198201
if i == max_runs - 1:
199202
raise e
200203
print(
201-
f"Retrying after attempt {i+1} of {func_name or target_func.__name__} failed with:\n"
204+
f"Retrying after attempt {i+1} of {func_name or target_func.__name__} failed with ({reason})):\n"
202205
f"{traceback.format_exc()}",
203206
file=sys.stderr,
204207
)
@@ -208,11 +211,6 @@ async def wrapper(*args, **kwargs):
208211

209212
return wrapper
210213

211-
# If `func` is callable, the decorator was used without arguments (`@flaky`).
212-
if callable(func):
213-
return decorator(func)
214-
215-
# Otherwise, return the decorator function, allowing arguments (`@flaky(max_runs=...)`).
216214
return decorator
217215

218216

0 commit comments

Comments
 (0)