Karma - Chrome Headless - 测试失败 - 抛出未捕获的 null
Karma - Chrome Headless - test FAILED - Uncaught null thrown
虽然 运行 单元测试,它们“有时”会失败,总是在不同的测试中,没有任何有意义的错误。
...
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)上那样频繁发生
- 在 docker 环境中 运行 发生 3 次
- 我们拥有的单元测试越多,它发生的次数就越多
- 我们也经历过 chrome 的超时(一些测试不会在 60 秒内响应:
Chrome Headless 93.0.4577.82 (Linux x86_64) ERROR 14:06:45 #19 695.4 Disconnected , because no message in 60000 ms
)但它有时也会发生......重新启动测试会使它消失大部分时间。
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 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
我们没有太多,但它可能会帮助别人看看它可能是什么。
对于可能偶然发现此问题的任何人:我能够使用 chrome 的“异常停止”功能捕获错误。在其中我们仍然只看到抛出了一个“null”(并且没有任何 stacttrace),但我们也看到错误发生在 zone.js 任务对象中,它提供了有关导致错误的原因的足够信息。
是我们。抱歉,添麻烦了。我们在其中一个测试中抛出了一个空对象,但没有捕获到它。这是一个非常糟糕的做法。
if (typeof res === 'boolean') {
return of(res);
} else {
return throwError(res); // res can be null...
}
所以最重要的是,要怀疑为什么堆栈跟踪是准确的null
...
虽然 运行 单元测试,它们“有时”会失败,总是在不同的测试中,没有任何有意义的错误。
...
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)上那样频繁发生
- 在 docker 环境中 运行 发生 3 次
- 我们拥有的单元测试越多,它发生的次数就越多
- 我们也经历过 chrome 的超时(一些测试不会在 60 秒内响应:
Chrome Headless 93.0.4577.82 (Linux x86_64) ERROR 14:06:45 #19 695.4 Disconnected , because no message in 60000 ms
)但它有时也会发生......重新启动测试会使它消失大部分时间。
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 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
我们没有太多,但它可能会帮助别人看看它可能是什么。
对于可能偶然发现此问题的任何人:我能够使用 chrome 的“异常停止”功能捕获错误。在其中我们仍然只看到抛出了一个“null”(并且没有任何 stacttrace),但我们也看到错误发生在 zone.js 任务对象中,它提供了有关导致错误的原因的足够信息。
是我们。抱歉,添麻烦了。我们在其中一个测试中抛出了一个空对象,但没有捕获到它。这是一个非常糟糕的做法。
if (typeof res === 'boolean') {
return of(res);
} else {
return throwError(res); // res can be null...
}
所以最重要的是,要怀疑为什么堆栈跟踪是准确的null
...