Describe the bug
In the JUnit XML produced by junitReporter, the root <testsuites timestamp="..."> is correct (the actual run-start time), but the nested <testsuite timestamp="..."> for each suite is wrong — it holds the moment the XML file was written (i.e. after that suite, including AfterSuite, finished), not when the suite started.
Root cause
lib/plugin/junitReporter.js:
setAttr(root, 'timestamp', toIso(result.stats && result.stats.start)) // correct: Mocha's real run-start stat
...
setAttr(suiteEl, 'timestamp', toIso(suite && suite.startedAt)) // suite.startedAt is never set anywhere
function toIso(value) {
const date = value ? new Date(value) : new Date()
return Number.isNaN(date.getTime()) ? new Date().toISOString() : date.toISOString()
}
suite.startedAt doesn't exist on Mocha's Suite — I grepped the whole codeceptjs package and startedAt is only ever set on individual test objects (lib/listener/steps.js:20), never on a Suite. So suite && suite.startedAt is always undefined, toIso() falls through to its new Date() fallback, and the <testsuite> gets stamped with "now" at write time — effectively the run's end time, not its start.
To Reproduce
- Run any suite with
-p junitReporter (or the junitReporter plugin enabled in config).
- Open the generated
report.xml.
- Compare the root
<testsuites timestamp> against the nested <testsuite timestamp> — the nested one matches the file's mtime / run-finish time instead of run-start time.
Example from a real run (root suite ran 08:09:58–08:10:20 local / 06:09:58–06:10:20 UTC):
<testsuites name="CodeceptJS" tests="5" ... timestamp="2026-07-30T06:09:58.974Z">
<testsuite name="LeaveRequest" ... timestamp="2026-07-30T06:10:20.079Z" ...>
The root timestamp (06:09:58.974Z) is right. The suite timestamp (06:10:20.079Z) matches report.xml's file mtime (08:10:20.079420438 +0200 local), i.e. write time, not start time — a ~22s discrepancy in this run.
Expected behavior
The <testsuite> timestamp attribute should reflect when that suite actually started (e.g. captured via event.suite.before, or derived from the earliest test.startedAt/test.opts.startedAt among the suite's tests), not the report-write time.
Environment
- CodeceptJS: 4.0.9
- Node: 24.18.0
- OS: Linux 6.17, Ubuntu 24.04.4 LTS
Related
Same underlying failure pattern — "now" captured at report-build/write time gets mislabeled as a start timestamp — also found and reported separately in @testomatio/reporter's HTML report ("Started At" field): testomatio/reporter#903
🤖 Filed with the help of Claude Sonnet 5 (Anthropic)
Describe the bug
In the JUnit XML produced by
junitReporter, the root<testsuites timestamp="...">is correct (the actual run-start time), but the nested<testsuite timestamp="...">for each suite is wrong — it holds the moment the XML file was written (i.e. after that suite, includingAfterSuite, finished), not when the suite started.Root cause
lib/plugin/junitReporter.js:suite.startedAtdoesn't exist on Mocha'sSuite— I grepped the wholecodeceptjspackage andstartedAtis only ever set on individual test objects (lib/listener/steps.js:20), never on aSuite. Sosuite && suite.startedAtis alwaysundefined,toIso()falls through to itsnew Date()fallback, and the<testsuite>gets stamped with "now" at write time — effectively the run's end time, not its start.To Reproduce
-p junitReporter(or thejunitReporterplugin enabled in config).report.xml.<testsuites timestamp>against the nested<testsuite timestamp>— the nested one matches the file's mtime / run-finish time instead of run-start time.Example from a real run (root suite ran 08:09:58–08:10:20 local / 06:09:58–06:10:20 UTC):
The root timestamp (06:09:58.974Z) is right. The suite timestamp (06:10:20.079Z) matches
report.xml's file mtime (08:10:20.079420438 +0200local), i.e. write time, not start time — a ~22s discrepancy in this run.Expected behavior
The
<testsuite>timestampattribute should reflect when that suite actually started (e.g. captured viaevent.suite.before, or derived from the earliesttest.startedAt/test.opts.startedAtamong the suite's tests), not the report-write time.Environment
Related
Same underlying failure pattern — "now" captured at report-build/write time gets mislabeled as a start timestamp — also found and reported separately in
@testomatio/reporter's HTML report ("Started At" field): testomatio/reporter#903🤖 Filed with the help of Claude Sonnet 5 (Anthropic)