Skip to content

Commit 7567d5f

Browse files
committed
test(junit): add run-workers regression test for suite hook attribution
Adds an end-to-end regression test that spawns a real run-workers process against a dedicated fixture (BeforeSuite/AfterSuite both throwing) with junitReporter enabled, then parses the resulting report.xml to assert both failures land under the real suite name in a single <testsuite> element instead of two <testsuite name="Tests"> elements. Verified this test fails cleanly (not just a timeout) against the pre-fix junitReporter.js/hooks.js and passes against the fix. The new fixture lives in its own workers-junit-suite-hooks/ directory rather than the shared workers/ directory, since several other tests in this file glob workers/*.js against the base config and would otherwise pick up the new failing suite and see different pass/fail counts.
1 parent 7967530 commit 7567d5f

3 files changed

Lines changed: 62 additions & 0 deletions

File tree

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export const config = {
2+
tests: './workers-junit-suite-hooks/*.js',
3+
timeout: 10000,
4+
output: './output',
5+
helpers: {
6+
FileSystem: {},
7+
Workers: {
8+
require: './workers_helper',
9+
},
10+
},
11+
include: {},
12+
async bootstrap() {},
13+
mocha: {},
14+
plugins: {
15+
junitReporter: {
16+
enabled: true,
17+
},
18+
},
19+
name: 'sandbox',
20+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Feature('JunitWorkerSuiteHooks')
2+
3+
BeforeSuite(async () => {
4+
throw new Error('BeforeSuite worker failure')
5+
})
6+
7+
Scenario('should not be executed either', ({ I }) => {
8+
I.say('unreachable')
9+
})
10+
11+
AfterSuite(async () => {
12+
throw new Error('AfterSuite worker failure')
13+
})

test/runner/run_workers_test.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import fs from 'fs'
66
import semver from 'semver'
77
import { exec } from 'child_process'
88
import { fileURLToPath } from 'url'
9+
import xml2js from 'xml2js'
910
const __filename = fileURLToPath(import.meta.url)
1011
const __dirname = path.dirname(__filename)
1112

@@ -512,6 +513,34 @@ describe('CodeceptJS Workers Runner', function () {
512513
})
513514
})
514515

516+
it('should preserve suite identity for BeforeSuite/AfterSuite hook failures in the JUnit report', function (done) {
517+
if (!semver.satisfies(process.version, '>=11.7.0')) this.skip('not for node version')
518+
const reportFile = path.join(codecept_dir, 'output', 'report.xml')
519+
if (fs.existsSync(reportFile)) fs.rmSync(reportFile)
520+
521+
exec(`${codecept_run_glob('codecept.workers-junit.conf.js')} 1`, (err, stdout) => {
522+
;(async () => {
523+
expect(stdout).toContain('BeforeSuite worker failure')
524+
expect(stdout).toContain('AfterSuite worker failure')
525+
expect(err.code).toEqual(1)
526+
527+
expect(fs.existsSync(reportFile)).toEqual(true)
528+
const parsed = await new xml2js.Parser().parseStringPromise(fs.readFileSync(reportFile, 'utf8'))
529+
530+
// Both hook failures must land under the real suite name, grouped into a
531+
// single <testsuite>, not split across two <testsuite name="Tests"> elements.
532+
expect(parsed.testsuites.testsuite).toHaveLength(1)
533+
const suiteEl = parsed.testsuites.testsuite[0]
534+
expect(suiteEl.$.name).toEqual('JunitWorkerSuiteHooks')
535+
expect(suiteEl.testcase).toHaveLength(2)
536+
537+
const names = suiteEl.testcase.map(tc => tc.$.name)
538+
expect(names.some(n => n.includes('BeforeSuite'))).toEqual(true)
539+
expect(names.some(n => n.includes('AfterSuite'))).toEqual(true)
540+
})().then(done, done)
541+
})
542+
})
543+
515544
it('should handle large worker count without inflating statistics', function (done) {
516545
if (!semver.satisfies(process.version, '>=11.7.0')) this.skip('not for node version')
517546
// Test with more workers than tests to ensure no inflation

0 commit comments

Comments
 (0)