commit 3bd1ed791f21b30d106fb279a7591915e1a6ec77
parent b4c9cec229cf75138d7cedd7c37db4872c077d7b
Author: Florian Quèze <florian@queze.net>
Date: Thu, 8 Jan 2026 16:52:42 +0000
Bug 2008920 - Make browser chrome mochitests log the task name as the subtest and log the assertion failure stacks in the stack field of structured messages, r=ahal.
Differential Revision: https://phabricator.services.mozilla.com/D278108
Diffstat:
2 files changed, 40 insertions(+), 13 deletions(-)
diff --git a/testing/mochitest/browser-harness.xhtml b/testing/mochitest/browser-harness.xhtml
@@ -146,11 +146,21 @@
return;
}
+ // Use task name as subtest if available
+ let subtest = this.scope?.SimpleTest?._currentTaskName || null;
+
+ // Combine assertion name with exception details if present
+ let message = result.name;
+ if (result.msg) {
+ message += " - " + result.msg;
+ }
+
this.dumper.structuredLogger.testStatus(this.path,
- result.name,
+ subtest,
result.status,
result.expected,
- result.msg);
+ message,
+ result.stack || null);
let markerName = "TEST-";
if (result.pass) {
markerName += result.todo ? "KNOWN-FAIL" : "PASS";
@@ -158,11 +168,7 @@
else {
markerName += "UNEXPECTED-" + result.status;
}
- let markerText = result.name;
- if (result.msg) {
- markerText += " - " + result.msg;
- }
- ChromeUtils.addProfilerMarker(markerName, {category: "Test"}, markerText);
+ ChromeUtils.addProfilerMarker(markerName, {category: "Test"}, message);
},
setDuration: function setDuration(duration) {
diff --git a/testing/mochitest/browser-test.js b/testing/mochitest/browser-test.js
@@ -1284,6 +1284,8 @@ Tester.prototype = {
let desc = isSetup ? "setup" : "test";
currentScope.SimpleTest.info(`Entering ${desc} ${task.name}`);
let startTimestamp = ChromeUtils.now();
+ currentScope.SimpleTest._currentTaskName = task.name;
+
let controller = new AbortController();
currentScope.__signal = controller.signal;
if (isSetup) {
@@ -1312,7 +1314,7 @@ Tester.prototype = {
}
currentTest.addResult(
new testResult({
- name: `Uncaught exception in ${desc} ${task.name}`,
+ name: `Uncaught exception in ${desc}`,
pass: currentScope.SimpleTest.isExpectingUncaughtException(),
ex,
stack: typeof ex == "object" && "stack" in ex ? ex.stack : null,
@@ -1328,9 +1330,10 @@ Tester.prototype = {
ChromeUtils.addProfilerMarker(
isSetup ? "setup-task" : "task",
{ category: "Test", startTime: startTimestamp },
- task.name.replace(/^bound /, "") || undefined
+ task.name || undefined
);
currentScope.SimpleTest.info(`Leaving ${desc} ${task.name}`);
+ currentScope.SimpleTest._currentTaskName = null;
},
async _runTaskBasedTest(currentTest) {
@@ -1704,8 +1707,23 @@ function testResult({ name, pass, todo, ex, stack, allowFailure }) {
if (ex) {
if (typeof ex == "object" && "fileName" in ex) {
- // we have an exception - print filename and linenumber information
- this.msg += "at " + ex.fileName + ":" + ex.lineNumber + " - ";
+ // Only add "at fileName:lineNumber" if stack doesn't start with same location
+ let stackMatchesExLocation = false;
+
+ if (stack instanceof Ci.nsIStackFrame) {
+ stackMatchesExLocation =
+ stack.filename == ex.fileName && stack.lineNumber == ex.lineNumber;
+ } else if (typeof stack === "string") {
+ // For string stacks, format is: functionName@fileName:lineNumber:columnNumber
+ // Check if first line contains fileName:lineNumber
+ let firstLine = stack.split("\n")[0];
+ let expectedLocation = ex.fileName + ":" + ex.lineNumber;
+ stackMatchesExLocation = firstLine.includes(expectedLocation);
+ }
+
+ if (!stackMatchesExLocation) {
+ this.msg += "at " + ex.fileName + ":" + ex.lineNumber + " - ";
+ }
}
if (
@@ -1722,8 +1740,8 @@ function testResult({ name, pass, todo, ex, stack, allowFailure }) {
}
}
+ // Store stack separately instead of appending to msg
if (stack) {
- this.msg += "\nStack trace:\n";
let normalized;
if (stack instanceof Ci.nsIStackFrame) {
let frames = [];
@@ -1739,7 +1757,7 @@ function testResult({ name, pass, todo, ex, stack, allowFailure }) {
} else {
normalized = "" + stack;
}
- this.msg += normalized;
+ this.stack = normalized;
}
if (gConfig.debugOnFailure) {
@@ -1997,7 +2015,10 @@ function testScope(aTester, aTest, expected) {
}
function decorateTaskFn(fn) {
+ let originalName = fn.name;
fn = fn.bind(this);
+ // Restore original name to avoid "bound " prefix in task name
+ Object.defineProperty(fn, "name", { value: originalName });
fn.skip = (val = true) => (fn.__skipMe = val);
fn.only = () => (this.__runOnlyThisTask = fn);
return fn;