diff --git a/e2e/utils/test-reporter.ts b/e2e/utils/test-reporter.ts new file mode 100644 index 0000000..f3521b6 --- /dev/null +++ b/e2e/utils/test-reporter.ts @@ -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; diff --git a/playwright.config.ts b/playwright.config.ts index df74cae..fc1acf9 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -43,9 +43,13 @@ export default defineConfig({ ? [ ['html', { outputFolder: 'reports/html', open: 'never' }], ['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: { baseURL, trace: 'on-first-retry',