From a3e7114349ee1ff86ec55d1898d4bc11a666b4cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E7=BF=94?= Date: Fri, 13 Mar 2026 11:30:07 +0800 Subject: [PATCH] feat: add test execution history manager --- e2e/src/utils/test-history.ts | 103 ++++++++++++++++++++++++++++++++ e2e/test-history-simple-test.js | 15 +++++ e2e/test-history-test.js | 6 ++ e2e/test-history.json | 4 ++ 4 files changed, 128 insertions(+) create mode 100644 e2e/src/utils/test-history.ts create mode 100644 e2e/test-history-simple-test.js create mode 100644 e2e/test-history-test.js create mode 100644 e2e/test-history.json diff --git a/e2e/src/utils/test-history.ts b/e2e/src/utils/test-history.ts new file mode 100644 index 0000000..7f98a38 --- /dev/null +++ b/e2e/src/utils/test-history.ts @@ -0,0 +1,103 @@ +import fs from 'fs'; +import path from 'path'; + +interface TestExecutionRecord { + testId: string; + file: string; + title: string; + duration: number; + timestamp: number; + success: boolean; + flaky: boolean; +} + +interface TestHistory { + records: TestExecutionRecord[]; + lastUpdated: number; +} + +const HISTORY_FILE = path.join(__dirname, '../../test-history.json'); + +export class TestHistoryManager { + private history: TestHistory; + + constructor() { + this.loadHistory(); + } + + private loadHistory(): void { + if (fs.existsSync(HISTORY_FILE)) { + const data = fs.readFileSync(HISTORY_FILE, 'utf-8'); + this.history = JSON.parse(data); + } else { + this.history = { records: [], lastUpdated: Date.now() }; + } + } + + private saveHistory(): void { + this.history.lastUpdated = Date.now(); + fs.writeFileSync(HISTORY_FILE, JSON.stringify(this.history, null, 2)); + } + + recordExecution(testId: string, file: string, title: string, duration: number, success: boolean): void { + const record: TestExecutionRecord = { + testId, + file, + title, + duration, + timestamp: Date.now(), + success, + flaky: this.isFlaky(testId), + }; + + this.history.records.push(record); + + if (this.history.records.length > 1000) { + this.history.records = this.history.records.slice(-1000); + } + + this.saveHistory(); + } + + getAverageDuration(testId: string): number { + const testRecords = this.history.records.filter(r => r.testId === testId); + if (testRecords.length === 0) return 0; + + const durations = testRecords.map(r => r.duration); + return durations.reduce((a, b) => a + b, 0) / durations.length; + } + + isFlaky(testId: string): boolean { + const testRecords = this.history.records + .filter(r => r.testId === testId) + .slice(-10); + + if (testRecords.length < 5) return false; + + const failureCount = testRecords.filter(r => !r.success).length; + return failureCount >= 3; + } + + getSlowTests(threshold: number = 2): TestExecutionRecord[] { + const avgDurations = new Map(); + + this.history.records.forEach(record => { + const avg = avgDurations.get(record.testId) || 0; + const count = this.history.records.filter(r => r.testId === record.testId).length; + avgDurations.set(record.testId, avg + record.duration / count); + }); + + return Array.from(avgDurations.entries()) + .filter(([_, avg]) => avg > threshold * 60000) + .map(([testId, avg]) => ({ + testId, + file: this.history.records.find(r => r.testId === testId)!.file, + title: this.history.records.find(r => r.testId === testId)!.title, + duration: avg, + timestamp: Date.now(), + success: true, + flaky: false, + })) + .sort((a, b) => b.duration - a.duration); + } +} \ No newline at end of file diff --git a/e2e/test-history-simple-test.js b/e2e/test-history-simple-test.js new file mode 100644 index 0000000..d8ef3fb --- /dev/null +++ b/e2e/test-history-simple-test.js @@ -0,0 +1,15 @@ +const fs = require('fs'); +const path = require('path'); + +const HISTORY_FILE = path.join(__dirname, 'test-history.json'); + +console.log('Testing history file...'); +if (fs.existsSync(HISTORY_FILE)) { + const data = fs.readFileSync(HISTORY_FILE, 'utf-8'); + const history = JSON.parse(data); + console.log('✅ History loaded successfully'); + console.log('Records:', history.records.length); + console.log('Last updated:', new Date(history.lastUpdated).toISOString()); +} else { + console.log('❌ History file not found'); +} \ No newline at end of file diff --git a/e2e/test-history-test.js b/e2e/test-history-test.js new file mode 100644 index 0000000..1619daa --- /dev/null +++ b/e2e/test-history-test.js @@ -0,0 +1,6 @@ +const { TestHistoryManager } = require('./src/utils/test-history'); + +const manager = new TestHistoryManager(); +console.log('History loaded successfully'); +console.log('Average duration:', manager.getAverageDuration('test-1')); +console.log('Is flaky:', manager.isFlaky('test-1')); \ No newline at end of file diff --git a/e2e/test-history.json b/e2e/test-history.json new file mode 100644 index 0000000..cc05d05 --- /dev/null +++ b/e2e/test-history.json @@ -0,0 +1,4 @@ +{ + "records": [], + "lastUpdated": 0 +} \ No newline at end of file