Closed11
AngularのテストをCloud Buildで回す
このスクラップについて
Angularの自動テストをCloud Buildで動かすところまで持っていく。
Angularといっているが、結局はCloud Build環境での依存関係(karmaなど)をうまく解決するためのあれやこれなので、実際はAngularとはあまり関係ない。
nodeのバージョンとかは特に明記しない。
もし、上手い感じにまとまれば記事にしたいなあ。
ng new 直後の状況。
こいつを自動テストできる状態にする。
package.json
{
"name": "test-cloud-build",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "~11.2.8",
"@angular/common": "~11.2.8",
"@angular/compiler": "~11.2.8",
"@angular/core": "~11.2.8",
"@angular/forms": "~11.2.8",
"@angular/platform-browser": "~11.2.8",
"@angular/platform-browser-dynamic": "~11.2.8",
"@angular/router": "~11.2.8",
"rxjs": "~6.6.0",
"tslib": "^2.0.0",
"zone.js": "~0.11.3"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.1102.7",
"@angular/cli": "~11.2.7",
"@angular/compiler-cli": "~11.2.8",
"@types/jasmine": "~3.6.0",
"@types/node": "^12.11.1",
"codelyzer": "^6.0.0",
"jasmine-core": "~3.6.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~6.1.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.0.3",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.5.0",
"protractor": "~7.0.0",
"ts-node": "~8.3.0",
"tslint": "~6.1.0",
"typescript": "~4.1.5"
}
}
準備
CHROME_BINを通すためにpuppeteerを入れる
npm i -D puppeteer
設定ファイル達
karma.conf.js
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
+ if (require('puppeteer').executablePath()) {
+ process.env.CHROME_BIN = require('puppeteer').executablePath()
+ }
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('@angular-devkit/build-angular/plugins/karma')
],
client: {
jasmine: {
// you can add configuration options for Jasmine here
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
// for example, you can disable the random execution with `random: false`
// or set a specific seed with `seed: 4321`
},
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
jasmineHtmlReporter: {
suppressAll: true // removes the duplicated traces
},
coverageReporter: {
dir: require('path').join(__dirname, './coverage/test-cloud-build'),
subdir: '.',
reporters: [
{ type: 'html' },
{ type: 'text-summary' }
]
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
+ customLaunchers: {
+ ChromeHeadlessCI: {
+ base: 'ChromeHeadless',
+ flags: ['--no-sandbox']
+ }
+ },
singleRun: false,
restartOnFileChange: true
});
};
Dockerfile
FROM node
RUN apt-get update && \
apt-get install -y libgtk-3.0 libgbm-dev libnss3 libatk-bridge2.0-0 libasound2
Docker imageはArtifact Registryにpushしておく。
cloudbuild.yaml
steps:
- name: node:alpine
entrypoint: npm
args: ['install']
- name: 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE}'
entrypoint: npm
args: ["run", "test", "--" , "--no-watch", "--no-progress", "--browsers=ChromeHeadlessCI"]
timeout: 1500s
自前のコンテナを指定する際は、変数を使うと良さげだった。
TAGまで変数化するかはお好み。
Please, set "CHROME_BIN" env variable. エラー
ただ走らせるだけだと、こんなエラーが出る。
07 04 2021 07:00:14.287:INFO [launcher]: Launching browsers ChromeHeadlessCI with concurrency unlimited
07 04 2021 07:00:14.291:INFO [launcher]: Starting browser ChromeHeadless
07 04 2021 07:00:14.292:ERROR [launcher]: No binary for ChromeHeadless browser on your platform.
Please, set "CHROME_BIN" env variable.
こちらを参考にて、karma.conf.js に process.env.CHROME_BIN = require('puppeteer').executablePath()
を追加しておく。
依存ライブラリエラー
CHROME_BINを通した後にこんなエラーが出る。
07 04 2021 07:48:50.218:ERROR [launcher]: Cannot start ChromeHeadless
/workspace/node_modules/puppeteer/.local-chromium/linux-856583/chrome-linux/chrome: error while loading shared libraries: libnss3.so: cannot open shared object file: No such file or directory
依存関係を解決した環境でテストを実行する。
Dockerfile参照のこと。
puppeteerを入れたくないver
cloudbuild.yaml
steps:
- name: node:alpine
entrypoint: npm
args: ['i', '-D', 'puppeteer']
- name: node:alpine
entrypoint: npm
args: ['install']
- name: 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE}'
entrypoint: npm
args: ["run", "test", "--" , "--no-watch", "--no-progress", "--browsers=ChromeHeadlessCI"]
timeout: 1500s
Dockerfile
FROM node
RUN apt-get update && \
apt-get install -y libgtk-3.0 libgbm-dev libnss3 libatk-bridge2.0-0 libasound2
# 自動で取得できるいい案ないかなあ
ENV CHROME_BIN=/workspace/node_modules/puppeteer/.local-chromium/linux-856583/chrome-linux/chrome
Error: Cannot find module '/workspace/npm
こうやって指定して実行していて、ハマった
- name: 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE}'
args:
- npm run test -- --no-watch --no-progress --browsers=ChromeHeadlessCI
node:internal/modules/cjs/loader:927
throw err;
^
これで動く
- name: 'asia-northeast1-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE}'
entrypoint: npm
args: ["run", "test", "--" , "--no-watch", "--no-progress", "--browsers=ChromeHeadlessCI"]
which npm の結果が /usr/local/bin/npm
だったため、これを指定しても動きそう
node-sassのエラー
環境が若干古い場合に出たりする
Step #2: ERROR in ./src/styles.scss (./node_modules/@angular-devkit/build-angular/src/angular-cli-files/plugins/raw-css-loader.js!./node_modules/postcss-loader/src??embedded!./node_modules/sass-loader/lib/loader.js??ref--14-3!./src/styles.scss)
Step #2: Module build failed (from ./node_modules/sass-loader/lib/loader.js):
Step #2: Error: Node Sass does not yet support your current environment: Linux 64-bit with Unsupported runtime (88)
Step #2: For more information on which environments are supported please see:
Step #2: https://github.com/sass/node-sass/releases/tag/v4.11.0
Step #2: at module.exports (/workspace/node_modules/node-sass/lib/binding.js:13:13)
Step #2: at Object.<anonymous> (/workspace/node_modules/node-sass/lib/index.js:14:35)
Step #2: at Module._compile (node:internal/modules/cjs/loader:1092:14)
Step #2: at Object.Module._extensions..js (node:internal/modules/cjs/loader:1121:10)
Step #2: at Module.load (node:internal/modules/cjs/loader:972:32)
Step #2: at Function.Module._load (node:internal/modules/cjs/loader:813:14)
Step #2: at Module.require (node:internal/modules/cjs/loader:996:19)
Step #2: at require (node:internal/modules/cjs/helpers:92:18)
Step #2: at Object.sassLoader (/workspace/node_modules/sass-loader/lib/loader.js:46:72)
Step #2: @ ./src/styles.scss 2:14-241
Step #2: @ multi ./src/styles.scss
ここに書いてある、nodeのバージョンを指定する。
例
FROM node:10-slim
Error: Missing binding /workspace/node_modules/node-sass/vendor/linux-x64-64/binding.node
こんな感じのエラーが出た
This usually happens because your environment has changed since running `npm install`.
Run `npm rebuild node-sass` to download the binding for your current environment.
at module.exports (/workspace/node_modules/node-sass/lib/binding.js:15:13)
at Object.<anonymous> (/workspace/node_modules/node-sass/lib/index.js:14:35)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
at Module.require (internal/modules/cjs/loader.js:692:17)
at require (internal/modules/cjs/helpers.js:25:18)
at Object.sassLoader (/workspace/node_modules/sass-loader/lib/loader.js:46:72)
@ ./src/app/assignment/assignment-add/assignment-add.component.ts 495:21-63
@ ./src/app/assignment/assignment-add/assignment-add.component.spec.ts
@ ./src sync \.spec\.ts$
@ ./src/test.ts
こんな感じで対処した
- name: 'us-central1-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/${_IMAGE}'
entrypoint: 'npm'
args: ['rebuild', 'node-sass']
Disconnectedreconnect failed before timeout of 2000ms
19 05 2021 02:10:08.711:WARN [HeadlessChrome 91.0.4469 (Linux 0.0.0)]: Disconnected (0 times)reconnect failed before timeout of 2000ms (transport close)
HeadlessChrome 91.0.4469 (Linux 0.0.0) ERROR
Disconnectedreconnect failed before timeout of 2000ms (transport close)
HeadlessChrome 91.0.4469 (Linux 0.0.0): Executed 298 of 496 (skipped 140) DISCONNECTED (6 mins 41.202 secs / 6 mins 34.893 secs)
HeadlessChrome 91.0.4469 (Linux 0.0.0) ERROR
Disconnectedreconnect failed before timeout of 2000ms (transport close)
HeadlessChrome 91.0.4469 (Linux 0.0.0): Executed 298 of 496 (skipped 140) DISCONNECTED (6 mins 41.202 secs / 6 mins 34.893 secs)
19 05 2021 02:10:08.925:ERROR [karma-server]: UncaughtException
npm ERR! code ELIFECYCLE
karma.conf.js
flags: [
+ '--disable-gpu',
'--no-sandbox'
]
...
+ singleRun: true,
+ restartOnFileChange: true,
+ browserDisconnectTolerance: 2,
+ captureTimeout: 600000,
+ browserNoActivityTimeout: 120000,
cloudbuild.yaml
args: ["run", "test", "--" , "--no-watch", "--no-progress", "--browsers=ChromeHeadlessCI", "--source-map=false"]
これで今の所問題なさそう
- 参考
https://developers.google.com/web/updates/2017/04/headless-chrome?hl=ja#cli
https://stackoverflow.com/questions/58484124/karma-disconnectedreconnect-failed-before-timeout-of-with-chromeheadless
https://github.com/karma-runner/karma-chrome-launcher/issues/154
http://karma-runner.github.io/6.3/config/configuration-file.html
めちゃくちゃ遅いのでオススメはしないかも・・
パフォーマンス改善する余裕があったら再開するかもしれない
このスクラップは2021/09/10にクローズされました