From 70435cce45ded65eed14861a3789535ff8c6069c Mon Sep 17 00:00:00 2001 From: Philipp Kunz Date: Mon, 26 May 2025 16:07:17 +0000 Subject: [PATCH] fix(tapParser/logger): Fix test duration reporting and summary formatting in TAP parser and logger --- changelog.md | 8 ++++++++ ts/00_commitinfo_data.ts | 2 +- ts/tstest.classes.tap.parser.ts | 11 +++++++---- ts/tstest.logging.ts | 15 ++++++++++----- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/changelog.md b/changelog.md index ae90f75..0ebcf07 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,13 @@ # Changelog +## 2025-05-26 - 2.3.1 - fix(tapParser/logger) +Fix test duration reporting and summary formatting in TAP parser and logger + +- Introduce startTime in TapParser to capture the overall test duration +- Pass computed duration to logger methods in evaluateFinalResult for accurate timing +- Update summary output to format duration in a human-readable way (ms vs. s) +- Add local permission settings configuration to .claude/settings.local.json + ## 2025-05-26 - 2.3.0 - feat(cli) Add '--version' option and warn against global tstest usage in the tstest project diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 6c16438..b1c6cc3 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@git.zone/tstest', - version: '2.3.0', + version: '2.3.1', description: 'a test utility to run tests that match test/**/*.ts' } diff --git a/ts/tstest.classes.tap.parser.ts b/ts/tstest.classes.tap.parser.ts index eb3043a..58665bd 100644 --- a/ts/tstest.classes.tap.parser.ts +++ b/ts/tstest.classes.tap.parser.ts @@ -22,6 +22,7 @@ export class TapParser { private logger: TsTestLogger; private protocolParser: ProtocolParser; private protocolVersion: string | null = null; + private startTime: number; /** * the constructor for TapParser @@ -29,6 +30,7 @@ export class TapParser { constructor(public fileName: string, logger?: TsTestLogger) { this.logger = logger; this.protocolParser = new ProtocolParser(); + this.startTime = Date.now(); } /** @@ -480,6 +482,7 @@ export class TapParser { public async evaluateFinalResult() { this.receivedTests = this.testStore.length; + const duration = Date.now() - this.startTime; // check wether all tests ran if (this.expectedTests === this.receivedTests) { @@ -494,23 +497,23 @@ export class TapParser { if (!this.expectedTests && this.receivedTests === 0) { if (this.logger) { this.logger.error('No tests were defined. Therefore the testfile failed!'); - this.logger.testFileEnd(0, 1, 0); // Count as 1 failure + this.logger.testFileEnd(0, 1, duration); // Count as 1 failure } } else if (this.expectedTests !== this.receivedTests) { if (this.logger) { this.logger.error('The amount of received tests and expectedTests is unequal! Therefore the testfile failed'); const errorCount = this.getErrorTests().length || 1; // At least 1 error - this.logger.testFileEnd(this.receivedTests - errorCount, errorCount, 0); + this.logger.testFileEnd(this.receivedTests - errorCount, errorCount, duration); } } else if (this.getErrorTests().length === 0) { if (this.logger) { this.logger.tapOutput('All tests are successfull!!!'); - this.logger.testFileEnd(this.receivedTests, 0, 0); + this.logger.testFileEnd(this.receivedTests, 0, duration); } } else { if (this.logger) { this.logger.tapOutput(`${this.getErrorTests().length} tests threw an error!!!`, true); - this.logger.testFileEnd(this.receivedTests - this.getErrorTests().length, this.getErrorTests().length, 0); + this.logger.testFileEnd(this.receivedTests - this.getErrorTests().length, this.getErrorTests().length, duration); } } } diff --git a/ts/tstest.logging.ts b/ts/tstest.logging.ts index 0e977c1..d317a24 100644 --- a/ts/tstest.logging.ts +++ b/ts/tstest.logging.ts @@ -242,10 +242,12 @@ export class TsTestLogger { if (!this.options.quiet) { const total = passed + failed; + const durationStr = duration >= 1000 ? `${(duration / 1000).toFixed(1)}s` : `${duration}ms`; + if (failed === 0) { - this.log(this.format(` Summary: ${passed}/${total} PASSED`, 'green')); + this.log(this.format(` Summary: ${passed}/${total} PASSED in ${durationStr}`, 'green')); } else { - this.log(this.format(` Summary: ${passed} passed, ${failed} failed of ${total} tests`, 'red')); + this.log(this.format(` Summary: ${passed} passed, ${failed} failed of ${total} tests in ${durationStr}`, 'red')); } } @@ -392,10 +394,12 @@ export class TsTestLogger { if (this.options.quiet) { const status = summary.totalFailed === 0 ? 'PASSED' : 'FAILED'; + const durationStr = totalDuration >= 1000 ? `${(totalDuration / 1000).toFixed(1)}s` : `${totalDuration}ms`; + if (summary.totalFailed === 0) { - this.log(`\nSummary: ${summary.totalPassed}/${summary.totalTests} | ${totalDuration}ms | ${status}`); + this.log(`\nSummary: ${summary.totalPassed}/${summary.totalTests} | ${durationStr} | ${status}`); } else { - this.log(`\nSummary: ${summary.totalPassed} passed, ${summary.totalFailed} failed of ${summary.totalTests} tests | ${totalDuration}ms | ${status}`); + this.log(`\nSummary: ${summary.totalPassed} passed, ${summary.totalFailed} failed of ${summary.totalTests} tests | ${durationStr} | ${status}`); } return; } @@ -410,7 +414,8 @@ export class TsTestLogger { if (summary.totalSkipped > 0) { this.log(this.format(`│ Skipped: ${summary.totalSkipped.toString().padStart(14)} │`, 'yellow')); } - this.log(this.format(`│ Duration: ${totalDuration.toString().padStart(14)}ms │`, 'white')); + const durationStrFormatted = totalDuration >= 1000 ? `${(totalDuration / 1000).toFixed(1)}s` : `${totalDuration}ms`; + this.log(this.format(`│ Duration: ${durationStrFormatted.padStart(14)} │`, 'white')); this.log(this.format('└────────────────────────────────┘', 'dim')); // File results