Angular 15项目CI/CD中Jasmine测试Headless Chrome断连问题
我有一个Angular 15项目,使用Jasmine和Karma执行测试,依赖配置如下:
"devDependencies": { "@angular-devkit/build-angular": "^15.0.0", "@angular/cli": "~15.0.0", "@angular/compiler-cli": "^15.0.0", "@types/jasmine": "~4.0.0", "autoprefixer": "^10.4.13", "jasmine-core": "~4.3.0", "karma": "~6.4.0", "karma-chrome-launcher": "~3.1.0", "karma-coverage": "~2.2.0", "karma-jasmine": "~5.1.0", "karma-jasmine-html-reporter": "~2.0.0", "postcss": "^8.4.21", "tailwindcss": "^3.2.4", "typescript": "~4.8.4" }
本地使用默认Karma配置通过Chrome运行测试一切正常,但在GitLab CI/CD流水线配置ChromeHeadlessNoSandbox后,偶尔出现断连错误。
Karma相关配置:
browsers: ['Chrome', 'ChromeHeadlessNoSandbox'], customLaunchers: { ChromeHeadlessNoSandbox: { base: 'ChromeHeadless', flags: ['--no-sandbox'], browserNoActivityTimeout: 10000, browserDisconnectTimeout: 10000 } },
GitLab CI流水线配置:
test: stage: test image: node:18-alpine dependencies: - install_dependencies artifacts: paths: - coverage/ expire_in: 1 hour script: - apk add chromium - export CHROME_BIN=/usr/bin/chromium-browser - node_modules/.bin/ng test --code-coverage --browsers=ChromeHeadlessNoSandbox --watch=false
错误日志片段:
Chrome Headless 110.0.5481.177 (Linux x86_64): Executed 461 of 694 SUCCESS (0 secs / 1 min 0.636 secs) Chrome Headless 110.0.5481.177 (Linux x86_64): Executed 462 of 694 SUCCESS (0 secs / 1 min 0.642 secs) Chrome Headless 110.0.5481.177 (Linux x86_64): Executed 463 of 694 SUCCESS (0 secs / 1 min 1.067 secs) Chrome Headless 110.0.5481.177 (Linux x86_64): Executed 464 of 694 SUCCESS (0 secs / 1 min 1.068 secs) 02 03 2023 18:05:23.730:WARN [Chrome Headless 110.0.5481.177 (Linux x86_64)]: Disconnected (0 times) reconnect failed before timeout of 2000ms (ping timeout) Chrome Headless 110.0.5481.177 (Linux x86_64) ERROR Disconnected reconnect failed before timeout of 2000ms (ping timeout) Chrome Headless 110.0.5481.177 (Linux x86_64): Executed 464 of 694 DISCONNECTED (2 mins 26.054 secs / 1 min 1.068 secs) Chrome Headless 110.0.5481.177 (Linux x86_64) ERROR Disconnected reconnect failed before timeout of 2000ms (ping timeout) Chrome Headless 110.0.5481.177 (Linux x86_64): Executed 464 of 694 DISCONNECTED (2 mins 26.054 secs / 1 min 1.068 secs) ✔ Browser application bundle generation complete. =============================== Coverage summary =============================== Statements : Unknown% ( 0/0 ) Branches : Unknown% ( 0/0 ) Functions : Unknown% ( 0/0 ) Lines : Unknown% ( 0/0 ) ================================================================================ ✔ Browser application bundle generation complete. Cleaning up project directory and file based variables 00:04 ERROR: Job failed: exit code 1
目前只能通过重试任务解决,请问可能的原因是什么?
可能的原因及优化方向
1. GitLab公共Runner资源不足
GitLab公共Runner是共享资源,同一时间可能有大量任务抢占CPU、内存。当Chrome Headless运行测试到中间阶段时,资源不足会导致浏览器进程无响应,触发Karma的ping超时。
2. Chrome Headless启动参数不完整
当前仅添加--no-sandbox,容器环境下需补充参数优化稳定性:
--disable-gpu:容器无GPU,禁用避免相关错误--disable-dev-shm-usage:Docker的/dev/shm空间有限,禁用后Chrome用临时文件替代,防止内存不足崩溃--remote-debugging-port=9222:指定调试端口,避免端口冲突
修改后的Karma配置:
ChromeHeadlessNoSandbox: { base: 'ChromeHeadless', flags: [ '--no-sandbox', '--disable-gpu', '--disable-dev-shm-usage', '--remote-debugging-port=9222' ], browserNoActivityTimeout: 30000, browserDisconnectTimeout: 30000, browserDisconnectTolerance: 2 }
3. Karma超时参数设置过短
当前browserNoActivityTimeout和browserDisconnectTimeout仅10秒,资源紧张的Runner环境下,单个测试或打包过程可能超时,导致Karma判定断连。建议延长到30秒,同时增加browserDisconnectTolerance(允许断连重试次数)至2,避免单次临时断连直接失败。
4. Alpine镜像的Chromium兼容性问题
Alpine Linux使用musl libc,而Chrome通常基于glibc编译,兼容性存在隐患,可能导致偶尔崩溃。可换成Debian系的Node镜像(如node:18-bullseye-slim),自带的Chromium兼容性更好。
修改后的CI配置:
test: stage: test image: node:18-bullseye-slim dependencies: - install_dependencies artifacts: paths: - coverage/ expire_in: 1 hour script: - apt-get update && apt-get install -y chromium - export CHROME_BIN=/usr/bin/chromium - node_modules/.bin/ng test --code-coverage --browsers=ChromeHeadlessNoSandbox --watch=false
5. 测试本身存在不稳定因素
本地测试正常但CI环境暴露问题,可能是:
- 异步测试未正确等待(未用
async/await、fakeAsync) - 测试间状态污染,未清理组件、服务状态
- 依赖外部资源的测试未mock,导致偶尔超时
可尝试拆分测试批次,排查出错点附近的测试,定位不稳定用例。
内容的提问来源于stack exchange,提问作者Carla C

