Files
everything-is-suitable/everything-is-suitable-admin/e2e/performance/performance.spec.ts
T
张翔 08ea5fbe98 feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
2026-03-28 14:37:29 +08:00

196 lines
6.1 KiB
TypeScript

import { test, expect, Page } from '@playwright/test';
import { LoginPage } from '../pages/login-page';
import { testConfig } from '../core/test-config';
export class PerformanceMetrics {
private metrics: Map<string, number[]> = new Map();
recordMetric(name: string, value: number) {
if (!this.metrics.has(name)) {
this.metrics.set(name, []);
}
this.metrics.get(name)!.push(value);
}
getAverage(name: string): number {
const values = this.metrics.get(name) || [];
if (values.length === 0) return 0;
const sum = values.reduce((a, b) => a + b, 0);
return sum / values.length;
}
getP95(name: string): number {
const values = this.metrics.get(name) || [];
if (values.length === 0) return 0;
const sorted = [...values].sort((a, b) => a - b);
const index = Math.floor(sorted.length * 0.95);
return sorted[index];
}
getP99(name: string): number {
const values = this.metrics.get(name) || [];
if (values.length === 0) return 0;
const sorted = [...values].sort((a, b) => a - b);
const index = Math.floor(sorted.length * 0.99);
return sorted[index];
}
getMax(name: string): number {
const values = this.metrics.get(name) || [];
if (values.length === 0) return 0;
return Math.max(...values);
}
getMin(name: string): number {
const values = this.metrics.get(name) || [];
if (values.length === 0) return 0;
return Math.min(...values);
}
printReport() {
console.log('\n=== 性能测试报告 ===');
for (const [name, values] of this.metrics.entries()) {
console.log(`\n${name}:`);
console.log(` 平均值: ${this.getAverage(name).toFixed(2)}ms`);
console.log(` P95: ${this.getP95(name).toFixed(2)}ms`);
console.log(` P99: ${this.getP99(name).toFixed(2)}ms`);
console.log(` 最大值: ${this.getMax(name).toFixed(2)}ms`);
console.log(` 最小值: ${this.getMin(name).toFixed(2)}ms`);
console.log(` 样本数: ${values.length}`);
}
console.log('\n====================\n');
}
}
export class PerformanceTestHelper {
static async measurePageLoad(page: Page, url: string): Promise<number> {
const startTime = Date.now();
await page.goto(url, { waitUntil: 'networkidle' });
const endTime = Date.now();
return endTime - startTime;
}
static async measureApiCall(page: Page, apiCall: () => Promise<void>): Promise<number> {
const startTime = Date.now();
await apiCall();
const endTime = Date.now();
return endTime - startTime;
}
static async measureElementInteraction(
page: Page,
selector: string,
action: () => Promise<void>
): Promise<number> {
await page.waitForSelector(selector, { state: 'visible' });
const startTime = Date.now();
await action();
const endTime = Date.now();
return endTime - startTime;
}
static async measurePageNavigation(
page: Page,
fromUrl: string,
toUrl: string
): Promise<number> {
await page.goto(fromUrl, { waitUntil: 'networkidle' });
const startTime = Date.now();
await page.goto(toUrl, { waitUntil: 'networkidle' });
const endTime = Date.now();
return endTime - startTime;
}
static async measureMemoryUsage(page: Page): Promise<{ used: number; total: number }> {
const metrics = await page.evaluate(() => {
if (performance && (performance as any).memory) {
return {
used: (performance as any).memory.usedJSHeapSize,
total: (performance as any).memory.totalJSHeapSize
};
}
return { used: 0, total: 0 };
});
return metrics;
}
static async measureNetworkRequests(page: Page): Promise<number> {
let requestCount = 0;
page.on('request', () => {
requestCount++;
});
return requestCount;
}
static async clearCacheAndCookies(page: Page) {
await page.context().clearCookies();
await page.context().clearPermissions();
}
}
test.describe.configure({
mode: 'serial',
timeout: 120000
});
test.describe('性能测试 - 页面加载性能', () => {
const metrics = new PerformanceMetrics();
const helper = new PerformanceTestHelper();
test.afterAll(() => {
metrics.printReport();
});
test('PT-001: 登录页面加载性能', async ({ page }) => {
const loadTime = await helper.measurePageLoad(page, testConfig.getBaseURL());
metrics.recordMetric('登录页面加载时间', loadTime);
expect(loadTime).toBeLessThan(3000);
});
test('PT-002: 仪表盘页面加载性能', async ({ page }) => {
const loginPage = new LoginPage(page);
await page.goto(testConfig.getBaseURL());
await loginPage.login('admin', 'admin123');
const loadTime = await helper.measurePageLoad(page, `${testConfig.getBaseURL()}/dashboard`);
metrics.recordMetric('仪表盘页面加载时间', loadTime);
expect(loadTime).toBeLessThan(2000);
});
test('PT-003: 用户管理页面加载性能', async ({ page }) => {
const loginPage = new LoginPage(page);
await page.goto(testConfig.getBaseURL());
await loginPage.login('admin', 'admin123');
const loadTime = await helper.measurePageLoad(page, `${testConfig.getBaseURL()}/users`);
metrics.recordMetric('用户管理页面加载时间', loadTime);
expect(loadTime).toBeLessThan(2000);
});
test('PT-004: 黄历页面加载性能', async ({ page }) => {
const loginPage = new LoginPage(page);
await page.goto(testConfig.getBaseURL());
await loginPage.login('admin', 'admin123');
const loadTime = await helper.measurePageLoad(page, `${testConfig.getBaseURL()}/almanac`);
metrics.recordMetric('黄历页面加载时间', loadTime);
expect(loadTime).toBeLessThan(2000);
});
test('PT-005: 运势页面加载性能', async ({ page }) => {
const loginPage = new LoginPage(page);
await page.goto(testConfig.getBaseURL());
await loginPage.login('admin', 'admin123');
const loadTime = await helper.measurePageLoad(page, `${testConfig.getBaseURL()}/fortune`);
metrics.recordMetric('运势页面加载时间', loadTime);
expect(loadTime).toBeLessThan(2000);
});
});