The Question:
Is it possible to clean up the stack trace and leave only relevant frames eliminating everything Protractor
, WebDriverJS
and Jasmine
specific?
The Story:
Let's execute this example test:
describe("SO test", function () {
beforeEach(function () {
browser.get("https://angularjs.org");
});
it("should throw a meaningful error", function () {
element(by.id("not_found")).click();
});
});
It would fail with a following stacktrace:
SO test should throw a meaningful error
- Failed: No element found using locator: By.id("not_found")
at new bot.Error (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/atoms/error.js:108:18)
at /usr/local/lib/node_modules/protractor/lib/element.js:676:15
at [object Object].promise.Promise.goog.defineClass.invokeCallback_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:1337:14)
at [object Object].promise.ControlFlow.goog.defineClass.goog.defineClass.abort_.error.executeNext_.execute_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:2776:14)
at [object Object].promise.ControlFlow.goog.defineClass.goog.defineClass.abort_.error.executeNext_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:2758:21)
at goog.async.run.processWorkQueue (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/async/run.js:124:15)
at process._tickCallback (node.js:377:9)
Error
at [object Object].ElementArrayFinder.applyAction_ (/usr/local/lib/node_modules/protractor/lib/element.js:382:21)
at [object Object].ElementArrayFinder.(anonymous function) [as click] (/usr/local/lib/node_modules/protractor/lib/element.js:78:17)
at [object Object].ElementFinder.(anonymous function) [as click] (/usr/local/lib/node_modules/protractor/lib/element.js:711:7)
at Object.<anonymous> (/Users/user/job/project/test/e2e/specs/test.spec.js:9:37)
at /usr/local/lib/node_modules/protractor/node_modules/jasminewd2/index.js:96:23
at [object Object].promise.Promise.goog.defineClass.constructor (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:1056:7)
at new wrappedCtr (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/base.js:2468:26)
at controlFlowExecute (/usr/local/lib/node_modules/protractor/node_modules/jasminewd2/index.js:82:18)
at [object Object].promise.ControlFlow.goog.defineClass.goog.defineClass.abort_.error.executeNext_.execute_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:2776:14)
at [object Object].promise.ControlFlow.goog.defineClass.goog.defineClass.abort_.error.executeNext_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:2758:21)
From: Task: Run it("should throw a meaningful error") in control flow
at Object.<anonymous> (/usr/local/lib/node_modules/protractor/node_modules/jasminewd2/index.js:81:14)
at /usr/local/lib/node_modules/protractor/node_modules/jasminewd2/index.js:18:5
at [object Object].promise.Promise.goog.defineClass.invokeCallback_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:1337:14)
at [object Object].promise.ControlFlow.goog.defineClass.goog.defineClass.abort_.error.executeNext_.execute_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:2776:14)
at [object Object].promise.ControlFlow.goog.defineClass.goog.defineClass.abort_.error.executeNext_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:2758:21)
at goog.async.run.processWorkQueue (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/async/run.js:124:15)
From asynchronous test:
Error
at Suite.<anonymous> (/Users/user/job/project/test/e2e/specs/test.spec.js:8:5)
at Object.<anonymous> (/Users/user/job/project/test/e2e/specs/test.spec.js:3:1)
at Module._compile (module.js:425:26)
at Object.Module._extensions..js (module.js:432:10)
at Module.load (module.js:356:32)
As you can see, it's not easy to find on which line in the test the error actually happened. It's hidden somewhere inside the stack trace covered by Protractor
, WebDriverJS
and Jasmine
stack frames. This makes it difficult to debug and develop end-to-end tests.
Desired output:
SO test should throw a meaningful error
- Failed: No element found using locator: By.id("not_found")
at Object.<anonymous> (/Users/user/job/project/test/e2e/specs/test.spec.js:9:37)
From asynchronous test:
Error
at Suite.<anonymous> (/Users/user/job/project/test/e2e/specs/test.spec.js:8:5)
at Object.<anonymous> (/Users/user/job/project/test/e2e/specs/test.spec.js:3:1)
at Module._compile (module.js:425:26)
at Object.Module._extensions..js (module.js:432:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:311:12)
Using protractor
3.0.0 and jasmine2
.
In mocha
world, there is a relevant mocha-clean
package that filters out everything coming from inside node_modules
and mocha
itself leaving a clean stack trace that is easy to read.
As it turns out, if you use any custom reporters, they may introduce new behavior in controlling output of a stack trace. Protractor itself hides pretty much everything, so you won't see any log entries from node_modules or Jasmine.
As you use jasmine-spec-reporter, which provides an option to control a stack trace, it might be the case, that you have set some verbose mode in the options. In the docs for Protractor for some reason it is suggested to use all
mode, which basically displays the enitre stack trace.
onPrepare: function () {
jasmine.getEnv().addReporter(new SpecReporter({
spec: {
displayStacktrace: true
}
}));
If you simply change the option displayStacktrace
from all
to none
, you should get clean results without any stack traces. There are also options summary
and specs
. You might not notice the difference between them in your example, but if you add a few more specs in your suite, then you'll be able to see the difference:
specs
- if spec fails in the process of running tests, you'll see a stack trace for it immediately after a spec failure messagesummary
- if spec fails in the process of running tests, you'll not see a stack trace for it immediately after a spec failure message, but you'll get a list of all stack traces for failed specs in the end of all testsall
- combines specs
and summary
- if spec fails in the process of running tests, you'll see a stack trace for it immediately after a spec failure message and you'll get a list of all stack traces for failed specs in the end of all testsnone
- stack traces won't be shown anywherejasmine-spec-reporter
's API has changed.
The new example illustrates a simple option to turn off stack traces:
let SpecReporter = require('jasmine-spec-reporter').SpecReporter;
exports.config = {
framework: 'jasmine',
// Your config here...
jasmineNodeOpts: {
print: function () {}
},
onPrepare: function () {
jasmine.getEnv().addReporter(
new SpecReporter({
spec: {
displayStacktrace: true
}
})
);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With