Repository navigation
Mochawesome/Testomatio/junit reporter: run-workers: Running of test with --suite doesn't aggregate results from all suites per browser #5411
Copy link
Copy link
Open
Description
The issue is even in older versions, e.g. in 3.5.3. Retested with the latest 3.7.6 and the issue persists.
npm i mochawesomenpm i mocha-junit-reporternpm i mocha-multi- Run the tests
codeceptjs run-workers 3 dev --by suite --reporter mocha-multi(parallelization per browser and per suite). Another variant is--suitesinstead of--by suite, but it behaves the same way.
$ codeceptjs run-workers 3 dev --by suite --reporter mocha-multi
CodeceptJS v3.7.6 #StandWithUkraine
Running tests in 3 workers...
[Worker 03] ✔ SuiteB › Scenario 1 in 4ms
[Worker 03] ✔ SuiteB › Scenario 2 in 1ms
[Worker 01] ✔ SuiteA › Scenario 1 in 5ms
[Worker 01] ✔ SuiteA › Scenario 2 in 1ms
[Worker 02] ✔ SuiteA › Scenario 1 in 3ms
[Worker 02] ✔ SuiteA › Scenario 2 in 1ms
[Worker 04] ✔ SuiteB › Scenario 1 in 4ms
[Worker 04] ✔ SuiteB › Scenario 2 in 1ms
OK | 8 passed // 3s
Expected result:
output/console.logcontains data from both test suitesoutput/dev_chromium1/report.htmlcontains data from both test suitesoutput/dev_chromium1/report.jsoncontains data from both test suitesoutput/dev_chromium1/result.xmlcontains data from both test suitesoutput/dev_firefox1/report.htmlcontains data from both test suitesoutput/dev_firefox1/report.jsoncontains data from both test suitesoutput/dev_firefox1/result.xmlcontains data from both test suites
This way it works with run-multiple (parallelization per browser, but test suites are run in sequence) ✔️
Actual result:
- All the mentioned files contains data from the SuiteA only. The SuiteB is missing there 🐞 . A problem seems to be that test suites overwrite each other's results when running in threads.
Config codecept.conf.ts:
import { setHeadlessWhen, setCommonPlugins } from "@codeceptjs/configure";
// turn on headless mode when running with HEADLESS=true environment variable
// export HEADLESS=true && npx codeceptjs run
setHeadlessWhen(process.env.HEADLESS);
// enable all common plugins https://github.com/codeceptjs/configure#setcommonplugins
setCommonPlugins();
export const config: CodeceptJS.MainConfig = {
tests: "./*_test.ts",
output: "./output",
helpers: {
Playwright: {
browser: "chromium",
url: "http://localhost",
show: true,
},
Mochawesome: {
uniqueScreenshotNames: true,
},
},
include: {
I: "./steps_file",
},
multiple: {
dev: {
browsers: [
{
browser: "chromium",
outputName: "chromium",
},
{
browser: "firefox",
outputName: "firefox",
},
],
},
},
mocha: {
reporterOptions: {
"codeceptjs-cli-reporter": {
stdout: "-",
options: {
verbose: true,
debug: true,
steps: true,
},
},
mochawesome: {
stdout: "./output/console.log",
options: {
reportDir: "./output",
reportFilename: "report",
},
},
"mocha-junit-reporter": {
stdout: "./output/console.log",
options: {
mochaFile: "./output/result.xml",
jenkinsMode: true,
attachments: true, //add screenshot for a failed test
},
},
},
},
name: "my",
};Test suites:
SuiteA_test.ts
Feature("SuiteA");
Scenario("Scenario 1", ({ I }) => {
I.say("Executing Scenario 1 in Suite A");
});
Scenario("Scenario 2", ({ I }) => {
I.say("Executing Scenario 2 in Suite A");
});SuiteB_test.ts
Feature("SuiteB");
Scenario("Scenario 1", ({ I }) => {
I.say("Executing Scenario 1 in Suite B");
});
Scenario("Scenario 2", ({ I }) => {
I.say("Executing Scenario 2 in Suite B");
});Used SW:
- CodeceptJS 3.7.6
- mochawesome 7.1.4
- mocha-junit-reporter 2.2.1
- mocha-multi 1.1.7
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
fix: aggregate custom reporter results in run-workers --by suite (cod…
github-actions commentedon Apr 27, 2026
This issue is stale because it has been open for 90 days with no activity.
mirao commentedon May 24, 2026
Mochawesome is deprecated in 4.x and JUnit XML was rewritten into a plugin:
https://codecept.io/reports#custom-reporter:

So I retested it with the Testomatio reporter and the new JUnit XML plugin.
The JUnit XML works well, I'm getting extra XML for Chromium and Webkit and they don't overwrite themselves 👍 .
But the issue with overwritten HTML persists 👎 : Only one report is created and it contains data from the worker that wrote there last time.
The report contains data from WebKit only (the data for Chromium were overwritten) 🐞 .

CC: @DavertMik
[-]Mochawesome/junit reporter: run-workers: Running of test with --suite doesn't aggregate results from all suites per browser[/-][+]Mochawesome/Testomatio/junit reporter: run-workers: Running of test with --suite doesn't aggregate results from all suites per browser[/+]mirao commentedon May 24, 2026
🤖 AI Analysis
Why the HTML report shows only one browser's results
When running
run-workers N dev --by suitewith multiple browsers configured (e.g.browsers: ['chromium', 'webkit']), CodeceptJS creates one worker per browser per suite. Each browser run executes the same tests, so their test UIDs are identical (UID = SHA-256 hash oftest.fullTitle()).The Testomatio reporter's
aggregateTestRetries()inhtml.jsgroups test results byrid(= UID):Since Chromium and WebKit runs of the same test produce identical UIDs, they end up in the same group. Only one browser's result survives (the last writer wins).
Part 1 — What needs to change in CodeceptJS
File:
lib/workers.jsWhen building workers for multiple browser runs (
selectedRuns), store each run's name (e.g.dev:chromium1,dev:webkit1) on theWorkerObject. Then, when dispatchingevent.test.afterback to the main process, append the run name to the test UID before passing it to the event dispatcher:Effect: Tests from different browser runs have distinct UIDs (e.g.
abc123_dev_chromium1vsabc123_dev_webkit1), soaggregateTestRetries()no longer merges them. The HTML report shows all results per browser (e.g. 4 tests × 2 browsers = 8 entries) instead of 4. This approach was tested and verified by the issue reporter.Part 2 — What needs to change in Testomatio reporter
Each test would carry
meta.env = 'dev:chromium1'(or'dev:webkit1'). The data would be there, but the HTML template doesn't expose it as a filter.What would be needed in
@testomatio/reporter:meta.env(or a dedicatedbrowserfield) on each test resultThis is a pure UI/template change inside the HTML pipe — the data plumbing from CodeceptJS to the reporter would be handled by the Part 1 fix above.
mirao commentedon Oct 21, 2026
Retest with 4.2.1 and @testomatio/reporter 2.18.0, plus a working fix
I retested this with CodeceptJS 4.2.1,
@testomatio/reporter2.18.0 and the built-injunitReporterplugin, then fixed it locally. Both are verified on a real project: 3 suites × 2 browsers (Chromium + WebKit) × 2 workers.Current state
run-workers 2 --by suite(one browser)output/report.xmlwith all testsrun-workers 2 dev --by suite(two browsers)output/dev_chromium1/report.xmlkeeps only the last worker's suites; the main process'soutput/report.xmlhas one browser onlyThe single-browser case works: the main process writes the merged report after all workers finish. Workers also write their own partial
report.xmlto the same path, but the main process writes last.Why the earlier AI analysis is not enough
The earlier comment correctly identified the cause: the same test has the same
uidin every browser. Its fix has three gaps:event.test.after. In the main process,uidis also the key inResult.addTest()(fed by the workers'event.all.result), in_testStates(event.test.finished, used for the final passed/failed events) and in skipped tests. The JUnit plugin builds its XML fromResult.tests, so it still drops one browser.report.xmlinto its run's folder, and two Chromium workers shareoutput/dev_chromium1/. This is the original bug of this issue, and the earlier fix doesn't touch it.run-multipleproduces and existing CI jobs expect, the reporter needs only a small change that writes one file per run folder. It doesn't need a UI change.Proposed fix
The result should be the same layout as
run-multiple: one XML and one HTML per browser, each containing every suite from all of that browser's workers.CodeceptJS
lib/workers.js: in the main process, tag every incoming message from a multi-run worker at the single entry point, instead of tagging individual events:Every uid-keyed structure in the main process then keeps the browsers apart without further changes. Each deserialized test also carries
outputDir, so reporters know which run it belongs to. Single-browserrun-workersand plainrunare not affected, becauserunOutputDiris set only in the multi-run branch.CodeceptJS
lib/plugin/junitReporter.js: workers no longer write partial files, and the main process writes one file per run:With only these two CodeceptJS changes, the Testomatio HTML is already correct. It is one combined
output/report/testomatio-report.htmlwith all results from both browsers (16 entries in the repro below), and each entry shows its browser in the metadata. No Testomatio UI change is needed.@testomatio/reporter(optional, a separate PR there; only needed for one HTML per browser, likerun-multiple):lib/adapter/codecept.js: passoutputDir: test.outputDir(hook.outputDirfor hook failures) in everyclient.addTestRun()call.lib/client.js: takeoutputDirfromtestDataand put it into thedataobject sent to the pipes.lib/pipe/html.js,finishRun(): if tests carryoutputDir, build one report per run into<outputDir>/report/<reportName>; otherwise keep the current behaviour.Side note:
isSameTest()in the reporter'sutils.jscomparesObject.values(a.example) === Object.values(b.example), i.e. two new arrays by reference. It is therefore alwaysfalse, soHtmlPipe.addTest()never merges entries.Verification
Real project,
run-workers 2 personal --by suite --grep "^(ChangePassword|AddUserRole|AddTenant) @"withbrowsers: [chromium, webkit], 4 workers in parallel:personal_chromium1/report.xmlpersonal_webkit1/report.xmlpersonal_chromium1/report/testomatio-report.htmlpersonal_webkit1/report/testomatio-report.htmlA minimal repro (4 suites, one failing scenario) gives 8 tests / 1 failure in each browser's XML and HTML. Without the optional reporter change, the repro gives one combined HTML with all 16 entries. Single-browser
run-workers 2 --by suiteand plainrunproduce the same singleoutput/report.xmland HTML as before.I deliberately didn't change two behaviours, because existing
run-workersusers may depend on them:dev_chromium1) differ fromrun-multiple's (dev_chromium_1,dev_webkit_2).[Worker NN]without the browser name.A non-breaking improvement would be to add the run label to the "Test distribution" header, e.g.
Worker 1: 8 tests (dev:chromium1).Created by AI agent (Claude Code)