feat(test): add custom metrics reporter and update playwright config
This commit is contained in:
@@ -0,0 +1,67 @@
|
|||||||
|
import { Reporter, TestCase, TestResult } from '@playwright/test/reporter';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
|
||||||
|
interface TestMetrics {
|
||||||
|
total: number;
|
||||||
|
passed: number;
|
||||||
|
failed: number;
|
||||||
|
skipped: number;
|
||||||
|
duration: number;
|
||||||
|
passRate: number;
|
||||||
|
avgDuration: number;
|
||||||
|
flakyTests: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
class MetricsReporter implements Reporter {
|
||||||
|
private tests: Array<{ test: TestCase; result: TestResult }> = [];
|
||||||
|
|
||||||
|
onTestEnd(test: TestCase, result: TestResult) {
|
||||||
|
this.tests.push({ test, result });
|
||||||
|
}
|
||||||
|
|
||||||
|
onEnd() {
|
||||||
|
const metrics: TestMetrics = {
|
||||||
|
total: this.tests.length,
|
||||||
|
passed: this.tests.filter(t => t.result.status === 'passed').length,
|
||||||
|
failed: this.tests.filter(t => t.result.status === 'failed').length,
|
||||||
|
skipped: this.tests.filter(t => t.result.status === 'skipped').length,
|
||||||
|
duration: this.tests.reduce((sum, t) => sum + t.result.duration, 0),
|
||||||
|
passRate: 0,
|
||||||
|
avgDuration: 0,
|
||||||
|
flakyTests: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
metrics.passRate = metrics.total > 0 ? (metrics.passed / metrics.total) * 100 : 0;
|
||||||
|
metrics.avgDuration = metrics.total > 0 ? metrics.duration / metrics.total : 0;
|
||||||
|
|
||||||
|
const flakyTests = this.tests.filter(
|
||||||
|
t => t.result.status === 'passed' && t.result.retryCount > 0
|
||||||
|
);
|
||||||
|
metrics.flakyTests = flakyTests.map(t => t.test.title);
|
||||||
|
|
||||||
|
if (!fs.existsSync('reports')) {
|
||||||
|
fs.mkdirSync('reports', { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(
|
||||||
|
'reports/test-metrics.json',
|
||||||
|
JSON.stringify(metrics, null, 2)
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log('\n=== 测试质量指标 ===');
|
||||||
|
console.log(`总测试数: ${metrics.total}`);
|
||||||
|
console.log(`通过: ${metrics.passed}`);
|
||||||
|
console.log(`失败: ${metrics.failed}`);
|
||||||
|
console.log(`跳过: ${metrics.skipped}`);
|
||||||
|
console.log(`通过率: ${metrics.passRate.toFixed(2)}%`);
|
||||||
|
console.log(`平均执行时间: ${(metrics.avgDuration / 1000).toFixed(2)}秒`);
|
||||||
|
console.log(`总执行时间: ${(metrics.duration / 1000).toFixed(2)}秒`);
|
||||||
|
|
||||||
|
if (metrics.flakyTests.length > 0) {
|
||||||
|
console.log(`\n⚠️ Flaky 测试 (${metrics.flakyTests.length}):`);
|
||||||
|
metrics.flakyTests.forEach(title => console.log(` - ${title}`));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MetricsReporter;
|
||||||
@@ -43,9 +43,13 @@ export default defineConfig({
|
|||||||
? [
|
? [
|
||||||
['html', { outputFolder: 'reports/html', open: 'never' }],
|
['html', { outputFolder: 'reports/html', open: 'never' }],
|
||||||
['json', { outputFile: 'reports/results.json' }],
|
['json', { outputFile: 'reports/results.json' }],
|
||||||
['list']
|
['list'],
|
||||||
|
['./e2e/utils/test-reporter.ts']
|
||||||
]
|
]
|
||||||
: 'html',
|
: [
|
||||||
|
['html', { outputFolder: 'reports/html', open: 'never' }],
|
||||||
|
['./e2e/utils/test-reporter.ts']
|
||||||
|
],
|
||||||
use: {
|
use: {
|
||||||
baseURL,
|
baseURL,
|
||||||
trace: 'on-first-retry',
|
trace: 'on-first-retry',
|
||||||
|
|||||||
Reference in New Issue
Block a user