| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 3f54c8b commit 904bdf5
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -62,6 +62,7 @@ function reportReruns(previousRuns, globalOptions) { | |||
| 62 | 62 | name: data.name, | |
| 63 | 63 | children, | |
| 64 | 64 | passed_on_attempt: data.details.passed_on_attempt ?? data.details.attempt, | |
| 65 | + duration_ms: data.details.duration_ms, | ||
| 65 | 66 | }; | |
| 66 | 67 | } | |
| 67 | 68 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -9,10 +9,12 @@ const { | |||
| 9 | 9 | ArrayPrototypeSplice, | |
| 10 | 10 | ArrayPrototypeUnshift, | |
| 11 | 11 | ArrayPrototypeUnshiftApply, | |
| 12 | + BigInt, | ||
| 12 | 13 | Error, | |
| 13 | 14 | FunctionPrototype, | |
| 14 | 15 | MathFloor, | |
| 15 | 16 | MathMax, | |
| 17 | + MathRound, | ||
| 16 | 18 | Number, | |
| 17 | 19 | NumberPrototypeToFixed, | |
| 18 | 20 | ObjectKeys, | |
@@ -769,14 +771,25 @@ class Test extends AsyncResource { | |||
| 769 | 771 | const previousAttempt = this.root.harness.previousRuns[this.attempt - 1]?.[testIdentifier]; | |
| 770 | 772 | if (previousAttempt != null) { | |
| 771 | 773 | this.passedAttempt = previousAttempt.passed_on_attempt; | |
| 774 | + if (previousAttempt.duration_ms !== undefined) { | ||
| 775 | + this.replayedDurationNs = BigInt(MathRound(previousAttempt.duration_ms * 1_000_000)); | ||
| 776 | + } | ||
| 772 | 777 | this.fn = () => { | |
| 778 | + // Restore the original duration on the synthetic replay. Suites are | ||
| 779 | + // skipped here because Suite.run() unconditionally reassigns | ||
| 780 | + // startTime later; only non-suite tests benefit from setting it. | ||
| 781 | + if (this.reportedType !== 'suite') { | ||
| 782 | + this.startTime = hrtime(); | ||
| 783 | + this.endTime = this.startTime + (this.replayedDurationNs ?? 0n); | ||
| 784 | + } | ||
| 773 | 785 | for (let i = 0; i < (previousAttempt.children?.length ?? 0); i++) { | |
| 774 | 786 | const child = previousAttempt.children[i]; | |
| 775 | 787 | const t = this.createSubtest(Test, child.name, { __proto__: null }, noop, { | |
| 776 | 788 | __proto__: null, | |
| 777 | 789 | loc: [child.line, child.column, child.file], | |
| 778 | 790 | }, noop); | |
| 779 | - t.endTime = t.startTime = hrtime(); | ||
| 791 | + t.startTime = hrtime(); | ||
| 792 | + t.endTime = t.startTime + (t.replayedDurationNs ?? 0n); | ||
| 780 | 793 | // For suites, Suite.run() starts the subtests via SafePromiseAll. | |
| 781 | 794 | // Starting them here as well would run them twice, re-invoking the | |
| 782 | 795 | // synthetic children-creator against a now-incremented disambiguator | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,13 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + // A passing test with a measurable duration alongside a failing test. The | ||
| 3 | + // failing test forces the rerun feature to retry on a second invocation, | ||
| 4 | + // causing the passing test to be replayed via the synthetic noop stub. | ||
| 5 | + const { test } = require('node:test'); | ||
| 6 | + | ||
| 7 | + test('passing slow test', async () => { | ||
| 8 | + await new Promise((resolve) => setTimeout(resolve, 25)); | ||
| 9 | + }); | ||
| 10 | + | ||
| 11 | + test('always failing', () => { | ||
| 12 | + throw new Error('boom'); | ||
| 13 | + }); | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -89,6 +89,7 @@ const getStateFile = async () => { | |||
| 89 | 89 | res.forEach((entry) => { | |
| 90 | 90 | for (const item in entry) { | |
| 91 | 91 | delete entry[item].children; | |
| 92 | + delete entry[item].duration_ms; | ||
| 92 | 93 | } | |
| 93 | 94 | }); | |
| 94 | 95 | return res; | |
@@ -152,6 +153,20 @@ test('test should pass on third rerun with `--test`', async () => { | |||
| 152 | 153 | assert.deepStrictEqual(await getStateFile(), expectedStateFile); | |
| 153 | 154 | }); | |
| 154 | 155 | ||
| 156 | + test('rerun preserves the original duration on the replayed pass', async () => { | ||
| 157 | + const durationFixture = fixtures.path('test-runner', 'rerun-duration.js'); | ||
| 158 | + const args = ['--test-rerun-failures', stateFile, durationFixture]; | ||
| 159 | + | ||
| 160 | + await common.spawnPromisified(process.execPath, args); | ||
| 161 | + await common.spawnPromisified(process.execPath, args); | ||
| 162 | + | ||
| 163 | + const raw = JSON.parse(await readFile(stateFile, 'utf8')); | ||
| 164 | + const passKey = Object.keys(raw[0]).find((k) => raw[0][k].name === 'passing slow test'); | ||
| 165 | + assert.ok(passKey, 'expected the passing test to be recorded on attempt 0'); | ||
| 166 | + assert.ok(raw[0][passKey].duration_ms > 0, 'expected a measurable duration on attempt 0'); | ||
| 167 | + assert.strictEqual(raw[1][passKey].duration_ms, raw[0][passKey].duration_ms); | ||
| 168 | + }); | ||
| 169 | + | ||
| 155 | 170 | test('using `run` api', async () => { | |
| 156 | 171 | let stream = run({ files: [fixture], rerunFailuresFilePath: stateFile }); | |
| 157 | 172 | stream.on('test:pass', common.mustCall(19)); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments