feat: 添加测试框架和覆盖率报告功能

feat(测试): 新增Playwright和Vitest测试配置
feat(测试): 添加测试覆盖率报告生成功能
feat(测试): 实现前后端测试脚本集成

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

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

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

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

chore: 更新依赖版本
chore: 添加测试相关配置文件
This commit is contained in:
张翔
2026-03-25 09:03:37 +08:00
parent 117978e148
commit e2ad1331cc
126 changed files with 18083 additions and 7805 deletions
@@ -0,0 +1,417 @@
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';
import { TestHelper } from './utils/testHelper';
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);
await loginPage.goto();
});
test.afterEach(async ({ page }) => {
await TestHelper.clearAllStorage(page);
});
test.describe('等待策略优化测试', () => {
test('登录页面 - 使用精确等待', async ({ page }) => {
const startTime = Date.now();
await test.step('等待登录页面加载完成', async () => {
await page.waitForLoadState('networkidle');
await page.waitForSelector('[data-testid="login-form"]', { state: 'visible' });
});
const endTime = Date.now();
const loadTime = endTime - startTime;
console.log(`登录页面加载时间: ${loadTime}ms`);
expect(loadTime).toBeLessThan(3000);
});
test('用户列表 - 使用智能等待', async ({ page }) => {
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
const startTime = Date.now();
await test.step('等待用户列表加载完成', async () => {
await page.goto('/users');
await page.waitForLoadState('domcontentloaded');
await page.waitForSelector('[data-testid="user-table"]', { state: 'attached' });
await page.waitForSelector('.el-table__body tr', { state: 'visible' });
});
const endTime = Date.now();
const loadTime = endTime - startTime;
console.log(`用户列表加载时间: ${loadTime}ms`);
expect(loadTime).toBeLessThan(2000);
});
test('角色列表 - 使用条件等待', async ({ page }) => {
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
const startTime = Date.now();
await test.step('等待角色列表加载完成', async () => {
await page.goto('/roles');
await page.waitForFunction(() => {
const rows = document.querySelectorAll('.el-table__body tr');
return rows.length > 0;
});
});
const endTime = Date.now();
const loadTime = endTime - startTime;
console.log(`角色列表加载时间: ${loadTime}ms`);
expect(loadTime).toBeLessThan(2000);
});
});
test.describe('选择器优化测试', () => {
test('使用data-testid选择器', async ({ page }) => {
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
const startTime = Date.now();
await test.step('使用data-testid定位元素', async () => {
await page.goto('/users');
await page.waitForSelector('[data-testid="user-table"]');
const createButton = page.locator('[data-testid="create-user-button"]');
await createButton.click();
await page.waitForSelector('[data-testid="user-form"]');
await page.fill('[data-testid="username-input"]', 'testuser');
await page.fill('[data-testid="password-input"]', 'password123');
await page.fill('[data-testid="email-input"]', 'test@example.com');
await page.click('[data-testid="save-button"]');
});
const endTime = Date.now();
const operationTime = endTime - startTime;
console.log(`data-testid选择器操作时间: ${operationTime}ms`);
expect(operationTime).toBeLessThan(3000);
});
test('选择器性能对比', async ({ page }) => {
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
await test.step('对比不同选择器性能', async () => {
await page.goto('/users');
await page.waitForSelector('[data-testid="user-table"]');
const startTime1 = Date.now();
const element1 = page.locator('[data-testid="create-user-button"]');
await element1.click();
const time1 = Date.now() - startTime1;
await page.click('.el-button--primary');
await page.waitForTimeout(500);
const startTime2 = Date.now();
const element2 = page.locator('button.el-button--primary');
await element2.click();
const time2 = Date.now() - startTime2;
console.log(`data-testid选择器: ${time1}ms`);
console.log(`CSS选择器: ${time2}ms`);
expect(time1).toBeLessThan(time2);
});
});
});
test.describe('测试数据优化测试', () => {
test('使用缓存数据', async ({ page }) => {
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
const startTime = Date.now();
await test.step('首次加载用户列表', async () => {
await page.goto('/users');
await page.waitForSelector('[data-testid="user-table"]');
});
const firstLoadTime = Date.now() - startTime;
await page.goto('/dashboard');
await page.waitForURL(/.*dashboard/);
const startTime2 = Date.now();
await test.step('再次加载用户列表(使用缓存)', async () => {
await page.goto('/users');
await page.waitForSelector('[data-testid="user-table"]');
});
const secondLoadTime = Date.now() - startTime2;
console.log(`首次加载时间: ${firstLoadTime}ms`);
console.log(`缓存加载时间: ${secondLoadTime}ms`);
expect(secondLoadTime).toBeLessThan(firstLoadTime);
});
test('优化数据准备时间', async ({ page, request }) => {
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
const startTime = Date.now();
await test.step('批量创建用户并测试性能', async () => {
const users = [];
for (let i = 0; i < 10; i++) {
const user = {
username: `perfuser${i}`,
password: 'password123',
email: `perfuser${i}@example.com`,
roleIds: ['1']
};
users.push(user);
await request.post('http://localhost:8084/api/users', {
data: user,
headers: {
'Authorization': `Bearer ${await TestHelper.getAuthToken(page)}`
}
});
}
});
const dataPrepTime = Date.now() - startTime;
const startTime2 = Date.now();
await test.step('加载大量用户数据', async () => {
await page.goto('/users');
await page.waitForSelector('[data-testid="user-table"]');
await page.waitForFunction(() => {
const rows = document.querySelectorAll('.el-table__body tr');
return rows.length >= 10;
});
});
const loadTime = Date.now() - startTime2;
console.log(`数据准备时间: ${dataPrepTime}ms`);
console.log(`数据加载时间: ${loadTime}ms`);
expect(loadTime).toBeLessThan(5000);
});
});
test.describe('测试隔离优化测试', () => {
test('独立测试环境', async ({ page, context }) => {
const page1 = page;
const page2 = await context.newPage();
await test.step('在独立页面中执行测试', async () => {
await page1.goto('/login');
await page2.goto('/login');
await page1.fill('[data-testid="username-input"]', 'admin');
await page2.fill('[data-testid="username-input"]', 'testuser');
await page1.fill('[data-testid="password-input"]', 'admin123');
await page2.fill('[data-testid="password-input"]', 'password123');
await page1.click('[data-testid="login-button"]');
await page2.click('[data-testid="login-button"]');
await page1.waitForURL(/.*dashboard/);
await page2.waitForURL(/.*dashboard/);
});
await test.step('验证页面隔离', async () => {
const url1 = page1.url();
const url2 = page2.url();
expect(url1).toContain('/dashboard');
expect(url2).toContain('/dashboard');
expect(url1).not.toBe(url2);
});
});
test('测试清理优化', async ({ page, request }) => {
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
const startTime = Date.now();
await test.step('创建测试数据', async () => {
const user = {
username: 'cleanupuser',
password: 'password123',
email: 'cleanup@example.com',
roleIds: ['1']
};
await request.post('http://localhost:8084/api/users', {
data: user,
headers: {
'Authorization': `Bearer ${await TestHelper.getAuthToken(page)}`
}
});
});
const createTime = Date.now() - startTime;
const startTime2 = Date.now();
await test.step('快速清理测试数据', async () => {
const usersResponse = await request.get('http://localhost:8084/api/users', {
headers: {
'Authorization': `Bearer ${await TestHelper.getAuthToken(page)}`
}
});
const usersData = await usersResponse.json();
const cleanupUser = usersData.find(u => u.username === 'cleanupuser');
if (cleanupUser) {
await request.delete(`http://localhost:8084/api/users/${cleanupUser.id}`, {
headers: {
'Authorization': `Bearer ${await TestHelper.getAuthToken(page)}`
}
});
}
});
const cleanupTime = Date.now() - startTime2;
console.log(`数据创建时间: ${createTime}ms`);
console.log(`数据清理时间: ${cleanupTime}ms`);
expect(cleanupTime).toBeLessThan(1000);
});
});
test.describe('并行化优化测试', () => {
test('并行执行多个测试', async ({ page }) => {
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
const startTime = Date.now();
await test.step('并行加载多个页面', async () => {
const promises = [
page.goto('/users'),
page.goto('/roles'),
page.goto('/settings')
];
await Promise.all(promises);
});
const endTime = Date.now();
const parallelTime = endTime - startTime;
console.log(`并行加载时间: ${parallelTime}ms`);
expect(parallelTime).toBeLessThan(5000);
});
test('并发API请求', async ({ page, request }) => {
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
const startTime = Date.now();
await test.step('并发发送多个API请求', async () => {
const promises = [
request.get('http://localhost:8084/api/users', {
headers: {
'Authorization': `Bearer ${await TestHelper.getAuthToken(page)}`
}
}),
request.get('http://localhost:8084/api/roles', {
headers: {
'Authorization': `Bearer ${await TestHelper.getAuthToken(page)}`
}
}),
request.get('http://localhost:8084/api/permissions', {
headers: {
'Authorization': `Bearer ${await TestHelper.getAuthToken(page)}`
}
})
];
await Promise.all(promises);
});
const endTime = Date.now();
const concurrentTime = endTime - startTime;
console.log(`并发请求时间: ${concurrentTime}ms`);
expect(concurrentTime).toBeLessThan(2000);
});
});
test.describe('内存和资源优化测试', () => {
test('内存使用监控', async ({ page }) => {
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
const initialMemory = await page.evaluate(() => {
if ((window.performance as any).memory) {
return (window.performance as any).memory.usedJSHeapSize;
}
return 0;
});
await test.step('执行多个操作', async () => {
await page.goto('/users');
await page.waitForSelector('[data-testid="user-table"]');
await page.goto('/roles');
await page.waitForSelector('[data-testid="role-table"]');
await page.goto('/settings');
await page.waitForSelector('[data-testid="settings-form"]');
});
const finalMemory = await page.evaluate(() => {
if ((window.performance as any).memory) {
return (window.performance as any).memory.usedJSHeapSize;
}
return 0;
});
const memoryIncrease = finalMemory - initialMemory;
const memoryIncreaseMB = memoryIncrease / (1024 * 1024);
console.log(`内存增长: ${memoryIncreaseMB.toFixed(2)}MB`);
expect(memoryIncreaseMB).toBeLessThan(50);
});
test('DOM节点数量监控', async ({ page }) => {
await loginPage.login('admin', 'admin123');
await page.waitForURL(/.*dashboard/);
await test.step('监控DOM节点数量', async () => {
await page.goto('/users');
await page.waitForSelector('[data-testid="user-table"]');
const nodeCount = await page.evaluate(() => {
return document.querySelectorAll('*').length;
});
console.log(`DOM节点数量: ${nodeCount}`);
expect(nodeCount).toBeLessThan(5000);
});
});
});
});