08ea5fbe98
添加用户管理视图、API和状态管理文件
332 lines
14 KiB
Python
332 lines
14 KiB
Python
"""
|
|
Caffeine缓存管理模块测试 - TDD Red阶段
|
|
|
|
测试基于Caffeine的本地缓存管理功能。
|
|
"""
|
|
|
|
import pytest
|
|
import allure
|
|
import time
|
|
from typing import Any, Optional
|
|
|
|
|
|
@allure.epic("核心框架")
|
|
@allure.feature("Caffeine缓存管理 - TDD Red阶段")
|
|
class TestCaffeineCache:
|
|
"""Caffeine缓存管理测试类 - TDD Red阶段(期望失败)"""
|
|
|
|
@allure.title("测试缓存基本操作 - TDD Red阶段")
|
|
@allure.description("验证缓存的基本CRUD操作 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.CRITICAL)
|
|
@pytest.mark.smoke
|
|
def test_cache_basic_operations(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试缓存基本操作
|
|
|
|
预期结果:
|
|
- 可以put数据到缓存
|
|
- 可以从缓存get数据
|
|
- 可以delete缓存数据
|
|
- 可以检查key是否存在
|
|
"""
|
|
from core.caffeine_cache import CaffeineCache
|
|
|
|
with allure.step("Step 1: 创建缓存实例"):
|
|
cache = CaffeineCache()
|
|
allure.attach("✅ 缓存实例创建成功", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 测试put操作"):
|
|
cache.put("key1", "value1")
|
|
allure.attach("✅ put操作成功", "步骤2", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 3: 测试get操作"):
|
|
value = cache.get("key1")
|
|
allure.attach(f"获取值: {value}", "步骤3", allure.attachment_type.TEXT)
|
|
assert value == "value1", f"缓存值不匹配,期望: value1, 实际: {value}"
|
|
|
|
with allure.step("Step 4: 测试exists操作"):
|
|
exists = cache.exists("key1")
|
|
allure.attach(f"key1存在: {exists}", "步骤4", allure.attachment_type.TEXT)
|
|
assert exists is True, "key1应该存在"
|
|
|
|
with allure.step("Step 5: 测试delete操作"):
|
|
cache.delete("key1")
|
|
value = cache.get("key1")
|
|
allure.attach(f"删除后获取值: {value}", "步骤5", allure.attachment_type.TEXT)
|
|
assert value is None, "删除后应该返回None"
|
|
|
|
@allure.title("测试缓存过期时间 - TDD Red阶段")
|
|
@allure.description("验证缓存数据在指定时间后过期 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.CRITICAL)
|
|
@pytest.mark.smoke
|
|
def test_cache_expiration(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试缓存过期时间
|
|
|
|
预期结果:
|
|
- 设置过期时间的缓存数据在过期后自动失效
|
|
- 未过期的数据仍然有效
|
|
"""
|
|
from core.caffeine_cache import CaffeineCache
|
|
|
|
with allure.step("Step 1: 创建缓存实例"):
|
|
cache = CaffeineCache()
|
|
allure.attach("✅ 缓存实例创建成功", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 设置带过期时间的缓存"):
|
|
cache.put("temp_key", "temp_value", expire_seconds=1)
|
|
allure.attach("✅ 设置1秒过期时间的缓存", "步骤2", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 3: 验证缓存立即生效"):
|
|
value = cache.get("temp_key")
|
|
assert value == "temp_value", f"缓存值不匹配,期望: temp_value, 实际: {value}"
|
|
allure.attach("✅ 缓存立即生效", "步骤3", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 4: 等待缓存过期"):
|
|
time.sleep(1.5) # 等待1.5秒,确保过期
|
|
allure.attach("⏱️ 等待1.5秒", "步骤4", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 5: 验证缓存已过期"):
|
|
value = cache.get("temp_key")
|
|
allure.attach(f"过期后获取值: {value}", "步骤5", allure.attachment_type.TEXT)
|
|
assert value is None, "过期后应该返回None"
|
|
|
|
@allure.title("测试缓存容量限制 - TDD Red阶段")
|
|
@allure.description("验证缓存在达到容量限制时的行为 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.CRITICAL)
|
|
@pytest.mark.smoke
|
|
def test_cache_capacity_limit(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试缓存容量限制
|
|
|
|
预期结果:
|
|
- 当缓存达到容量限制时,最久未使用的数据被移除
|
|
- 最近使用的数据仍然保留
|
|
"""
|
|
from core.caffeine_cache import CaffeineCache
|
|
|
|
with allure.step("Step 1: 创建容量为3的缓存"):
|
|
cache = CaffeineCache(max_size=3)
|
|
allure.attach("✅ 创建容量为3的缓存", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 添加3个缓存项"):
|
|
cache.put("key1", "value1")
|
|
cache.put("key2", "value2")
|
|
cache.put("key3", "value3")
|
|
allure.attach("✅ 添加3个缓存项", "步骤2", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 3: 访问key1使其最近使用"):
|
|
value = cache.get("key1")
|
|
assert value == "value1"
|
|
allure.attach("✅ 访问key1", "步骤3", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 4: 添加第4个缓存项"):
|
|
cache.put("key4", "value4")
|
|
allure.attach("✅ 添加第4个缓存项key4", "步骤4", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 5: 验证key2被移除(最久未使用)"):
|
|
value2 = cache.get("key2")
|
|
value1 = cache.get("key1")
|
|
allure.attach(f"key2值: {value2}", "步骤5", allure.attachment_type.TEXT)
|
|
allure.attach(f"key1值: {value1}", "步骤5", allure.attachment_type.TEXT)
|
|
assert value2 is None, "key2应该被移除"
|
|
assert value1 == "value1", "key1应该仍然存在"
|
|
|
|
@allure.title("测试缓存统计信息 - TDD Red阶段")
|
|
@allure.description("验证缓存统计信息正确收集 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.NORMAL)
|
|
@pytest.mark.regression
|
|
def test_cache_statistics(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试缓存统计信息
|
|
|
|
预期结果:
|
|
- 缓存命中率统计正确
|
|
- 缓存大小统计正确
|
|
- 加载次数统计正确
|
|
"""
|
|
from core.caffeine_cache import CaffeineCache
|
|
|
|
with allure.step("Step 1: 创建启用统计的缓存"):
|
|
cache = CaffeineCache(record_stats=True)
|
|
allure.attach("✅ 创建启用统计的缓存", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 执行缓存操作"):
|
|
cache.put("key1", "value1")
|
|
cache.get("key1") # 命中
|
|
cache.get("key1") # 命中
|
|
cache.get("key2") # 未命中
|
|
allure.attach("✅ 执行缓存操作", "步骤2", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 3: 获取统计信息"):
|
|
stats = cache.get_stats()
|
|
allure.attach(f"统计信息: {stats}", "步骤3", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 4: 验证统计信息"):
|
|
assert "hit_count" in stats, "统计信息应包含hit_count"
|
|
assert "miss_count" in stats, "统计信息应包含miss_count"
|
|
assert "hit_rate" in stats, "统计信息应包含hit_rate"
|
|
assert stats["hit_count"] == 2, "命中次数应为2"
|
|
assert stats["miss_count"] == 1, "未命中次数应为1"
|
|
|
|
@allure.title("测试缓存刷新机制 - TDD Red阶段")
|
|
@allure.description("验证缓存自动刷新机制 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.NORMAL)
|
|
@pytest.mark.regression
|
|
def test_cache_refresh(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试缓存刷新机制
|
|
|
|
预期结果:
|
|
- 缓存支持手动刷新
|
|
- 刷新后数据更新
|
|
"""
|
|
from core.caffeine_cache import CaffeineCache
|
|
|
|
with allure.step("Step 1: 创建缓存实例"):
|
|
cache = CaffeineCache()
|
|
allure.attach("✅ 缓存实例创建成功", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 添加初始数据"):
|
|
cache.put("refresh_key", "initial_value")
|
|
allure.attach("✅ 添加初始数据", "步骤2", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 3: 更新数据"):
|
|
cache.put("refresh_key", "updated_value")
|
|
allure.attach("✅ 更新数据", "步骤3", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 4: 验证数据已更新"):
|
|
value = cache.get("refresh_key")
|
|
allure.attach(f"更新后的值: {value}", "步骤4", allure.attachment_type.TEXT)
|
|
assert value == "updated_value", f"缓存值未更新,期望: updated_value, 实际: {value}"
|
|
|
|
@allure.title("测试缓存批量操作 - TDD Red阶段")
|
|
@allure.description("验证缓存批量操作功能 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.NORMAL)
|
|
@pytest.mark.regression
|
|
def test_cache_batch_operations(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试缓存批量操作
|
|
|
|
预期结果:
|
|
- 支持批量put
|
|
- 支持批量get
|
|
- 支持批量delete
|
|
"""
|
|
from core.caffeine_cache import CaffeineCache
|
|
|
|
with allure.step("Step 1: 创建缓存实例"):
|
|
cache = CaffeineCache()
|
|
allure.attach("✅ 缓存实例创建成功", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 批量添加数据"):
|
|
data = {
|
|
"batch_key1": "batch_value1",
|
|
"batch_key2": "batch_value2",
|
|
"batch_key3": "batch_value3",
|
|
}
|
|
cache.put_all(data)
|
|
allure.attach(f"批量添加: {data}", "步骤2", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 3: 批量获取数据"):
|
|
keys = ["batch_key1", "batch_key2", "batch_key3"]
|
|
values = cache.get_all(keys)
|
|
allure.attach(f"批量获取: {values}", "步骤3", allure.attachment_type.TEXT)
|
|
assert len(values) == 3, f"批量获取结果数量错误,期望: 3, 实际: {len(values)}"
|
|
|
|
with allure.step("Step 4: 批量删除数据"):
|
|
cache.delete_all(keys)
|
|
allure.attach("✅ 批量删除完成", "步骤4", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 5: 验证数据已删除"):
|
|
values = cache.get_all(keys)
|
|
allure.attach(f"删除后批量获取: {values}", "步骤5", allure.attachment_type.TEXT)
|
|
assert all(v is None for v in values.values()), "所有值应该为None"
|
|
|
|
@allure.title("测试缓存清空 - TDD Red阶段")
|
|
@allure.description("验证缓存清空功能 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.NORMAL)
|
|
@pytest.mark.regression
|
|
def test_cache_clear(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试缓存清空
|
|
|
|
预期结果:
|
|
- 清空后所有数据被移除
|
|
- 缓存大小归零
|
|
"""
|
|
from core.caffeine_cache import CaffeineCache
|
|
|
|
with allure.step("Step 1: 创建缓存实例并添加数据"):
|
|
cache = CaffeineCache()
|
|
cache.put("key1", "value1")
|
|
cache.put("key2", "value2")
|
|
cache.put("key3", "value3")
|
|
allure.attach("✅ 添加3个缓存项", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 清空缓存"):
|
|
cache.clear()
|
|
allure.attach("✅ 缓存已清空", "步骤2", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 3: 验证缓存为空"):
|
|
value1 = cache.get("key1")
|
|
value2 = cache.get("key2")
|
|
value3 = cache.get("key3")
|
|
allure.attach(f"key1: {value1}, key2: {value2}, key3: {value3}", "步骤3", allure.attachment_type.TEXT)
|
|
assert value1 is None, "key1应该为None"
|
|
assert value2 is None, "key2应该为None"
|
|
assert value3 is None, "key3应该为None"
|
|
|
|
@allure.title("测试缓存线程安全 - TDD Red阶段")
|
|
@allure.description("验证缓存在多线程环境下的安全性 - 期望失败(Red)")
|
|
@allure.severity(allure.severity_level.CRITICAL)
|
|
@pytest.mark.smoke
|
|
def test_cache_thread_safety(self) -> None:
|
|
"""
|
|
TDD Red阶段: 测试缓存线程安全
|
|
|
|
预期结果:
|
|
- 多线程并发操作不会导致数据不一致
|
|
- 不会出现竞态条件
|
|
"""
|
|
from core.caffeine_cache import CaffeineCache
|
|
import threading
|
|
|
|
with allure.step("Step 1: 创建缓存实例"):
|
|
cache = CaffeineCache()
|
|
allure.attach("✅ 缓存实例创建成功", "步骤1", allure.attachment_type.TEXT)
|
|
|
|
with allure.step("Step 2: 多线程并发写入"):
|
|
errors = []
|
|
|
|
def write_data(thread_id: int):
|
|
try:
|
|
for i in range(10):
|
|
cache.put(f"thread_{thread_id}_key_{i}", f"value_{i}")
|
|
except Exception as e:
|
|
errors.append(str(e))
|
|
|
|
threads = []
|
|
for i in range(5):
|
|
t = threading.Thread(target=write_data, args=(i,))
|
|
threads.append(t)
|
|
t.start()
|
|
|
|
for t in threads:
|
|
t.join()
|
|
|
|
allure.attach(f"线程数: 5, 每线程写入: 10条", "步骤2", allure.attachment_type.TEXT)
|
|
assert len(errors) == 0, f"并发写入出现错误: {errors}"
|
|
|
|
with allure.step("Step 3: 验证数据完整性"):
|
|
total_keys = 5 * 10 # 5个线程,每线程10条
|
|
count = 0
|
|
for thread_id in range(5):
|
|
for i in range(10):
|
|
value = cache.get(f"thread_{thread_id}_key_{i}")
|
|
if value is not None:
|
|
count += 1
|
|
|
|
allure.attach(f"成功写入: {count}/{total_keys} 条", "步骤3", allure.attachment_type.TEXT)
|
|
assert count == total_keys, f"数据不完整,期望: {total_keys}, 实际: {count}"
|