返回 douyin-downloader
test_retry_handler.py
根目录 / tests / test_retry_handler.py
1 import time
2
3 import pytest
4
5 from control.retry_handler import RetryHandler
6
7
8 @pytest.mark.asyncio
9 async def test_retry_handler_succeeds_on_first_try():
10 handler = RetryHandler(max_retries=3)
11 call_count = 0
12
13 async def task():
14 nonlocal call_count
15 call_count += 1
16 return "ok"
17
18 result = await handler.execute_with_retry(task)
19 assert result == "ok"
20 assert call_count == 1
21
22
23 @pytest.mark.asyncio
24 async def test_retry_handler_retries_then_succeeds():
25 handler = RetryHandler(max_retries=3)
26 handler.retry_delays = [0, 0, 0]
27 call_count = 0
28
29 async def task():
30 nonlocal call_count
31 call_count += 1
32 if call_count < 3:
33 raise RuntimeError("transient error")
34 return "recovered"
35
36 result = await handler.execute_with_retry(task)
37 assert result == "recovered"
38 assert call_count == 3
39
40
41 @pytest.mark.asyncio
42 async def test_retry_handler_raises_after_exhaustion():
43 handler = RetryHandler(max_retries=2)
44 handler.retry_delays = [0, 0]
45
46 async def task():
47 raise ValueError("permanent")
48
49 with pytest.raises(ValueError, match="permanent"):
50 await handler.execute_with_retry(task)
51
52
53 @pytest.mark.asyncio
54 async def test_retry_handler_makes_max_retries_plus_one_attempts():
55 # max_retries=N means N retries after the initial attempt → N+1 total
56 # attempts. The previous implementation looped only N times, so the third
57 # configured delay was unreachable.
58 handler = RetryHandler(max_retries=3)
59 handler.retry_delays = [0, 0, 0]
60 call_count = 0
61
62 async def task():
63 nonlocal call_count
64 call_count += 1
65 if call_count < 4:
66 raise RuntimeError("transient")
67 return "ok"
68
69 result = await handler.execute_with_retry(task)
70 assert result == "ok"
71 assert call_count == 4
72
73
74 @pytest.mark.asyncio
75 async def test_retry_handler_applies_all_configured_delays():
76 # All three delays in retry_delays must be applied between failed attempts.
77 handler = RetryHandler(max_retries=3)
78 handler.retry_delays = [0.05, 0.1, 0.2]
79 call_count = 0
80
81 async def always_fail():
82 nonlocal call_count
83 call_count += 1
84 raise RuntimeError("always")
85
86 start = time.time()
87 with pytest.raises(RuntimeError):
88 await handler.execute_with_retry(always_fail)
89 elapsed = time.time() - start
90
91 assert call_count == 4
92 assert elapsed >= 0.3, f"expected >= 0.3s of delay (sum of retry_delays), got {elapsed:.3f}s"
93
93 lines PYTHON