Skip to content

Commit 317f670

Browse files
committed
feat: add waiting helpers
1 parent 3744b62 commit 317f670

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

sipgate_e2e_test_utils/waiting.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import asyncio
2+
from datetime import timedelta
3+
from typing import Callable, Any
4+
5+
6+
async def wait_for_condition(
7+
condition: Callable[[], bool], attempts: int = 5, interval: timedelta = timedelta(milliseconds=100)) -> None:
8+
if attempts < 1:
9+
raise ValueError('needs at least one attempt')
10+
11+
if interval < timedelta(milliseconds=0):
12+
raise ValueError('interval cannot be negative')
13+
14+
attempt = 1
15+
while condition() is False:
16+
attempt += 1
17+
18+
if attempt > attempts:
19+
raise TimeoutError('timed out waiting for condition')
20+
21+
await asyncio.sleep(interval.total_seconds())
22+
23+
24+
async def wait_for_assertions(
25+
asserter: Callable[[], Any], attempts: int = 5, interval: timedelta = timedelta(milliseconds=100)) -> None:
26+
if attempts < 1:
27+
raise ValueError('needs at least one attempt')
28+
29+
if interval < timedelta(milliseconds=0):
30+
raise ValueError('interval cannot be negative')
31+
32+
attempt = 1
33+
while True:
34+
try:
35+
asserter()
36+
except AssertionError as e:
37+
attempt += 1
38+
39+
if attempt > attempts:
40+
raise e
41+
42+
await asyncio.sleep(interval.total_seconds())
43+
else:
44+
return

tests/test_waiting.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import unittest
2+
3+
from sipgate_e2e_test_utils.waiting import wait_for_condition, wait_for_assertions
4+
5+
6+
class WaitingTest(unittest.IsolatedAsyncioTestCase):
7+
async def test_completes_when_condition_is_met(self) -> None:
8+
await wait_for_condition(lambda: True)
9+
10+
async def test_throws_after_num_attempts_when_condition_is_not_met(self) -> None:
11+
attempts_done = 0
12+
13+
def waiter() -> bool:
14+
nonlocal attempts_done
15+
attempts_done += 1
16+
return False
17+
18+
with self.assertRaises(TimeoutError):
19+
await wait_for_condition(waiter, attempts=3)
20+
21+
self.assertEqual(3, attempts_done)
22+
23+
async def test_completes_when_assertion_succeeds(self) -> None:
24+
await wait_for_assertions(lambda: self.assertEqual(1, 1))
25+
26+
async def test_throws_after_num_attempts_when_assertion_fails(self) -> None:
27+
attempts_done = 0
28+
29+
def asserter() -> None:
30+
nonlocal attempts_done
31+
attempts_done += 1
32+
33+
self.assertEqual(1, 2)
34+
35+
with self.assertRaises(AssertionError):
36+
await wait_for_assertions(asserter, attempts=3)
37+
38+
self.assertEqual(3, attempts_done)

0 commit comments

Comments
 (0)