功能实现: - 全选功能:跨分组保持选中状态,使用全局 Set 存储 - 验证码提取:支持 Graph API → IMAP 回退策略 - 自动轮询:新邮件通知、红点提示、连续错误自动停止 BUG 修复 (BUG-001 ~ BUG-008): - Toast 通知位置移至右下角 - 切换分组时保持全选状态 - 添加批量删除邮箱功能 - 验证码提取支持 IMAP 回退 - 修复轮询开关类型不一致 (boolean vs string) - 完善轮询通知内容与红点位置 - 轮询次数校验改为 0-100 (0 表示持续) - 复制按钮添加加载状态与反馈 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
285 lines
9.0 KiB
Python
285 lines
9.0 KiB
Python
"""
|
||
性能测试用例
|
||
|
||
测试批量操作与自动化增强功能的性能指标,包括:
|
||
- 全选性能测试(1000 个邮箱 < 100ms)
|
||
- 验证码提取 API 性能测试(< 2 秒)
|
||
- 轮询性能测试(不影响页面交互)
|
||
"""
|
||
|
||
import unittest
|
||
import sys
|
||
import os
|
||
import time
|
||
|
||
# 添加项目根目录到 Python 路径
|
||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
||
|
||
|
||
class TestPerformance(unittest.TestCase):
|
||
"""性能测试类"""
|
||
|
||
def setUp(self):
|
||
"""测试前置准备"""
|
||
pass
|
||
|
||
# ==================== 全选性能测试 ====================
|
||
|
||
def test_pt_001_select_all_1000_accounts_performance(self):
|
||
"""
|
||
测试用例 PT-001:全选 1000 个邮箱性能
|
||
|
||
测试目的:验证全选 1000 个邮箱的性能 < 100ms
|
||
|
||
测试方法:
|
||
1. 准备 1000 个测试邮箱数据
|
||
2. 渲染到页面
|
||
3. 执行全选操作
|
||
4. 测量耗时
|
||
|
||
预期结果:耗时 < 100ms
|
||
|
||
注意:此测试需要在浏览器环境中执行
|
||
"""
|
||
# 这是一个前端性能测试,需要在浏览器中执行
|
||
# 测试代码示例(在浏览器控制台执行):
|
||
"""
|
||
// 准备 1000 个测试邮箱
|
||
const testAccounts = Array.from({length: 1000}, (_, i) => ({
|
||
id: i + 1,
|
||
email: `test${i + 1}@example.com`,
|
||
group_id: 1
|
||
}));
|
||
|
||
// 渲染到页面
|
||
renderAccountList(testAccounts);
|
||
|
||
// 测试全选性能
|
||
console.time('全选性能');
|
||
selectAllAccounts();
|
||
console.timeEnd('全选性能');
|
||
|
||
// 预期输出:全选性能: XX.XXms (应该 < 100ms)
|
||
"""
|
||
|
||
self.assertTrue(True, "前端性能测试,需要在浏览器中执行")
|
||
|
||
# ==================== API 性能测试 ====================
|
||
|
||
def test_pt_002_extract_verification_api_performance(self):
|
||
"""
|
||
测试用例 PT-002:验证码提取 API 性能
|
||
|
||
测试目的:验证验证码提取 API 响应时间 < 2 秒
|
||
|
||
测试方法:
|
||
1. 准备测试邮箱和邮件数据
|
||
2. 多次调用 API(至少 10 次)
|
||
3. 计算平均响应时间
|
||
|
||
预期结果:平均响应时间 < 2000ms
|
||
"""
|
||
# TODO: 实现后取消注释
|
||
# from outlook_web.app import create_app
|
||
#
|
||
# app = create_app()
|
||
# client = app.test_client()
|
||
#
|
||
# # 登录
|
||
# client.post('/login', data={'password': 'admin123'})
|
||
#
|
||
# # 多次测试取平均值
|
||
# times = []
|
||
# for i in range(10):
|
||
# start_time = time.time()
|
||
#
|
||
# response = client.get('/api/emails/test@example.com/extract-verification')
|
||
#
|
||
# end_time = time.time()
|
||
# elapsed_time = (end_time - start_time) * 1000 # 转换为毫秒
|
||
# times.append(elapsed_time)
|
||
#
|
||
# self.assertEqual(response.status_code, 200)
|
||
#
|
||
# # 计算平均时间
|
||
# avg_time = sum(times) / len(times)
|
||
# max_time = max(times)
|
||
# min_time = min(times)
|
||
#
|
||
# print(f"\n性能测试结果:")
|
||
# print(f" 平均响应时间: {avg_time:.2f}ms")
|
||
# print(f" 最大响应时间: {max_time:.2f}ms")
|
||
# print(f" 最小响应时间: {min_time:.2f}ms")
|
||
#
|
||
# # 断言平均时间 < 2000ms
|
||
# self.assertLess(avg_time, 2000, f"API 平均响应时间过长: {avg_time:.2f}ms")
|
||
|
||
self.assertTrue(True, "待实现:API 性能测试")
|
||
|
||
# ==================== 轮询性能测试 ====================
|
||
|
||
def test_pt_003_polling_not_block_ui(self):
|
||
"""
|
||
测试用例 PT-003:轮询不影响页面交互
|
||
|
||
测试目的:验证轮询过程中页面交互流畅
|
||
|
||
测试方法:
|
||
1. 启动轮询
|
||
2. 在轮询过程中执行各种操作
|
||
3. 测量操作响应时间
|
||
|
||
预期结果:
|
||
- 页面交互流畅,无卡顿
|
||
- 操作响应及时
|
||
|
||
注意:此测试需要在浏览器环境中执行
|
||
"""
|
||
# 这是一个前端性能测试,需要在浏览器中执行
|
||
# 测试代码示例(在浏览器控制台执行):
|
||
"""
|
||
// 启动轮询
|
||
startPolling('test@example.com');
|
||
|
||
// 测试各种操作的响应时间
|
||
async function testUIResponsiveness() {
|
||
const operations = [
|
||
{
|
||
name: '切换分组',
|
||
action: () => loadAccountsByGroup(2)
|
||
},
|
||
{
|
||
name: '搜索邮箱',
|
||
action: () => {
|
||
const searchInput = document.getElementById('accountSearch');
|
||
searchInput.value = 'test';
|
||
searchInput.dispatchEvent(new Event('input'));
|
||
}
|
||
},
|
||
{
|
||
name: '点击按钮',
|
||
tion: () => {
|
||
const btn = document.querySelector('.refresh-btn');
|
||
btn.click();
|
||
}
|
||
}
|
||
];
|
||
|
||
for (const op of operations) {
|
||
console.time(op.name);
|
||
await op.action();
|
||
console.timeEnd(op.name);
|
||
await new Promise(resolve => setTimeout(resolve, 100));
|
||
}
|
||
}
|
||
|
||
testUIResponsiveness();
|
||
|
||
// 预期:所有操作响应时间都应该 < 100ms
|
||
"""
|
||
|
||
self.assertTrue(True, "前端性能测试,需要在浏览器中执行")
|
||
|
||
# ==================== 压力测试(可选)====================
|
||
|
||
def test_pt_004_concurrent_api_requests(self):
|
||
"""
|
||
测试用例 PT-004:并发 API 请求测试(可选)
|
||
|
||
测试目的:验证 API 能处理并发请求
|
||
|
||
测试方法:
|
||
1. 同时发送多个 API 请求
|
||
2. 测量响应时间
|
||
3. 验证所有请求都成功
|
||
|
||
预期结果:
|
||
- 所有请求都成功返回
|
||
- 平均响应时间仍然 < 2 秒
|
||
"""
|
||
# TODO: 实现后取消注释
|
||
# import concurrent.futures
|
||
# from outlook_web.app import create_app
|
||
#
|
||
# app = create_app()
|
||
# client = app.test_client()
|
||
#
|
||
# # 登录
|
||
# client.post('/login', data={'password': 'admin123'})
|
||
#
|
||
# def make_request():
|
||
# start_time = time.time()
|
||
# response = client.get('/api/emails/test@example.com/extract-verification')
|
||
# end_time = time.time()
|
||
# return {
|
||
# 'status_code': response.status_code,
|
||
# 'elapsed_time': (end_time - start_time) * 1000
|
||
# }
|
||
#
|
||
# # 并发 10 个请求
|
||
# with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
|
||
# futures = [executor.submit(make_request) for _ in range(10)]
|
||
# results = [f.result() for f in concurrent.futures.as_completed(futures)]
|
||
#
|
||
# # 验证结果
|
||
# success_count = sum(1 for r in results if r['status_code'] == 200)
|
||
# avg_time = sum(r['elapsed_time'] for r in results) / len(results)
|
||
#
|
||
# print(f"\n并发测试结果:")
|
||
# print(f" 成功请求数: {success_count}/10")
|
||
# print(f" 平均响应时间: {avg_time:.2f}ms")
|
||
#
|
||
# self.assertEqual(success_count, 10, "部分请求失败")
|
||
# self.assertLess(avg_time, 2000, f"并发情况下响应时间过长: {avg_time:.2f}ms")
|
||
|
||
self.assertTrue(True, "待实现:并发 API 请求测试")
|
||
|
||
|
||
class TestMemoryUsage(unittest.TestCase):
|
||
"""内存使用测试类(可选)"""
|
||
|
||
def test_memory_leak_detection(self):
|
||
"""
|
||
测试用例:内存泄漏检测
|
||
|
||
测试目的:验证轮询功能不会导致内存泄漏
|
||
|
||
测试方法:
|
||
1. 记录初始内存使用
|
||
2. 执行多次轮询操作
|
||
3. 记录最终内存使用
|
||
4. 对比内存增长
|
||
|
||
预期结果:内存增长在合理范围内
|
||
|
||
注意:此测试需要在浏览器环境中执行
|
||
"""
|
||
# 这是一个前端内存测试,需要在浏览器中执行
|
||
# 测试代码示例(在浏览器控制台执行):
|
||
"""
|
||
// 使用 Chrome DevTools Memory Profiler
|
||
|
||
// 1. 打开 Chrome DevTools -> Memory
|
||
// 2. 记录初始堆快照
|
||
// 3. 执行以下代码
|
||
async function testMemoryLeak() {
|
||
for (let i = 0; i < 100; i++) {
|
||
startPolling('test@example.com');
|
||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||
stopPolling();
|
||
}
|
||
}
|
||
|
||
testMemoryLeak();
|
||
|
||
// 4. 记录最终堆快照
|
||
// 5. 对比两个快照,检查是否有内存泄漏
|
||
"""
|
||
|
||
self.assertTrue(True, "前端内存测试,需要在浏览器中执行")
|
||
|
||
|
||
if __name__ == '__main__':
|
||
# 运行性能测试
|
||
unittest.main(verbosity=2)
|