I have an Angular 9 project and I am trying to get the minimal code coverage working on an pull request in Azure devops conform the documentation. However the minimal code coverage isn't working, probably missing some step....
Steps to reproduce:
- Create an new Angular 9 project: "ng new DefaultWebsite"
- Create build pipeline and edit the karma and protractor config conform Microsoft "Build, test, and deploy JavaScript and Node.js apps" documentation
- Add and "azurepipelines-coverage.yml" in the root of my project to enable the code coverage check in an pull request conform the Microsoft "Code coverage for pull requests" documentation
- Disable some test in de app.spec.ts file, so the code coverage isn't 100% any more, it now is 77%. Changed the minimal code coverag in the yml file to 95% so the pull request cannot be complited conform the theory and it should give an "Coverage status check failed" error conform the Microsoft documentation.
However when the pull request is started there is an code coverage check below the 'Status' part. When the build (with unit and e2e tests) is done, there is no code coverage error which I espect te see below the 'Status' part.
Pull reqeust with code coverage check Pull reqeust build completed
When I look at the build there are test results and code coverage results.
Build test result Build code coverage result
When I look at the code coverage result I see an Line coverage of 75% which should be an minimal of 90% conform the yml-file.
Karma config file
// 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 config file:
// 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 Build pipeline steps:
"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": ""
}
}
],