Bloom_Ware / tests /test_retry.py
LawrenceBai's picture
Latest
26b9faa
Raw
History Blame Contribute Delete
3.59 kB
"""
測試 core/retry.py 重試機制
"""
import pytest
import asyncio
from core.retry import (
RetryConfig,
retry_async,
with_retry,
default_retry_config,
api_retry_config,
)
class TestRetryConfig:
"""測試重試配置"""
def test_default_config(self):
"""測試預設配置"""
config = RetryConfig()
assert config.max_retries == 3
assert config.base_delay == 1.0
assert config.max_delay == 30.0
def test_custom_config(self):
"""測試自訂配置"""
config = RetryConfig(max_retries=5, base_delay=0.5)
assert config.max_retries == 5
assert config.base_delay == 0.5
def test_calculate_delay(self):
"""測試延遲計算"""
config = RetryConfig(base_delay=1.0, jitter=False)
# 第一次重試
delay0 = config.calculate_delay(0)
assert delay0 == 1.0
# 第二次重試(指數退避)
delay1 = config.calculate_delay(1)
assert delay1 == 2.0
def test_max_delay_cap(self):
"""測試最大延遲上限"""
config = RetryConfig(base_delay=10.0, max_delay=15.0, jitter=False)
delay = config.calculate_delay(5) # 10 * 2^5 = 320,應被限制
assert delay == 15.0
class TestRetryAsync:
"""測試異步重試"""
@pytest.mark.asyncio
async def test_success_no_retry(self):
"""測試成功時不重試"""
call_count = 0
async def success_func():
nonlocal call_count
call_count += 1
return "success"
result = await retry_async(success_func)
assert result == "success"
assert call_count == 1
@pytest.mark.asyncio
async def test_retry_then_success(self):
"""測試重試後成功"""
call_count = 0
async def fail_then_success():
nonlocal call_count
call_count += 1
if call_count < 3:
raise ValueError("temporary error")
return "success"
config = RetryConfig(max_retries=3, base_delay=0.01)
result = await retry_async(fail_then_success, config=config)
assert result == "success"
assert call_count == 3
@pytest.mark.asyncio
async def test_all_retries_fail(self):
"""測試所有重試都失敗"""
call_count = 0
async def always_fail():
nonlocal call_count
call_count += 1
raise ValueError("always fails")
config = RetryConfig(max_retries=2, base_delay=0.01)
with pytest.raises(ValueError):
await retry_async(always_fail, config=config)
assert call_count == 3 # 初始 + 2 次重試
class TestWithRetryDecorator:
"""測試重試裝飾器"""
@pytest.mark.asyncio
async def test_decorator_success(self):
"""測試裝飾器成功"""
@with_retry(max_retries=2, base_delay=0.01)
async def decorated_func():
return "decorated"
result = await decorated_func()
assert result == "decorated"
class TestPredefinedConfigs:
"""測試預定義配置"""
def test_default_config_exists(self):
"""測試預設配置存在"""
assert default_retry_config is not None
assert default_retry_config.max_retries == 3
def test_api_config_exists(self):
"""測試 API 配置存在"""
assert api_retry_config is not None
assert api_retry_config.max_retries == 2
assert api_retry_config.base_delay == 0.5