Karma with Webpack:伊斯坦布尔覆盖率为 100%(0/0)
Karma with Webpack: Istanbul coverage is 100%(0/0)
我正在尝试使用 Webpack (4.27.1) 和 Karma(3.1.3) + Jasmine(jasmine-core 2.99.1) 为 Angular 1.6.6 应用程序实现代码覆盖功能。所有测试都成功通过。但是 Istanbul(0.4.5) 代码覆盖率结果显示 100%(0/0)
测试结果输出
===========覆盖率摘要============
报表:100% ( 0/0 )
分支机构 : 100% ( 0/0 )
功能 : 100% ( 0/0 )
线条:100% ( 0/0 )
========================================
HeadlessChrome 73.0.3683 (Windows 7.0.0):执行 127 次,共 128 次(跳过 1 次)成功(15.837 秒/14.88 秒)
总计:127 次成功
karma.config.js
const webpackConfig = require('./webpack.config.js');
webpackConfig.devtool = false;
module.exports = function (config) {
config.set({
plugins: [
'karma-*'
],
singleRun: true,
frameworks: ['jasmine'],
basePath: '../',
exclude: [],
browsers: ['ChromeHeadless'],
preprocessors: {
'test/unit/index_test.js': ['webpack'],
'app/index.js': ['coverage']
},
'reporters': [
'coverage', 'spec', 'html', 'junit'
],
webpack: webpackConfig,
coverageReporter: {
dir: 'target/test-results/coverage',
reporters: [
{ type: 'html', subdir: 'html' },
{ type: 'lcovonly', subdir: '.' },
{ type: 'text-summary' }
],
instrumenterOptions: {
istanbul: { noCompact: true }
},
check: {
global: {
statements: 90.0,
branches: 80.0,
functions: 80.0,
lines: 90.0
}
}
},
reportSlowerThan: 100,
browserNoActivityTimeout: 60000,
autoWatch: true,
files: [
'node_modules/babel-polyfill/dist/polyfill.js',
'test/unit/index_test.js',
]
});
};
webpack.config.js
const webpack = require('webpack');
const path = require('path');
module.exports = merge.smart(base, {
entry: {
app: './src/app.js'
},
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
devtool: 'eval',
devServer: {open: true},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
]
}
})
;
.babelrc
{
"presets": ["@babel/preset-env", "@babel/preset-react"],
"plugins": [
"angularjs-annotate",
"@babel/plugin-transform-modules-commonjs"
],
"env": {
"test": {
"plugins": ["istanbul"]
}
}
}
index_test.js
import 'core-js/es6/reflect';
import 'core-js/client/shim';
require('app/index');
require('angular');
require('angular-mocks/angular-mocks');
beforeEach(() => {
angular.mock.module('app');
});
const testContext = require.context('.', true, /\.spec.js?$/);
testContext.keys().forEach(testContext);
const srcContext = require.context('../../app/', false, /app\.module\.js$/);
srcContext.keys().forEach(srcContext);
我们从未设法为我们的 angularjs 项目配置 istanbul
的代码覆盖率。此版本的伊斯坦布尔也已弃用
我们切换到 istanbul-instrumenter-loader
webpack loader
以下配置将为我们生成代码覆盖率
找不到我们遵循的原始指南,但我会最好地描述我们的配置
尽我所能:
package.json devDependencies(与代码覆盖率相关)
{
"babel-loader": "^8.0.5",
"istanbul-instrumenter-loader": "^3.0.1", // webpack loader added in coverage tests
"jasmine-core": "^2.99.1",
"karma": "^3.1.3",
"karma-chrome-launcher": "^2.2.0",
"karma-cli": "^1.0.1",
"karma-coverage-istanbul-reporter": "^1.4.2", // coverage reporter used in tests
"karma-html-reporter": "^0.2.7", // html reporter used in tests
"karma-jasmine": "^1.1.1",
"karma-ng-html2js-preprocessor": "^1.0.0",
"karma-sourcemap-loader": "^0.3.7",
"karma-spec-reporter": "0.0.32",
"karma-webpack": "^3.0.5",
"webpack": "4.28.4",
}
测试包版本接近你的
package.json 测试脚本:
我们的业力配置在 ./karma
子文件夹中
"scripts": {
"test": "NODE_ENV=development karma start karma/karma.conf.js",
"cover": "npm test -- --cover --reportHtml", // pass flags to karma.conf
}
karma/karma.conf.js
const path = require('path');
const makeWebpackTestConfig = require('./karma.webpack.config');
module.exports = (config) => {
const REPORTS_PATH = path.join(__dirname, '../reports/');
const cover = config.cover || process.env.COVER;
const webstorm = process.env.WEBSTORM; // Running coverage from inside the IDE
const webpack = makeWebpackTestConfig(cover);
const reporters = config.reportHtml ? ['html'] : [];
if (!webstorm) reporters.push('spec');
if (cover) reporters.push('coverage-istanbul');
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '../',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: ['src/main.tests.js'],
// list of files to exclude
exclude: [],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'src/**/*.js': ['webpack', 'sourcemap'],
'src/**/*.html': ['webpack'],
'src/**/*.less': ['webpack'],
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters,
specReporter: {
maxLogLines: 5, // limit number of lines logged per test
suppressErrorSummary: false,// do not print error summary
suppressFailed: false, // do not print information about failed tests
suppressPassed: false, // do not print information about passed tests
suppressSkipped: true, // do not print information about skipped tests
showSpecTiming: true, // print the time elapsed for each spec
failFast: false // test would finish with error when a first fail occurs.
},
htmlReporter: {
outputDir: path.join(REPORTS_PATH, 'unit-tests'), // where to put the reports
// templatePath: null, // set if you moved jasmine_template.html
focusOnFailures: true, // reports show failures on start
namedFiles: true, // name files instead of creating sub-directories
pageTitle: 'Unit Tests', // page title for reports; browser info by default
urlFriendlyName: true, // simply replaces spaces with _ for files/dirs
reportName: 'index', // report summary filename; browser info by default
// experimental
preserveDescribeNesting: true, // folded suites stay folded
foldAll: true, // reports start folded (only with preserveDescribeNesting)
},
coverageIstanbulReporter: {
reports: ['lcov', 'text-summary'],
dir: webstorm ? undefined : path.join(REPORTS_PATH, 'code-coverage'),
},
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN ||
// config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['RunnerHeadless'],
customLaunchers: {
RunnerHeadless: {
base: 'ChromeHeadless',
flags: ['--headless', '--no-sandbox', '--disable-gpu', '--disable-translate', '--disable-extensions'],
},
},
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true,
webpack,
webpackMiddleware: {
stats: 'errors-only',
},
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity,
client: {
// Log browser console only locally
captureConsole: !!process.env.WEBSTORM,
}
});
};
同样,由于业力配置位于子文件夹中,因此路径(基础、报告等)的配置不同。大多数配置都是不言自明的。
- 我们有一个 env 变量
WEBSTORM
,当 IDE 中的覆盖范围为 运行 时,我们会设置它。
- 还要记住,需要启用源映射才能正确映射到原始源行,因为原始源由 babel 转换。
- 我们正在使用自定义
browsers
配置,您的情况可能不需要
karma/karma.webpack.config.js
const makeWebpackConfig = require('../webpack/base-config');
module.exports = (cover) => {
const defaultConfig = makeWebpackConfig();
// Remove entry. Karma will provide the source
defaultConfig.entry = null;
// Have source maps generated so covered statements are mapped correctly
defaultConfig.devtool = 'inline-source-map';
defaultConfig.mode = 'development';
defaultConfig.optimization = {
splitChunks: false,
runtimeChunk: false,
minimize: false,
};
if (cover) {
defaultConfig.module.rules.push({
test: /\.js$/,
use: {
loader: 'istanbul-instrumenter-loader',
options: { esModules: true },
},
enforce: 'post',
exclude: /node_modules|\.spec\.js$/,
});
}
return defaultConfig;
};
makeWebpackConfig
创建我们在 运行ning 开发或生产构建时使用的基础配置,其中包含 babel-loader
和其他样式加载器、html、文件等...
- 需要覆盖的任何设置都在
karma.webpack.conf.js
中被覆盖
- 条目已删除,我想,Karam 无论如何都会覆盖它。
- 重要
devtool
设置为 inline-source-map
- 结果是一场巨大的斗争,因为似乎外部源映射没有被拾取并且在我们设置为 inline
配置之前,源映射不起作用。源映射不仅有助于代码覆盖,而且在测试失败和打印出错误信息时也有帮助——它将引用原始代码行。
- 最后,在进行覆盖时,将加载程序配置为排除 node_modules 和任何外部源,并排除测试本身
.babelrc 配置
{
"presets": [
["@babel/preset-env", { "modules": "commonjs" }],
"@babel/preset-react"
],
"plugins": [
"angularjs-annotate",
["@babel/plugin-proposal-decorators", {
"legacy": true
}],
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-syntax-import-meta",
["@babel/plugin-proposal-class-properties", {
"loose": true
}],
"@babel/plugin-proposal-json-strings",
"@babel/plugin-proposal-function-sent",
"@babel/plugin-proposal-export-namespace-from",
"@babel/plugin-proposal-numeric-separator",
"@babel/plugin-proposal-throw-expressions",
"@babel/plugin-proposal-export-default-from",
"@babel/plugin-proposal-logical-assignment-operators",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-do-expressions",
"@babel/plugin-proposal-function-bind"
]
}
应该可以使用您自己的 .babelrc
配置。 { "modules": "commonjs" }
出于某种原因对我们很重要,但现在不记得了
测试入口点 - src/main.tests.js
import '@babel/polyfill';
import './appConfig';
import './main';
const testsContext = require.context('.', true, /\.spec.js$/);
testsContext.keys().forEach(testsContext);
这与您的配置类似,尽管 angular 是在 main
中导入的,并且 anglar-mocks
是为每个测试导入的,因为我们有很多单独的模块
我正在尝试使用 Webpack (4.27.1) 和 Karma(3.1.3) + Jasmine(jasmine-core 2.99.1) 为 Angular 1.6.6 应用程序实现代码覆盖功能。所有测试都成功通过。但是 Istanbul(0.4.5) 代码覆盖率结果显示 100%(0/0)
测试结果输出
===========覆盖率摘要============
报表:100% ( 0/0 ) 分支机构 : 100% ( 0/0 ) 功能 : 100% ( 0/0 ) 线条:100% ( 0/0 )
========================================
HeadlessChrome 73.0.3683 (Windows 7.0.0):执行 127 次,共 128 次(跳过 1 次)成功(15.837 秒/14.88 秒) 总计:127 次成功
karma.config.js
const webpackConfig = require('./webpack.config.js');
webpackConfig.devtool = false;
module.exports = function (config) {
config.set({
plugins: [
'karma-*'
],
singleRun: true,
frameworks: ['jasmine'],
basePath: '../',
exclude: [],
browsers: ['ChromeHeadless'],
preprocessors: {
'test/unit/index_test.js': ['webpack'],
'app/index.js': ['coverage']
},
'reporters': [
'coverage', 'spec', 'html', 'junit'
],
webpack: webpackConfig,
coverageReporter: {
dir: 'target/test-results/coverage',
reporters: [
{ type: 'html', subdir: 'html' },
{ type: 'lcovonly', subdir: '.' },
{ type: 'text-summary' }
],
instrumenterOptions: {
istanbul: { noCompact: true }
},
check: {
global: {
statements: 90.0,
branches: 80.0,
functions: 80.0,
lines: 90.0
}
}
},
reportSlowerThan: 100,
browserNoActivityTimeout: 60000,
autoWatch: true,
files: [
'node_modules/babel-polyfill/dist/polyfill.js',
'test/unit/index_test.js',
]
});
};
webpack.config.js
const webpack = require('webpack');
const path = require('path');
module.exports = merge.smart(base, {
entry: {
app: './src/app.js'
},
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
devtool: 'eval',
devServer: {open: true},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
]
}
})
;
.babelrc
{
"presets": ["@babel/preset-env", "@babel/preset-react"],
"plugins": [
"angularjs-annotate",
"@babel/plugin-transform-modules-commonjs"
],
"env": {
"test": {
"plugins": ["istanbul"]
}
}
}
index_test.js
import 'core-js/es6/reflect';
import 'core-js/client/shim';
require('app/index');
require('angular');
require('angular-mocks/angular-mocks');
beforeEach(() => {
angular.mock.module('app');
});
const testContext = require.context('.', true, /\.spec.js?$/);
testContext.keys().forEach(testContext);
const srcContext = require.context('../../app/', false, /app\.module\.js$/);
srcContext.keys().forEach(srcContext);
我们从未设法为我们的 angularjs 项目配置 istanbul
的代码覆盖率。此版本的伊斯坦布尔也已弃用
我们切换到 istanbul-instrumenter-loader
webpack loader
以下配置将为我们生成代码覆盖率
找不到我们遵循的原始指南,但我会最好地描述我们的配置
尽我所能:
package.json devDependencies(与代码覆盖率相关)
{
"babel-loader": "^8.0.5",
"istanbul-instrumenter-loader": "^3.0.1", // webpack loader added in coverage tests
"jasmine-core": "^2.99.1",
"karma": "^3.1.3",
"karma-chrome-launcher": "^2.2.0",
"karma-cli": "^1.0.1",
"karma-coverage-istanbul-reporter": "^1.4.2", // coverage reporter used in tests
"karma-html-reporter": "^0.2.7", // html reporter used in tests
"karma-jasmine": "^1.1.1",
"karma-ng-html2js-preprocessor": "^1.0.0",
"karma-sourcemap-loader": "^0.3.7",
"karma-spec-reporter": "0.0.32",
"karma-webpack": "^3.0.5",
"webpack": "4.28.4",
}
测试包版本接近你的
package.json 测试脚本:
我们的业力配置在 ./karma
子文件夹中
"scripts": {
"test": "NODE_ENV=development karma start karma/karma.conf.js",
"cover": "npm test -- --cover --reportHtml", // pass flags to karma.conf
}
karma/karma.conf.js
const path = require('path');
const makeWebpackTestConfig = require('./karma.webpack.config');
module.exports = (config) => {
const REPORTS_PATH = path.join(__dirname, '../reports/');
const cover = config.cover || process.env.COVER;
const webstorm = process.env.WEBSTORM; // Running coverage from inside the IDE
const webpack = makeWebpackTestConfig(cover);
const reporters = config.reportHtml ? ['html'] : [];
if (!webstorm) reporters.push('spec');
if (cover) reporters.push('coverage-istanbul');
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '../',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: ['src/main.tests.js'],
// list of files to exclude
exclude: [],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'src/**/*.js': ['webpack', 'sourcemap'],
'src/**/*.html': ['webpack'],
'src/**/*.less': ['webpack'],
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters,
specReporter: {
maxLogLines: 5, // limit number of lines logged per test
suppressErrorSummary: false,// do not print error summary
suppressFailed: false, // do not print information about failed tests
suppressPassed: false, // do not print information about passed tests
suppressSkipped: true, // do not print information about skipped tests
showSpecTiming: true, // print the time elapsed for each spec
failFast: false // test would finish with error when a first fail occurs.
},
htmlReporter: {
outputDir: path.join(REPORTS_PATH, 'unit-tests'), // where to put the reports
// templatePath: null, // set if you moved jasmine_template.html
focusOnFailures: true, // reports show failures on start
namedFiles: true, // name files instead of creating sub-directories
pageTitle: 'Unit Tests', // page title for reports; browser info by default
urlFriendlyName: true, // simply replaces spaces with _ for files/dirs
reportName: 'index', // report summary filename; browser info by default
// experimental
preserveDescribeNesting: true, // folded suites stay folded
foldAll: true, // reports start folded (only with preserveDescribeNesting)
},
coverageIstanbulReporter: {
reports: ['lcov', 'text-summary'],
dir: webstorm ? undefined : path.join(REPORTS_PATH, 'code-coverage'),
},
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN ||
// config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['RunnerHeadless'],
customLaunchers: {
RunnerHeadless: {
base: 'ChromeHeadless',
flags: ['--headless', '--no-sandbox', '--disable-gpu', '--disable-translate', '--disable-extensions'],
},
},
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true,
webpack,
webpackMiddleware: {
stats: 'errors-only',
},
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity,
client: {
// Log browser console only locally
captureConsole: !!process.env.WEBSTORM,
}
});
};
同样,由于业力配置位于子文件夹中,因此路径(基础、报告等)的配置不同。大多数配置都是不言自明的。
- 我们有一个 env 变量
WEBSTORM
,当 IDE 中的覆盖范围为 运行 时,我们会设置它。 - 还要记住,需要启用源映射才能正确映射到原始源行,因为原始源由 babel 转换。
- 我们正在使用自定义
browsers
配置,您的情况可能不需要
karma/karma.webpack.config.js
const makeWebpackConfig = require('../webpack/base-config');
module.exports = (cover) => {
const defaultConfig = makeWebpackConfig();
// Remove entry. Karma will provide the source
defaultConfig.entry = null;
// Have source maps generated so covered statements are mapped correctly
defaultConfig.devtool = 'inline-source-map';
defaultConfig.mode = 'development';
defaultConfig.optimization = {
splitChunks: false,
runtimeChunk: false,
minimize: false,
};
if (cover) {
defaultConfig.module.rules.push({
test: /\.js$/,
use: {
loader: 'istanbul-instrumenter-loader',
options: { esModules: true },
},
enforce: 'post',
exclude: /node_modules|\.spec\.js$/,
});
}
return defaultConfig;
};
makeWebpackConfig
创建我们在 运行ning 开发或生产构建时使用的基础配置,其中包含 babel-loader
和其他样式加载器、html、文件等...
- 需要覆盖的任何设置都在
karma.webpack.conf.js
中被覆盖
- 条目已删除,我想,Karam 无论如何都会覆盖它。
- 重要
devtool
设置为inline-source-map
- 结果是一场巨大的斗争,因为似乎外部源映射没有被拾取并且在我们设置为inline
配置之前,源映射不起作用。源映射不仅有助于代码覆盖,而且在测试失败和打印出错误信息时也有帮助——它将引用原始代码行。 - 最后,在进行覆盖时,将加载程序配置为排除 node_modules 和任何外部源,并排除测试本身
.babelrc 配置
{
"presets": [
["@babel/preset-env", { "modules": "commonjs" }],
"@babel/preset-react"
],
"plugins": [
"angularjs-annotate",
["@babel/plugin-proposal-decorators", {
"legacy": true
}],
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-syntax-import-meta",
["@babel/plugin-proposal-class-properties", {
"loose": true
}],
"@babel/plugin-proposal-json-strings",
"@babel/plugin-proposal-function-sent",
"@babel/plugin-proposal-export-namespace-from",
"@babel/plugin-proposal-numeric-separator",
"@babel/plugin-proposal-throw-expressions",
"@babel/plugin-proposal-export-default-from",
"@babel/plugin-proposal-logical-assignment-operators",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-do-expressions",
"@babel/plugin-proposal-function-bind"
]
}
应该可以使用您自己的 .babelrc
配置。 { "modules": "commonjs" }
出于某种原因对我们很重要,但现在不记得了
测试入口点 - src/main.tests.js
import '@babel/polyfill';
import './appConfig';
import './main';
const testsContext = require.context('.', true, /\.spec.js$/);
testsContext.keys().forEach(testsContext);
这与您的配置类似,尽管 angular 是在 main
中导入的,并且 anglar-mocks
是为每个测试导入的,因为我们有很多单独的模块