首页 > 解决方案 > Azure devops - 最小代码覆盖拉取请求

问题描述

我有一个 Angular 9 项目,我试图在 Azure devops 中的拉取请求上获得最小的代码覆盖率,以符合文档。然而,最小的代码覆盖率不起作用,可能缺少一些步骤......

重现步骤:

  1. 创建一个新的 Angular 9 项目:“ng new DefaultWebsite”
  2. 创建构建管道并编辑业力和量角器配置符合 Microsoft“构建、测试和部署 JavaScript 和 Node.js 应用程序”文档
  3. 在我的项目的根目录中添加和“azurepipelines-coverage.yml”以启用拉取请求中的代码覆盖率检查符合 Microsoft“拉取请求的代码覆盖率”文档
  4. 在 de app.spec.ts 文件中禁用一些测试,因此代码覆盖率不再是 100%,现在是 77%。将 yml 文件中的最小代码覆盖率更改为 95%,因此无法编译拉取请求符合理论,它应该给出“覆盖状态检查失败”错误,符合 Microsoft 文档。

但是,当拉取请求启动时,“状态”部分下方会进行代码覆盖率检查。构建(使用单元和 e2e 测试)完成后,没有代码覆盖错误,我认为您可以在“状态”部分下方看到。

使用代码覆盖检查 拉取请求 拉取请求构建完成

当我查看构建时,会有测试结果和代码覆盖率结果。

构建测试结果 构建代码覆盖率结果

当我查看代码覆盖率结果时,我看到 75% 的行覆盖率应该是 90% 的最小值,符合 yml 文件。

业力配置文件

// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function (config) {
  const process = require('process');
  process.env.CHROME_BIN = require('puppeteer').executablePath();

  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-istanbul-reporter'),
      require('@angular-devkit/build-angular/plugins/karma'),
      require('karma-junit-reporter')
    ],
    client: {
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    coverageIstanbulReporter: {
      dir: require('path').join(__dirname, './coverage'),
      reports: ['html', 'lcovonly', 'text-summary', 'cobertura'],
      fixWebpackSourcePaths: true
    },
    coverageReporter: {
      type : 'html',
      dir : 'coverage/'
    },
    junitReporter: {
      outputDir: './coverage', // results will be saved as $outputDir/$browserName.xml
      outputFile: 'junit.xml', // if included, results will be saved as $outputDir/$browserName/$outputFile
      suite: '', // suite will become the package name attribute in xml testsuite element
      useBrowserName: true, // add browser name to report and classes names
      nameFormatter: undefined, // function (browser, result) to customize the name attribute in xml testcase element
      classNameFormatter: undefined, // function (browser, result) to customize the classname attribute in xml testcase element
      properties: {}, // key value pair of properties to add to the <properties> section of the report
      xmlVersion: null // use '1' if reporting to be per SonarQube 6.2 XML format
    },
    reporters: ['progress', 'kjhtml','junit'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['ChromeHeadless'],
    singleRun: false,
    restartOnFileChange: true
  });
};

量角器配置文件:

// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts

const { SpecReporter } = require('jasmine-spec-reporter');
const { JUnitXmlReporter } = require('jasmine-reporters');

process.env.CHROME_BIN = process.env.CHROME_BIN || require("puppeteer").executablePath();

exports.config = {
  allScriptsTimeout: 11000,
  specs: [
    './src/**/*.e2e-spec.ts'
  ],
  capabilities: {
    'browserName': 'chrome',

    chromeOptions: {
      args: ["--headless", "--disable-gpu", "--window-size=1200,900"],
      binary: process.env.CHROME_BIN
    }
  },
  directConnect: true,
  baseUrl: 'http://localhost:4200/',
  framework: 'jasmine',
  jasmineNodeOpts: {
    showColors: true,
    defaultTimeoutInterval: 30000,
    print: function () { }
  },
  onPrepare() {
    require('ts-node').register({
      project: require('path').join(__dirname, './tsconfig.json')
    });
    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
    var junitReporter = new JUnitXmlReporter({
      savePath: require('path').join(__dirname, './junit'),
      consolidateAll: true
    });
    jasmine.getEnv().addReporter(junitReporter);
  }
};

azurepipelines-coverage.yml

coverage:
  status:           #Code coverage status will be posted to pull requests based on targets defined below.
    diff:           #diff coverage is code coverage only for the lines changed in a pull request.
      target: 95%   #set this to a desired %. Default is 70%.

Azure 构建管道步骤:

