在 docker 中 运行 e2e Angular 测试和设置 Chromium 的问题

Issue with running e2e Angular tests in docker and setting up Chromium

我正在为 运行 我的 Angular E2E 测试设置一个 docker 容器。似乎我在设置 Chromium 时遗漏了一些东西。我正在使用 Angular 11 和量角器。

我的 Dockerfile 是

FROM node:15.6.0

RUN apt-get update && \
    DEBIAN_FRONTEND="nointeractive" \
    apt-get install -y --no-install-recommends \
    chromium \
    libgconf-2-4 \
    openjdk-8-jre-headless \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /opt/frontend/angular
COPY . .

RUN rm -r node_modules
RUN npm install -g @angular/cli
RUN npm install

CMD ng e2e --baseUrl="http://something.com/"

我在 docker 中遇到的错误是

Connected.
Your global Angular CLI version (11.1.1) is greater than your local version (11.0.0). The local Angular CLI version is used.

To disable this warning use "ng config -g cli.warnings.versionMismatch false".
[20:43:25] I/file_manager - creating folder /opt/frontend/angular/node_modules/protractor/node_modules/webdriver-manager/selenium
[20:43:25] I/config_source - curl -o/opt/frontend/angular/node_modules/protractor/node_modules/webdriver-manager/selenium/chrome-response.xml https://chromedriver.storage.googleapis.com/
[20:43:27] I/downloader - curl -o/opt/frontend/angular/node_modules/protractor/node_modules/webdriver-manager/selenium/chromedriver_88.0.4324.96.zip https://chromedriver.storage.googleapis.com/88.0.4324.96/chromedriver_linux64.zip
[20:43:29] I/update - chromedriver: unzipping chromedriver_88.0.4324.96.zip
[20:43:29] I/update - chromedriver: setting permissions to 0755 for /opt/frontend/angular/node_modules/protractor/node_modules/webdriver-manager/selenium/chromedriver_88.0.4324.96
[20:43:30] I/launcher - Running 1 instances of WebDriver
[20:43:30] I/direct - Using ChromeDriver directly...
[20:43:32] E/runner - Unable to start a WebDriver session.
[20:43:32] E/launcher - Error: WebDriverError: unknown error: Chrome failed to start: exited abnormally.
  (unknown error: DevToolsActivePort file doesn't exist)
  (The process started from chrome location /usr/bin/chromium is no longer running, so ChromeDriver is assuming that Chrome has crashed.)
  (Driver info: chromedriver=88.0.4324.96 (68dba2d8a0b149a1d3afac56fa74648032bcf46b-refs/branch-heads/4324@{#1784}),platform=Linux 4.19.121-linuxkit x86_64)
    at Object.checkLegacyResponse (/opt/frontend/angular/node_modules/selenium-webdriver/lib/error.js:546:15)
    at parseHttpResponse (/opt/frontend/angular/node_modules/selenium-webdriver/lib/http.js:509:13)
    at /opt/frontend/angular/node_modules/selenium-webdriver/lib/http.js:441:30
    at processTicksAndRejections (node:internal/process/task_queues:94:5)
[20:43:32] E/launcher - Process exited with error code 100
Disconnected from container.

在 docker 中为 Angular e2e 测试设置 Chromium 时,我是否遗漏了什么?

您可以使用解决此任务的预构建映像 https://hub.docker.com/r/trion/ng-cli-e2e 或从有效的 Dockerfile 中获得灵感: https://github.com/trion-development/docker-ng-cli-e2e/blob/master/Dockerfile

主要问题在 Dockerfile 和量角器配置文件中。

量角器配置文件的第一个问题是您应该传递正确的 chromeOptions。这些参数是必需的。最终量角器文件:

const { SpecReporter } = require('jasmine-spec-reporter');
const PrettyReporter = require('protractor-pretty-html-reporter').Reporter;
const path = require('path');
const fs = require('fs');
const now = new Date();
exports.report_name = 'Report-' + now.getFullYear() + "-" + (now.getMonth() + 1) + "-" + now.getDate() + "-" + now.getHours() + "-" + now.getMinutes() + "-" + now.getSeconds();
exports.logfile_name = 'results-' + now.getFullYear() + "-" + (now.getMonth() + 1) + "-" + now.getDate() + "-" + now.getHours() + "-" + now.getMinutes() + "-" + now.getSeconds();
const Reporter = path.resolve("./target/");
const report = `${Reporter}` + '/' + exports.report_name;

const mkdirSync = function (report) {
  try {
    fs.mkdirSync(report);
  }
  catch (err) {
    if (err.code !== 'EEXIST')
      throw err;
  }
};
// @ts-ignore
var prettyReporter = new PrettyReporter({
  path: report,
  screenshotOnPassed: true
});

/**
 * @type { import("protractor").Config }
 */
exports.config = {
  allScriptsTimeout: 11000,
  specs: [
    './src/**/*.e2e-spec.ts'
  ],
  capabilities: {
    browserName: 'chrome',
    'directConnect': true,
    chromeOptions: {
      args: [
        'window-size=1280,710',
        'no-sandbox',
        'headless',
        'disable-gpu',
        'disable-dev-shm-usage'
      ]
    },
    sharedTestFiles: true,
    maxInstances: 1
  },
  directConnect: true,
  baseUrl: 'http://localhost:4200/',
  framework: 'jasmine',
  jasmineNodeOpts: {
    showColors: true,
    defaultTimeoutInterval: 30000,
    print: function() {}
  },
  beforeLaunch() {
    mkdirSync("target")
    prettyReporter.startReporter();
  },
  onPrepare() {
    require('ts-node').register({
      project: require('path').join(__dirname, './tsconfig.json')
    });
    jasmine.getEnv().addReporter(prettyReporter);
    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
  }
};

另一个问题是无法找到 Chrome 的特定版本,并且很容易在每次构建时遇到此问题,因为版本可能会更改。解决方案是确保您知道正在安装哪个版本的 Chrome。然后您需要使用节点模块中的 webdriver-manager 更新预期的 Chrome 版本(请注意,此步骤应在安装节点包后完成)。这是成功运行的 Dockerfile 的编辑版本。最终的 Dockerfile:

FROM node:15.6.0
ENV chrome_version=88.0.4324.104
ENV testurl default_test_base_url

# Google Chrome
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
    && echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list \
    && apt-get update -qqy \
    && apt-get -qqy install google-chrome-stable \
    && rm /etc/apt/sources.list.d/google-chrome.list \
    && rm -rf /var/lib/apt/lists/* /var/cache/apt/* \
    && sed -i 's/"$HERE\/chrome"/"$HERE\/chrome" --no-sandbox/g' /opt/google/chrome/google-chrome
    
WORKDIR /opt/frontend/angular
COPY ./frontend/angular .

RUN rm -rf node_modules || true
RUN npm install -g @angular/cli@11
RUN npm install
RUN ./node_modules/.bin/webdriver-manager update --versions.chrome ${chrome_version}

CMD ng e2e --baseUrl=$testurl