清理量角器堆栈跟踪
Cleaning up Protractor stack trace
问题:
是否可以清理堆栈跟踪并仅保留相关帧以消除所有 Protractor
、WebDriverJS
和 Jasmine
特定内容?
故事:
让我们执行这个示例测试:
describe("SO test", function () {
beforeEach(function () {
browser.get("https://angularjs.org");
});
it("should throw a meaningful error", function () {
element(by.id("not_found")).click();
});
});
它将失败并显示以下堆栈跟踪:
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)
如您所见,要找出错误实际发生在测试中的哪一行并不容易。它隐藏在由 Protractor
、WebDriverJS
和 Jasmine
堆栈帧覆盖的堆栈跟踪中的某处。这使得调试和开发端到端测试变得困难。
期望输出:
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)
使用 protractor
3.0.0 和 jasmine2
。
在 mocha
世界中,有一个相关的 mocha-clean
包可以过滤掉来自内部 node_modules
和 mocha
本身的所有内容,留下一个干净的堆栈跟踪,这很容易阅读。
事实证明,如果您使用任何自定义报告器,它们可能会引入新的行为来控制堆栈跟踪的输出。 Protractor 本身几乎隐藏了所有内容,因此您不会看到来自 node_modules 或 Jasmine 的任何日志条目。
当您出于某种原因使用 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 时,建议使用 all
模式,它基本上显示整个堆栈跟踪。
onPrepare: function () {
jasmine.getEnv().addReporter(new SpecReporter({
spec: {
displayStacktrace: true
}
}));
如果您只是将选项 displayStacktrace
从 all
更改为 none
,您应该会得到干净的结果,没有任何堆栈跟踪。还有选项 summary
和 specs
。在您的示例中您可能没有注意到它们之间的区别,但是如果您在套件中添加更多规范,那么您将能够看到区别:
specs
- 如果规范在 运行 测试过程中失败,您将在规范失败消息后立即看到它的堆栈跟踪
summary
- 如果规范在 运行 测试过程中失败,您将 不会 在规范失败后立即看到它的堆栈跟踪消息,但您将在所有测试结束时获得失败规范的所有堆栈跟踪列表
all
- 组合 specs
和 summary
- 如果规范在 运行 测试过程中失败,您将在规范失败消息和您将在所有测试结束时获得失败规范的所有堆栈跟踪列表
none
- 堆栈跟踪不会显示在任何地方
jasmine-spec-reporter
的 API 已更改。
new example 说明了关闭堆栈跟踪的简单选项:
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
}
})
);
}
}
对于那些正在寻找一种稳定且方便的方法来过滤 Protractor 堆栈跟踪的人来说,还有一个选择 - protractor-beautiful-reporter
这将生成一个非常有用的 HTML 报告,该报告也可以过滤掉堆栈跟踪仅关注相关部分("smart stack trace" 功能)。
您可以通过传递参数 --logging 来设置 webdriver 日志记录级别。
例如,在 package.json 中使其看起来像这样
"start": "node node_modules/protractor/bin/webdriver-manager start --logging=logging.conf"
创建文件 logging.conf 并将其放在项目的根文件夹中
并在此文件中放入
level=WARNING
问题:
是否可以清理堆栈跟踪并仅保留相关帧以消除所有 Protractor
、WebDriverJS
和 Jasmine
特定内容?
故事:
让我们执行这个示例测试:
describe("SO test", function () {
beforeEach(function () {
browser.get("https://angularjs.org");
});
it("should throw a meaningful error", function () {
element(by.id("not_found")).click();
});
});
它将失败并显示以下堆栈跟踪:
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)
如您所见,要找出错误实际发生在测试中的哪一行并不容易。它隐藏在由 Protractor
、WebDriverJS
和 Jasmine
堆栈帧覆盖的堆栈跟踪中的某处。这使得调试和开发端到端测试变得困难。
期望输出:
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)
使用 protractor
3.0.0 和 jasmine2
。
在 mocha
世界中,有一个相关的 mocha-clean
包可以过滤掉来自内部 node_modules
和 mocha
本身的所有内容,留下一个干净的堆栈跟踪,这很容易阅读。
事实证明,如果您使用任何自定义报告器,它们可能会引入新的行为来控制堆栈跟踪的输出。 Protractor 本身几乎隐藏了所有内容,因此您不会看到来自 node_modules 或 Jasmine 的任何日志条目。
当您出于某种原因使用 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 时,建议使用 all
模式,它基本上显示整个堆栈跟踪。
onPrepare: function () {
jasmine.getEnv().addReporter(new SpecReporter({
spec: {
displayStacktrace: true
}
}));
如果您只是将选项 displayStacktrace
从 all
更改为 none
,您应该会得到干净的结果,没有任何堆栈跟踪。还有选项 summary
和 specs
。在您的示例中您可能没有注意到它们之间的区别,但是如果您在套件中添加更多规范,那么您将能够看到区别:
specs
- 如果规范在 运行 测试过程中失败,您将在规范失败消息后立即看到它的堆栈跟踪summary
- 如果规范在 运行 测试过程中失败,您将 不会 在规范失败后立即看到它的堆栈跟踪消息,但您将在所有测试结束时获得失败规范的所有堆栈跟踪列表all
- 组合specs
和summary
- 如果规范在 运行 测试过程中失败,您将在规范失败消息和您将在所有测试结束时获得失败规范的所有堆栈跟踪列表none
- 堆栈跟踪不会显示在任何地方
jasmine-spec-reporter
的 API 已更改。
new example 说明了关闭堆栈跟踪的简单选项:
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
}
})
);
}
}
对于那些正在寻找一种稳定且方便的方法来过滤 Protractor 堆栈跟踪的人来说,还有一个选择 - protractor-beautiful-reporter
这将生成一个非常有用的 HTML 报告,该报告也可以过滤掉堆栈跟踪仅关注相关部分("smart stack trace" 功能)。
您可以通过传递参数 --logging 来设置 webdriver 日志记录级别。 例如,在 package.json 中使其看起来像这样
"start": "node node_modules/protractor/bin/webdriver-manager start --logging=logging.conf"
创建文件 logging.conf 并将其放在项目的根文件夹中
并在此文件中放入
level=WARNING