"steps": [
    {
        "environment": {},
        "enabled": true,
        "continueOnError": false,
        "alwaysRun": false,
        "displayName": "npm install",
        "timeoutInMinutes": 0,
        "condition": "succeeded()",
        "task": {
            "id": "fe47e961-9fa8-4106-8639-368c022d43ad",
            "versionSpec": "1.*",
            "definitionType": "task"
        },
        "inputs": {
            "command": "install",
            "workingDir": "Project\\Frontend\\DefaultWebsite",
            "verbose": "false",
            "customCommand": "",
            "customRegistry": "useNpmrc",
            "customFeed": "",
            "customEndpoint": "",
            "publishRegistry": "useExternalRegistry",
            "publishFeed": "",
            "publishPackageMetadata": "true",
            "publishEndpoint": ""
        }
    },
    {
        "environment": {},
        "enabled": true,
        "continueOnError": false,
        "alwaysRun": false,
        "displayName": "npm custom - test ",
        "timeoutInMinutes": 0,
        "condition": "succeeded()",
        "task": {
            "id": "fe47e961-9fa8-4106-8639-368c022d43ad",
            "versionSpec": "1.*",
            "definitionType": "task"
        },
        "inputs": {
            "command": "custom",
            "workingDir": "Project\\Frontend\\DefaultWebsite",
            "verbose": "false",
            "customCommand": "run test",
            "customRegistry": "useNpmrc",
            "customFeed": "",
            "customEndpoint": "",
            "publishRegistry": "useExternalRegistry",
            "publishFeed": "",
            "publishPackageMetadata": "true",
            "publishEndpoint": ""
        }
    },
    {
        "environment": {},
        "enabled": true,
        "continueOnError": false,
        "alwaysRun": false,
        "displayName": "Publish code coverage from Project\\Frontend\\DefaultWebsite\\coverage\\cobertura-coverage.xml",
        "timeoutInMinutes": 0,
        "condition": "succeeded()",
        "task": {
            "id": "2a7ebc54-c13e-490e-81a5-d7561ab7cd97",
            "versionSpec": "1.*",
            "definitionType": "task"
        },
        "inputs": {
            "codeCoverageTool": "Cobertura",
            "summaryFileLocation": "Project\\Frontend\\DefaultWebsite\\coverage\\cobertura-coverage.xml",
            "pathToSources": "",
            "reportDirectory": "",
            "additionalCodeCoverageFiles": "",
            "failIfCoverageEmpty": "false"
        }
    },
    {
        "environment": {},
        "enabled": true,
        "continueOnError": false,
        "alwaysRun": false,
        "displayName": "Publish Test Results Project\\Frontend\\DefaultWebsite\\**\\junit.xml copy",
        "timeoutInMinutes": 0,
        "condition": "succeeded()",
        "task": {
            "id": "0b0f01ed-7dde-43ff-9cbb-e48954daf9b1",
            "versionSpec": "2.*",
            "definitionType": "task"
        },
        "inputs": {
            "testRunner": "JUnit",
            "testResultsFiles": "Project\\Frontend\\DefaultWebsite\\**\\junit.xml",
            "searchFolder": "$(System.DefaultWorkingDirectory)",
            "mergeTestResults": "false",
            "failTaskOnFailedTests": "false",
            "testRunTitle": "",
            "platform": "",
            "configuration": "",
            "publishRunAttachments": "true"
        }
    },
    {
        "environment": {},
        "enabled": true,
        "continueOnError": false,
        "alwaysRun": false,
        "displayName": "npm custom - e2e",
        "timeoutInMinutes": 0,
        "condition": "succeeded()",
        "task": {
            "id": "fe47e961-9fa8-4106-8639-368c022d43ad",
            "versionSpec": "1.*",
            "definitionType": "task"
        },
        "inputs": {
            "command": "custom",
            "workingDir": "Project\\Frontend\\DefaultWebsite",
            "verbose": "false",
            "customCommand": "run e2e",
            "customRegistry": "useNpmrc",
            "customFeed": "",
            "customEndpoint": "",
            "publishRegistry": "useExternalRegistry",
            "publishFeed": "",
            "publishPackageMetadata": "true",
            "publishEndpoint": ""
        }
    },
    {
        "environment": {},
        "enabled": true,
        "continueOnError": false,
        "alwaysRun": false,
        "displayName": "Publish Test Results Project\\Frontend\\DefaultWebsite\\e2e\\**\\junitresults.xml",
        "timeoutInMinutes": 0,
        "condition": "succeeded()",
        "task": {
            "id": "0b0f01ed-7dde-43ff-9cbb-e48954daf9b1",
            "versionSpec": "2.*",
            "definitionType": "task"
        },
        "inputs": {
            "testRunner": "JUnit",
            "testResultsFiles": "Project\\Frontend\\DefaultWebsite\\e2e\\**\\junitresults.xml",
            "searchFolder": "$(System.DefaultWorkingDirectory)",
            "mergeTestResults": "false",
            "failTaskOnFailedTests": "false",
            "testRunTitle": "",
            "platform": "",
            "configuration": "",
            "publishRunAttachments": "true"
        }
    },
    {
        "environment": {},
        "enabled": true,
        "continueOnError": false,
        "alwaysRun": false,
        "displayName": "npm custom - prodBuild",
        "timeoutInMinutes": 0,
        "condition": "succeeded()",
        "task": {
            "id": "fe47e961-9fa8-4106-8639-368c022d43ad",
            "versionSpec": "1.*",
            "definitionType": "task"
        },
        "inputs": {
            "command": "custom",
            "workingDir": "Project\\Frontend\\DefaultWebsite",
            "verbose": "false",
            "customCommand": "run prodBuild",
            "customRegistry": "useNpmrc",
            "customFeed": "",
            "customEndpoint": "",
            "publishRegistry": "useExternalRegistry",
            "publishFeed": "",
            "publishPackageMetadata": "true",
            "publishEndpoint": ""
        }
    },
    {
        "environment": {},
        "enabled": true,
        "continueOnError": false,
        "alwaysRun": false,
        "displayName": "Publish Artifact: app",
        "timeoutInMinutes": 0,
        "condition": "succeeded()",
        "task": {
            "id": "2ff763a7-ce83-4e1f-bc89-0ae63477cebe",
            "versionSpec": "1.*",
            "definitionType": "task"
        },
        "inputs": {
            "PathtoPublish": "Project\\Frontend\\DefaultWebsite\\dist",
            "ArtifactName": "app",
            "ArtifactType": "Container",
            "TargetPath": "",
            "Parallel": "false",
            "ParallelCount": "8",
            "FileCopyOptions": ""
        }
    }
],

标签: azure-devopscode-coveragepull-requestangular9angular-unit-test

解决方案


推荐阅读