Files
novalon-manage-system/novalon-manage-web/e2e/performance-benchmarks.spec.ts
T
张翔 e2ad1331cc feat: 添加测试框架和覆盖率报告功能
feat(测试): 新增Playwright和Vitest测试配置
feat(测试): 添加测试覆盖率报告生成功能
feat(测试): 实现前后端测试脚本集成

fix(测试): 修复测试密码不匹配问题
fix(测试): 修正URL等待策略
fix(测试): 调整错误消息选择器

refactor(测试): 重构测试目录结构
refactor(测试): 优化测试用例组织方式

docs: 更新测试报告文档
docs: 添加测试覆盖率报告模板

ci: 添加Docker测试环境配置
ci: 实现测试自动化脚本

chore: 更新依赖版本
chore: 添加测试相关配置文件
2026-03-25 09:03:37 +08:00

489 lines
15 KiB
TypeScript

import { test, expect } from '@playwright/test';
import { LoginPage } from './pages/LoginPage';
import { DashboardPage } from './pages/DashboardPage';
import { UserManagementPage } from './pages/UserManagementPage';
import { RoleManagementPage } from './pages/RoleManagementPage';
test.describe('性能测试基准', () => {
let loginPage: LoginPage;
let dashboardPage: DashboardPage;
let userManagementPage: UserManagementPage;
let roleManagementPage: RoleManagementPage;
test.beforeEach(async ({ page }) => {
loginPage = new LoginPage(page);
dashboardPage = new DashboardPage(page);
userManagementPage = new UserManagementPage(page);
roleManagementPage = new RoleManagementPage(page);
});
test('登录页面加载性能', async ({ page }) => {
const startTime = Date.now();
await loginPage.goto();
await page.waitForLoadState('networkidle');
const endTime = Date.now();
const loadTime = endTime - startTime;
console.log(`登录页面加载时间: ${loadTime}ms`);
expect(loadTime).toBeLessThan(3000);
});
test('登录操作性能', async ({ page }) => {
await loginPage.goto();
await page.waitForLoadState('networkidle');
const startTime = Date.now();
await loginPage.usernameInput.fill('admin');
await loginPage.passwordInput.fill('admin123');
await loginPage.loginButton.click();
await page.waitForURL(/.*dashboard/);
const endTime = Date.now();
const loginTime = endTime - startTime;
console.log(`登录操作时间: ${loginTime}ms`);
expect(loginTime).toBeLessThan(2000);
});
test('Dashboard页面加载性能', async ({ page }) => {
await loginPage.goto();
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
const startTime = Date.now();
await page.goto('/dashboard');
await page.waitForLoadState('networkidle');
const endTime = Date.now();
const loadTime = endTime - startTime;
console.log(`Dashboard页面加载时间: ${loadTime}ms`);
expect(loadTime).toBeLessThan(2000);
});
test('用户管理页面加载性能', async ({ page }) => {
await loginPage.goto();
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
const startTime = Date.now();
await dashboardPage.navigateToUserManagement();
await page.waitForLoadState('networkidle');
const endTime = Date.now();
const loadTime = endTime - startTime;
console.log(`用户管理页面加载时间: ${loadTime}ms`);
expect(loadTime).toBeLessThan(2000);
});
test('角色管理页面加载性能', async ({ page }) => {
await loginPage.goto();
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
const startTime = Date.now();
await dashboardPage.navigateToRoleManagement();
await page.waitForLoadState('networkidle');
const endTime = Date.now();
const loadTime = endTime - startTime;
console.log(`角色管理页面加载时间: ${loadTime}ms`);
expect(loadTime).toBeLessThan(2000);
});
test('用户列表加载性能', async ({ page }) => {
await loginPage.goto();
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
await dashboardPage.navigateToUserManagement();
await page.waitForLoadState('networkidle');
const startTime = Date.now();
const table = page.locator('.el-table').first();
await expect(table).toBeVisible();
const endTime = Date.now();
const loadTime = endTime - startTime;
console.log(`用户列表加载时间: ${loadTime}ms`);
expect(loadTime).toBeLessThan(1500);
});
test('角色列表加载性能', async ({ page }) => {
await loginPage.goto();
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
await dashboardPage.navigateToRoleManagement();
await page.waitForLoadState('networkidle');
const startTime = Date.now();
const table = page.locator('.el-table').first();
await expect(table).toBeVisible();
const endTime = Date.now();
const loadTime = endTime - startTime;
console.log(`角色列表加载时间: ${loadTime}ms`);
expect(loadTime).toBeLessThan(1500);
});
test('创建用户对话框打开性能', async ({ page }) => {
await loginPage.goto();
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
await dashboardPage.navigateToUserManagement();
await page.waitForLoadState('networkidle');
const startTime = Date.now();
await userManagementPage.clickCreateUser();
await expect(page.locator('.el-dialog')).toBeVisible();
const endTime = Date.now();
const openTime = endTime - startTime;
console.log(`创建用户对话框打开时间: ${openTime}ms`);
expect(openTime).toBeLessThan(1000);
});
test('创建角色对话框打开性能', async ({ page }) => {
await loginPage.goto();
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
await dashboardPage.navigateToRoleManagement();
await page.waitForLoadState('networkidle');
const startTime = Date.now();
await roleManagementPage.clickCreateRole();
await expect(page.locator('.el-dialog')).toBeVisible();
const endTime = Date.now();
const openTime = endTime - startTime;
console.log(`创建角色对话框打开时间: ${openTime}ms`);
expect(openTime).toBeLessThan(1000);
});
test('用户搜索性能', async ({ page }) => {
await loginPage.goto();
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
await dashboardPage.navigateToUserManagement();
await page.waitForLoadState('networkidle');
const startTime = Date.now();
await userManagementPage.search('admin');
await page.waitForLoadState('networkidle');
const endTime = Date.now();
const searchTime = endTime - startTime;
console.log(`用户搜索时间: ${searchTime}ms`);
expect(searchTime).toBeLessThan(1000);
});
test('角色搜索性能', async ({ page }) => {
await loginPage.goto();
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
await dashboardPage.navigateToRoleManagement();
await page.waitForLoadState('networkidle');
const startTime = Date.now();
const searchInput = page.locator('input[placeholder*="搜索"]').or(page.locator('.search-input'));
if (await searchInput.count() > 0) {
await searchInput.fill('admin');
await page.waitForLoadState('networkidle');
}
const endTime = Date.now();
const searchTime = endTime - startTime;
console.log(`角色搜索时间: ${searchTime}ms`);
expect(searchTime).toBeLessThan(1000);
});
test('用户表单提交性能', async ({ page }) => {
await loginPage.goto();
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
await dashboardPage.navigateToUserManagement();
await page.waitForLoadState('networkidle');
await userManagementPage.clickCreateUser();
await expect(page.locator('.el-dialog')).toBeVisible();
const userData = {
username: `testuser_${Date.now()}`,
nickname: '测试用户',
email: 'test@example.com',
phone: '13800138000',
password: 'Test123!@#',
confirmPassword: 'Test123!@#',
};
await userManagementPage.fillUserForm(userData);
const startTime = Date.now();
await userManagementPage.submitForm();
await expect(page.locator('.el-message--success')).toBeVisible();
const endTime = Date.now();
const submitTime = endTime - startTime;
console.log(`用户表单提交时间: ${submitTime}ms`);
expect(submitTime).toBeLessThan(2000);
});
test('角色表单提交性能', async ({ page }) => {
await loginPage.goto();
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
await dashboardPage.navigateToRoleManagement();
await page.waitForLoadState('networkidle');
await roleManagementPage.clickCreateRole();
await expect(page.locator('.el-dialog')).toBeVisible();
const roleData = {
roleName: `测试角色_${Date.now()}`,
roleKey: `test_role_${Date.now()}`,
roleSort: '1',
status: '1',
remark: '测试角色',
};
await roleManagementPage.fillRoleForm(roleData);
const startTime = Date.now();
await roleManagementPage.submitForm();
await expect(page.locator('.el-message--success')).toBeVisible();
const endTime = Date.now();
const submitTime = endTime - startTime;
console.log(`角色表单提交时间: ${submitTime}ms`);
expect(submitTime).toBeLessThan(2000);
});
test('页面切换性能', async ({ page }) => {
await loginPage.goto();
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
const switchTimes = 5;
const startTime = Date.now();
for (let i = 0; i < switchTimes; i++) {
await dashboardPage.navigateToUserManagement();
await page.waitForLoadState('networkidle');
await dashboardPage.navigateToRoleManagement();
await page.waitForLoadState('networkidle');
}
const endTime = Date.now();
const avgSwitchTime = (endTime - startTime) / switchTimes;
console.log(`平均页面切换时间: ${avgSwitchTime}ms`);
expect(avgSwitchTime).toBeLessThan(1000);
});
test('表格滚动性能', async ({ page }) => {
await loginPage.goto();
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
await dashboardPage.navigateToUserManagement();
await page.waitForLoadState('networkidle');
const table = page.locator('.el-table').first();
await expect(table).toBeVisible();
const startTime = Date.now();
await table.evaluate(el => {
el.scrollTop = 1000;
});
await page.waitForTimeout(500);
const endTime = Date.now();
const scrollTime = endTime - startTime;
console.log(`表格滚动时间: ${scrollTime}ms`);
expect(scrollTime).toBeLessThan(500);
});
test('内存使用性能', async ({ page }) => {
await loginPage.goto();
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
const metrics = await page.evaluate(() => {
if (window.performance && (window.performance as any).memory) {
const perfMemory = (window.performance as any).memory;
return {
usedJSHeapSize: perfMemory.usedJSHeapSize,
totalJSHeapSize: perfMemory.totalJSHeapSize,
jsHeapSizeLimit: perfMemory.jsHeapSizeLimit,
};
}
return null;
});
if (metrics) {
console.log('内存使用情况:', metrics);
const memoryUsageRatio = metrics.usedJSHeapSize / metrics.jsHeapSizeLimit;
expect(memoryUsageRatio).toBeLessThan(0.8);
}
});
test('网络请求性能', async ({ page }) => {
const apiRequests: { url: string; duration: number }[] = [];
page.on('response', async (response) => {
if (response.url().includes('/api/')) {
const timing = (response as any).timing();
const duration = timing.responseEnd - timing.requestStart;
apiRequests.push({
url: response.url(),
duration,
});
}
});
await loginPage.goto();
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
await dashboardPage.navigateToUserManagement();
await page.waitForLoadState('networkidle');
if (apiRequests.length > 0) {
const avgDuration = apiRequests.reduce((sum, req) => sum + req.duration, 0) / apiRequests.length;
const maxDuration = Math.max(...apiRequests.map(req => req.duration));
console.log(`API请求平均时间: ${avgDuration}ms`);
console.log(`API请求最大时间: ${maxDuration}ms`);
expect(avgDuration).toBeLessThan(500);
expect(maxDuration).toBeLessThan(2000);
}
});
test('并发操作性能', async ({ page, context }) => {
await loginPage.goto();
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
const startTime = Date.now();
const page1 = page;
const page2 = await context.newPage();
const page3 = await context.newPage();
await Promise.all([
page1.goto('/users'),
page2.goto('/roles'),
page3.goto('/menus'),
]);
await Promise.all([
page1.waitForLoadState('networkidle'),
page2.waitForLoadState('networkidle'),
page3.waitForLoadState('networkidle'),
]);
const endTime = Date.now();
const concurrentLoadTime = endTime - startTime;
console.log(`并发页面加载时间: ${concurrentLoadTime}ms`);
expect(concurrentLoadTime).toBeLessThan(5000);
await page2.close();
await page3.close();
});
test('长时间运行稳定性', async ({ page }) => {
await loginPage.goto();
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
const startTime = Date.now();
const duration = 60000; // 1分钟
let operationCount = 0;
const interval = setInterval(async () => {
await page.goto('/users');
await page.waitForLoadState('networkidle');
await page.goto('/roles');
await page.waitForLoadState('networkidle');
operationCount++;
}, 5000);
await page.waitForTimeout(duration);
clearInterval(interval);
const endTime = Date.now();
const actualDuration = endTime - startTime;
console.log(`长时间运行操作次数: ${operationCount}`);
console.log(`长时间运行实际时间: ${actualDuration}ms`);
expect(operationCount).toBeGreaterThan(10);
});
test('响应式布局性能', async ({ page }) => {
await loginPage.goto();
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
const viewports = [
{ width: 1920, height: 1080 },
{ width: 1366, height: 768 },
{ width: 768, height: 1024 },
{ width: 375, height: 667 },
];
for (const viewport of viewports) {
const startTime = Date.now();
await page.setViewportSize(viewport);
await page.reload();
await page.waitForLoadState('networkidle');
const endTime = Date.now();
const loadTime = endTime - startTime;
console.log(`视口 ${viewport.width}x${viewport.height} 加载时间: ${loadTime}ms`);
expect(loadTime).toBeLessThan(3000);
}
});
});