Karma - Chrome Headless - 测试失败 - 抛出未捕获的空值
在运行单元测试时,它们“有时”会失败,总是在不同的测试中失败,没有任何有意义的错误。
...
Chrome 89.0.4389.114 (Linux x86_64): Executed 1225 of 1453 SUCCESS (0 secs / 3 mins 29.829 secs)
Chrome 89.0.4389.114 (Linux x86_64): Executed 1226 of 1453 SUCCESS (0 secs / 3 mins 30.893 secs)
Chrome 89.0.4389.114 (Linux x86_64): Executed 1227 of 1453 SUCCESS (0 secs / 3 mins 31.923 secs)
Chrome 89.0.4389.114 (Linux x86_64) ChooseOfWorkplaceComponent should show institutie warning info FAILED
Uncaught null thrown
Chrome 89.0.4389.114 (Linux x86_64): Executed 1228 of 1453 (1 FAILED) (0 secs / 3 mins 32.237 secs)
✗ should show institutie warning info
Uncaught null thrown
Chrome 89.0.4389.114 (Linux x86_64): Executed 1229 of 1453 (1 FAILED) (0 secs / 3 mins 32.713 secs)
Chrome 89.0.4389.114 (Linux x86_64): Executed 1230 of 1453 (1 FAILED) (0 secs / 3 mins 33.432 secs)
Chrome 89.0.4389.114 (Linux x86_64): Executed 1231 of 1453 (1 FAILED) (0 secs / 3 mins 33.461 secs)
- 我们使用 ng test --watch=false --browsers=ChromeHeadlessCI 运行测试
- 我们以相同的顺序运行测试(没有随机顺序,正如您从下面的配置中看到的),但错误发生在不同的地方总是有相同的错误消息
- 在更强的配置(16gb 内存,第 8 代 i7)上,它不会像旧配置(12gb 内存,第 7 代 i5)那样频繁地发生
- 它会发生 2 次3 在 docker 环境中运行
- 单元测试越多,这种情况发生的次数就越多。
- 我们还遇到了 chrome 超时的情况(某些测试在 60 秒内不会响应:
Chrome Headless 93.0.4577.82 (Linux x86_64) ERROR 14:06: 45 #19 695.4 已断开连接,因为 60000 毫秒内没有消息
),但有时也会发生...重新启动测试使其在大多数情况下消失。
Karma.conf.js:
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage'),
require('karma-spec-reporter'),
require('@angular-devkit/build-angular/plugins/karma'),
],
client: {
clearContext: false, // leave FJasmine Spec Runner output visible in browser
jasmine: {
random: false,
},
},
jasmineHtmlReporter: {
suppressAll: true, // removes the duplicated traces
},
coverageReporter: {
dir: require('path').join(__dirname, '...'),
subdir: '.',
reporters: [{ type: 'html' }, { type: 'text-summary' }],
check: {
global: {
statements: 50,
branches: 50,
functions: 50,
lines: 50,
},
},
},
captureTimeout: 180000,
browserNoActivityTimeout: 60000,
browserDisconnectTimeout: 10000,
browserDisconnectTolerance: 3,
reporters: ['progress', 'kjhtml', 'spec'],
port: 9876,
colors: true,
logLevel: config.DEBUG,
autoWatch: true,
browsers: ['Chrome', 'ChromeHeadless'],
singleRun: false,
restartOnFileChange: true,
customLaunchers: {
ChromeHeadlessCI: {
base: 'ChromeHeadless',
flags: ['--no-sandbox'],
},
},
});
};
Angular 版本:
$ ng --version
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI: 13.2.2
Node: 14.17.1
Package Manager: npm 6.14.13
OS: linux x64
Angular: 13.2.1
... animations, cdk, common, compiler, compiler-cli, core, forms
... localize, material, material-moment-adapter
... platform-browser, platform-browser-dynamic, router
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1302.2
@angular-devkit/build-angular 13.2.2
@angular-devkit/core 13.2.2
@angular-devkit/schematics 13.2.2
@angular/cli 13.2.2
@angular/flex-layout 12.0.0-beta.35
@schematics/angular 13.2.2
rxjs 7.4.0
typescript 4.5.5
另一个错误日志,用于说明错误如何随机出现,并且没有其他数据:
...
15:42:21 #19 381.2 [1A[2KChrome Headless 93.0.4577.82 (Linux x86_64): Executed 1253 of 1453 SUCCESS (0 secs / 3 mins 29.334 secs)
15:42:21 #19 381.2 [32m✓ [39mshould "toIdentificationMode" anim status
15:42:21 #19 381.3 [1A[2KChrome Headless 93.0.4577.82 (Linux x86_64) ERROR
15:42:21 #19 381.3 An error was thrown in afterAll
15:42:21 #19 381.3 Uncaught null thrown
15:42:21 #19 381.3 Chrome Headless 93.0.4577.82 (Linux x86_64): Executed 1253 of 1453 ERROR (0 secs / 3 mins 29.334 secs)
15:42:21 #19 381.3 Chrome Headless 93.0.4577.82 (Linux x86_64) ERROR
15:42:21 #19 381.3 An error was thrown in afterAll
15:42:21 #19 381.3 Uncaught null thrown
15:42:21 #19 381.3 [31mChrome Headless 93.0.4577.82 (Linux x86_64) ERROR[39m
15:42:21 #19 381.3 An error was thrown in afterAll
15:42:21 #19 381.3 Uncaught null thrown
15:42:21 #19 381.3 [1A[2KChrome Headless 93.0.4577.82 (Linux x86_64): Executed 1253 of 1453 ERROR (4 mins 27.037 secs / 3 mins 29.334 secs)
更新: 我能够在 Chrome 窗口中捕获该错误。
zone.js:182 Uncaught null
runTask @ zone.js:182
invokeTask @ zone.js:487
ZoneTask.invoke @ zone.js:476
data.args.<computed> @ zone.js:2541
setTimeout (async)
scheduleTask @ zone.js:2543
scheduleTask @ zone.js:393
onScheduleTask @ zone-testing.js:306
scheduleTask @ zone.js:386
scheduleTask @ zone.js:221
scheduleMacroTask @ zone.js:244
scheduleMacroTaskWithCurrentZone @ zone.js:679
(anonymous) @ zone.js:2585
proto.<computed> @ zone.js:975
setTimeout @ timeoutProvider.js:4
reportUnhandledError @ reportUnhandledError.js:4
(anonymous) @ Subscriber.js:117
_error @ Subscriber.js:64
error @ Subscriber.js:40
_error @ Subscriber.js:64
error @ Subscriber.js:40
init @ throwError.js:5
_trySubscribe @ Observable.js:37
(anonymous) @ Observable.js:31
errorContext @ errorContext.js:19
subscribe @ Observable.js:22
doInnerSub @ mergeInternals.js:19
outerNext @ mergeInternals.js:14
OperatorSubscriber._next @ OperatorSubscriber.js:9
next @ Subscriber.js:31
(anonymous) @ innerFrom.js:51
_trySubscribe @ Observable.js:37
(anonymous) @ Observable.js:31
errorContext @ errorContext.js:19
subscribe @ Observable.js:22
mergeInternals @ mergeInternals.js:50
(anonymous) @ mergeMap.js:13
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:26
errorContext @ errorContext.js:19
subscribe @ Observable.js:22
(anonymous) @ session-transfer.component.ts:263
(anonymous) @ Subscriber.js:110
_complete @ Subscriber.js:72
complete @ Subscriber.js:49
(anonymous) @ take.js:14
OperatorSubscriber._next @ OperatorSubscriber.js:9
next @ Subscriber.js:31
(anonymous) @ map.js:7
OperatorSubscriber._next @ OperatorSubscriber.js:9
next @ Subscriber.js:31
(anonymous) @ timer.js:23
_execute @ AsyncAction.js:53
execute @ AsyncAction.js:41
flush @ AsyncScheduler.js:18
timer @ zone.js:2561
invokeTask @ zone.js:406
onInvokeTask @ zone-testing.js:318
invokeTask @ zone.js:405
runTask @ zone.js:178
invokeTask @ zone.js:487
ZoneTask.invoke @ zone.js:476
data.args.<computed> @ zone.js:2541
Show 32 more frames
我们没有太多,但它可能会帮助人们了解它可能是什么。
While running unit tests, they fail "sometimes", always on different tests, without any meaningful error.
...
Chrome 89.0.4389.114 (Linux x86_64): Executed 1225 of 1453 SUCCESS (0 secs / 3 mins 29.829 secs)
Chrome 89.0.4389.114 (Linux x86_64): Executed 1226 of 1453 SUCCESS (0 secs / 3 mins 30.893 secs)
Chrome 89.0.4389.114 (Linux x86_64): Executed 1227 of 1453 SUCCESS (0 secs / 3 mins 31.923 secs)
Chrome 89.0.4389.114 (Linux x86_64) ChooseOfWorkplaceComponent should show institutie warning info FAILED
Uncaught null thrown
Chrome 89.0.4389.114 (Linux x86_64): Executed 1228 of 1453 (1 FAILED) (0 secs / 3 mins 32.237 secs)
✗ should show institutie warning info
Uncaught null thrown
Chrome 89.0.4389.114 (Linux x86_64): Executed 1229 of 1453 (1 FAILED) (0 secs / 3 mins 32.713 secs)
Chrome 89.0.4389.114 (Linux x86_64): Executed 1230 of 1453 (1 FAILED) (0 secs / 3 mins 33.432 secs)
Chrome 89.0.4389.114 (Linux x86_64): Executed 1231 of 1453 (1 FAILED) (0 secs / 3 mins 33.461 secs)
- We run the tests with
ng test --watch=false --browsers=ChromeHeadlessCI
- We run the tests with the same order (no random order as you can see from the config below) but the error happens on different places always with the same error message
- On stronger configurations (16gb ram, 8th gen i7) it won't happen as frequently as on an older config (12gb ram, 7th gen i5)
- It happens 2 times out of 3 run in a docker environment
- The more unit tests we have the more it happens
- We also experience timeouts from chrome (some tests won't respond for 60 seconds:
Chrome Headless 93.0.4577.82 (Linux x86_64) ERROR 14:06:45 #19 695.4 Disconnected , because no message in 60000 ms
) but it happens just sometimes as well... restarting the tests makes it dissappear most of the time.
Karma.conf.js:
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage'),
require('karma-spec-reporter'),
require('@angular-devkit/build-angular/plugins/karma'),
],
client: {
clearContext: false, // leave FJasmine Spec Runner output visible in browser
jasmine: {
random: false,
},
},
jasmineHtmlReporter: {
suppressAll: true, // removes the duplicated traces
},
coverageReporter: {
dir: require('path').join(__dirname, '...'),
subdir: '.',
reporters: [{ type: 'html' }, { type: 'text-summary' }],
check: {
global: {
statements: 50,
branches: 50,
functions: 50,
lines: 50,
},
},
},
captureTimeout: 180000,
browserNoActivityTimeout: 60000,
browserDisconnectTimeout: 10000,
browserDisconnectTolerance: 3,
reporters: ['progress', 'kjhtml', 'spec'],
port: 9876,
colors: true,
logLevel: config.DEBUG,
autoWatch: true,
browsers: ['Chrome', 'ChromeHeadless'],
singleRun: false,
restartOnFileChange: true,
customLaunchers: {
ChromeHeadlessCI: {
base: 'ChromeHeadless',
flags: ['--no-sandbox'],
},
},
});
};
Angular version:
$ ng --version
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI: 13.2.2
Node: 14.17.1
Package Manager: npm 6.14.13
OS: linux x64
Angular: 13.2.1
... animations, cdk, common, compiler, compiler-cli, core, forms
... localize, material, material-moment-adapter
... platform-browser, platform-browser-dynamic, router
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1302.2
@angular-devkit/build-angular 13.2.2
@angular-devkit/core 13.2.2
@angular-devkit/schematics 13.2.2
@angular/cli 13.2.2
@angular/flex-layout 12.0.0-beta.35
@schematics/angular 13.2.2
rxjs 7.4.0
typescript 4.5.5
An another error log, to illustrate how the error appears randomly, and with no additional data:
...
15:42:21 #19 381.2 [1A[2KChrome Headless 93.0.4577.82 (Linux x86_64): Executed 1253 of 1453 SUCCESS (0 secs / 3 mins 29.334 secs)
15:42:21 #19 381.2 [32m✓ [39mshould "toIdentificationMode" anim status
15:42:21 #19 381.3 [1A[2KChrome Headless 93.0.4577.82 (Linux x86_64) ERROR
15:42:21 #19 381.3 An error was thrown in afterAll
15:42:21 #19 381.3 Uncaught null thrown
15:42:21 #19 381.3 Chrome Headless 93.0.4577.82 (Linux x86_64): Executed 1253 of 1453 ERROR (0 secs / 3 mins 29.334 secs)
15:42:21 #19 381.3 Chrome Headless 93.0.4577.82 (Linux x86_64) ERROR
15:42:21 #19 381.3 An error was thrown in afterAll
15:42:21 #19 381.3 Uncaught null thrown
15:42:21 #19 381.3 [31mChrome Headless 93.0.4577.82 (Linux x86_64) ERROR[39m
15:42:21 #19 381.3 An error was thrown in afterAll
15:42:21 #19 381.3 Uncaught null thrown
15:42:21 #19 381.3 [1A[2KChrome Headless 93.0.4577.82 (Linux x86_64): Executed 1253 of 1453 ERROR (4 mins 27.037 secs / 3 mins 29.334 secs)
update:
I was able to catch the error in a Chrome window.
zone.js:182 Uncaught null
runTask @ zone.js:182
invokeTask @ zone.js:487
ZoneTask.invoke @ zone.js:476
data.args.<computed> @ zone.js:2541
setTimeout (async)
scheduleTask @ zone.js:2543
scheduleTask @ zone.js:393
onScheduleTask @ zone-testing.js:306
scheduleTask @ zone.js:386
scheduleTask @ zone.js:221
scheduleMacroTask @ zone.js:244
scheduleMacroTaskWithCurrentZone @ zone.js:679
(anonymous) @ zone.js:2585
proto.<computed> @ zone.js:975
setTimeout @ timeoutProvider.js:4
reportUnhandledError @ reportUnhandledError.js:4
(anonymous) @ Subscriber.js:117
_error @ Subscriber.js:64
error @ Subscriber.js:40
_error @ Subscriber.js:64
error @ Subscriber.js:40
init @ throwError.js:5
_trySubscribe @ Observable.js:37
(anonymous) @ Observable.js:31
errorContext @ errorContext.js:19
subscribe @ Observable.js:22
doInnerSub @ mergeInternals.js:19
outerNext @ mergeInternals.js:14
OperatorSubscriber._next @ OperatorSubscriber.js:9
next @ Subscriber.js:31
(anonymous) @ innerFrom.js:51
_trySubscribe @ Observable.js:37
(anonymous) @ Observable.js:31
errorContext @ errorContext.js:19
subscribe @ Observable.js:22
mergeInternals @ mergeInternals.js:50
(anonymous) @ mergeMap.js:13
(anonymous) @ lift.js:10
(anonymous) @ Observable.js:26
errorContext @ errorContext.js:19
subscribe @ Observable.js:22
(anonymous) @ session-transfer.component.ts:263
(anonymous) @ Subscriber.js:110
_complete @ Subscriber.js:72
complete @ Subscriber.js:49
(anonymous) @ take.js:14
OperatorSubscriber._next @ OperatorSubscriber.js:9
next @ Subscriber.js:31
(anonymous) @ map.js:7
OperatorSubscriber._next @ OperatorSubscriber.js:9
next @ Subscriber.js:31
(anonymous) @ timer.js:23
_execute @ AsyncAction.js:53
execute @ AsyncAction.js:41
flush @ AsyncScheduler.js:18
timer @ zone.js:2561
invokeTask @ zone.js:406
onInvokeTask @ zone-testing.js:318
invokeTask @ zone.js:405
runTask @ zone.js:178
invokeTask @ zone.js:487
ZoneTask.invoke @ zone.js:476
data.args.<computed> @ zone.js:2541
Show 32 more frames
We don't have much, but it might help somebody to see what it could be.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
对于任何可能偶然发现这一点的人:我能够使用 Chrome 的“异常停止”功能捕获该错误。在其中我们仍然只看到抛出了“null”(并且没有任何 stacttrace),但我们还看到错误发生在 zone.js 任务对象中,该对象提供了有关导致错误的原因的足够信息。
是我们。抱歉给您带来麻烦了。我们在其中一项测试中抛出了一个 null 对象,但没有捕获它。这是一个非常糟糕的做法。
所以底线是,怀疑为什么堆栈跟踪是 exaclty
null
...To anyone who might stumble upon this: I was able to catch the error with the "stop on exception" feature of chrome. In it we still only saw that a "null" was thrown (and no stacttrace whatsoever) but we also saw that the error happens in a zone.js task object, which provided enough information about what causes the error.
It was us. Sorry for the trouble. We threw a null object in one of the tests and did not catch it. That's a quite bad practice.
So the bottom line is, be suspicious about why the stacktrace is exaclty
null
...