关键词:
【中文标题】Karma Coverage + RequireJS:误导性覆盖报告【英文标题】:Karma Coverage + RequireJS: Misleading coverage reports 【发布时间】:2015-01-07 03:54:56 【问题描述】:今天我已将 Karma Coverage 集成到我现有的 RequireJS 应用程序中。我添加了 karma-requirejs 插件,并且能够成功获取覆盖率报告。
最初的报告非常好,几乎 100% 的覆盖率。当我仔细分析结果时,我注意到我的“src”文件夹中有很多丢失的文件,这导致了这个非常好的报告。
事实证明,覆盖只是对具有相应规范的“src”文件应用分析(因为我在该规范中使用了 require('someFileFromSrcFolder'))。
问题:有没有办法让coverage 分析“src”文件夹中的所有文件?
Karma-conf.js
module.exports = function (config)
config.set(
basePath: '../',
autoWatch: true,
singleRun: false,
frameworks: ['jasmine', 'requirejs'],
browsers: ['PhantomJS', 'Chrome'],
logLevel: config.LOG_ERROR,
files: [
pattern: 'vendor/**/*.js', included: false,
pattern: 'vendor/**/*.html', included: false,
pattern: 'src/**/*.js', included: false,
pattern: 'src/**/*.html', included: false,
pattern: 'tests/mock/**/*.js', included: false,
pattern: 'tests/**/*Specs.js', included: false,
'tests/test-require.js'
],
// list of files to exclude
exclude: [
'src/app-require.js'
],
reporters: ['progress', 'coverage'],
preprocessors:
'src/**/*.js': ['coverage']
);
;
Test-require.js
var allTestFiles = [];
var TEST_REGEXP = /Specs\.js$/;
Object.keys(window.__karma__.files).forEach(function (file)
if (TEST_REGEXP.test(file))
allTestFiles.push(file);
);
require.config(
baseUrl: '/base/',
paths:
...
,
deps: allTestFiles,
callback: window.__karma__.start(),
waitSeconds: 20
);
【问题讨论】:
【参考方案1】:我最近遇到了同样的问题。我的项目angular-require-lazy 中有一个解决方案,我将对其进行描述。虽然它需要很多定制的东西,但它最终还是可以工作的。
总结
-
预先检测您的代码,保持基线
让 Karma 服务器发送预先检测的源
与考虑基线的报告者一起收集覆盖结果
1。预仪表
首先,我确实没有设法使用coverage
预处理器。由于 RequireJS 动态加载源,现有的预处理器不足以满足我们的需求。相反,我首先使用自定义的 Grunt 插件在伊斯坦布尔手动运行仪器阶段:
(查看here)
module.exports = function(grunt)
grunt.registerMultiTask("instrument", "Instrument with istanbul", function()
var istanbul = require("istanbul"),
instrumenter,
options,
instrumenterOptions,
baselineCollector;
options = this.options(
);
if( options.baseline )
baselineCollector = new istanbul.Collector();
instrumenterOptions =
coverageVariable: options.coverageVariable || "__coverage__",
embedSource: options.embedSource || false,
preserveComments: options.preserveComments || false,
noCompact: options.noCompact || false,
noAutoWrap: options.noAutoWrap || false,
codeGenerationOptions: options.codeGenerationOptions,
debug: options.debug || false,
walkDebug: options.walkDebug || false
;
instrumenter = new istanbul.Instrumenter(instrumenterOptions);
this.files.forEach(function(f)
if( f.src.length !== 1 )
throw new Error("encountered src with length: " + f.src.length + ": " + JSON.stringify(f.src));
var filename = f.src[0],
code = grunt.file.read(filename, encoding: grunt.file.defaultEncoding),
result = instrumenter.instrumentSync(code, filename),
baseline,
coverage;
if( options.baseline )
baseline = instrumenter.lastFileCoverage();
coverage = ;
coverage[baseline.path] = baseline;
baselineCollector.add(coverage);
grunt.file.write(f.dest, result, encoding: grunt.file.defaultEncoding);
);
if( options.baseline )
grunt.file.write(options.baseline, JSON.stringify(baselineCollector.getFinalCoverage()), encoding: grunt.file.defaultEncoding);
);
;
它被用作:
grunt.initConfig(
instrument:
sources:
files: [
expand: true,
cwd: "..the base directory of your sources...",
src: ["...all your sources..."],
dest: "...where to put the instrumented files..."
],
options:
baseline: "build-coverage/baseline.json" // IMPORTANT!
,
...
为以后保留基线很重要。
如果不使用 Grunt,我认为您仍然可以从这段代码中获得灵感。实际上,伊斯坦布尔 API 非常适合手动工作,所以如果需要,请继续使用它。
2。配置 Karma 服务器以发送预检测文件
对于初学者,请配置预处理器以使用您的预检测文件(注意我们将使用自定义预处理器和报告器,代码在最后):
...
preprocessors:
'...all your sources...': 'preInstrumented'
,
preInstrumentedPreprocessor:
basePath: '!!!SAME AS GRUNT'S dest!!!',
stripPrefix: '...the base prefix to strip, same as Grunt's cwd...'
,
...
3。调整记者以使用基线
报道记者必须考虑基线。不幸的是,原始没有,所以我稍微调整了一下。配置是:
...
reporters: [
'progress', 'coverage'
],
coverageReporter:
type: 'lcov',
dir: 'build-coverage/report',
baseLine: '!!!SAME AS GRUNT'S options.baseline!!!'
,
...
代码
为了激活我的自定义 Karma 插件,我添加了这个:
plugins: [
...
require('./build-scripts/karma')
],
文件夹./build-scripts/karma
包含这些文件:
index.js:
module.exports =
"preprocessor:preInstrumented": ["factory", require("./preInstrumentedPreprocessor")],
"reporter:coverage": ["type", require("./reporter")]
;
preInstrumentedPreprocessor.js:
var path = require("path"),
fs = require("fs");
createPreInstrumentedPreprocessor.$inject = ["args", "config.preInstrumentedPreprocessor", "config.basePath", "logger", "helper"];
function createPreInstrumentedPreprocessor(args, config, basePath, logger, helper)
var STRIP_PREFIX_RE = new RegExp("^" + path.join(basePath, config.stripPrefix).replace(/\\/g, "\\\\"));
function instrumentedFilePath(file)
return path.join(basePath, config.basePath, path.normalize(file.originalPath).replace(STRIP_PREFIX_RE, ""));
return function(content, file, done)
fs.readFile(instrumentedFilePath(file), encoding:"utf8", function(err, instrumentedContent)
if( err ) throw err;
done(instrumentedContent);
);
;
module.exports = createPreInstrumentedPreprocessor;
reporter.js:
(请查看 this issue 了解让我“分叉”它的原因。)
// DERIVED FROM THE COVERAGE REPORTER OF KARMA, https://github.com/karma-runner/karma-coverage/blob/master/lib/reporter.js
var path = require('path');
var fs = require('fs');
var util = require('util');
var istanbul = require('istanbul');
var dateformat = require('dateformat');
var Store = istanbul.Store;
var BasePathStore = function(opts)
Store.call(this, opts);
opts = opts || ;
this.basePath = opts.basePath;
this.delegate = Store.create('fslookup');
;
BasePathStore.TYPE = 'basePathlookup';
util.inherits(BasePathStore, Store);
Store.mix(BasePathStore,
keys : function()
return this.delegate.keys();
,
toKey : function(key)
if (key.indexOf('./') === 0) return path.join(this.basePath, key);
return key;
,
get : function(key)
return this.delegate.get(this.toKey(key));
,
hasKey : function(key)
return this.delegate.hasKey(this.toKey(key));
,
set : function(key, contents)
return this.delegate.set(this.toKey(key), contents);
);
// TODO(vojta): inject only what required (config.basePath, config.coverageReporter)
var CoverageReporter = function(rootConfig, helper, logger)
var log = logger.create('coverage');
var config = rootConfig.coverageReporter || ;
var basePath = rootConfig.basePath;
var reporters = config.reporters;
var baseLine;
if (config.baseLine)
baseLine = JSON.parse(fs.readFileSync(path.join(basePath, config.baseLine), encoding:"utf8"));
if (!helper.isDefined(reporters))
reporters = [config];
this.adapters = [];
var collectors;
var pendingFileWritings = 0;
var fileWritingFinished = function() ;
function writeEnd()
if (!--pendingFileWritings)
// cleanup collectors
Object.keys(collectors).forEach(function(key)
collectors[key].dispose();
);
fileWritingFinished();
/**
* Generate the output directory from the `coverageReporter.dir` and
* `coverageReporter.subdir` options.
*
* @param String browserName - The browser name
* @param String dir - The given option
* @param String|Function subdir - The given option
*
* @return String - The output directory
*/
function generateOutputDir(browserName, dir, subdir)
dir = dir || 'coverage';
subdir = subdir || browserName;
if (typeof subdir === 'function')
subdir = subdir(browserName);
return path.join(dir, subdir);
this.onRunStart = function(browsers)
collectors = Object.create(null);
// TODO(vojta): remove once we don't care about Karma 0.10
if (browsers)
browsers.forEach(function(browser)
collectors[browser.id] = new istanbul.Collector();
);
;
this.onBrowserStart = function(browser)
var collector = new istanbul.Collector();
if( baseLine )
collector.add(baseLine);
collectors[browser.id] = collector;
;
this.onBrowserComplete = function(browser, result)
var collector = collectors[browser.id];
if (!collector)
return;
if (result && result.coverage)
collector.add(result.coverage);
;
this.onSpecComplete = function(browser, result)
if (result.coverage)
collectors[browser.id].add(result.coverage);
;
this.onRunComplete = function(browsers)
reporters.forEach(function(reporterConfig)
browsers.forEach(function(browser)
var collector = collectors[browser.id];
if (collector)
pendingFileWritings++;
var outputDir = helper.normalizeWinPath(path.resolve(basePath, generateOutputDir(browser.name,
reporterConfig.dir || config.dir,
reporterConfig.subdir || config.subdir)));
helper.mkdirIfNotExists(outputDir, function()
log.debug('Writing coverage to %s', outputDir);
var options = helper.merge(, reporterConfig,
dir : outputDir,
sourceStore : new BasePathStore(
basePath : basePath
)
);
var reporter = istanbul.Report.create(reporterConfig.type || 'html', options);
try
reporter.writeReport(collector, true);
catch (e)
log.error(e);
writeEnd();
);
);
);
;
this.onExit = function(done)
if (pendingFileWritings)
fileWritingFinished = done;
else
done();
;
;
CoverageReporter.$inject = ['config', 'helper', 'logger'];
// PUBLISH
module.exports = CoverageReporter;
这是很多代码,我知道。我希望有一个更简单的解决方案(有什么想法吗?)。无论如何,您可以查看它如何与 angular-require-lazy 一起进行实验。希望对你有帮助...
【讨论】:
是的,这是很多代码。我正在发布我能够得到的解决方案。你能试试看它是否适合你吗?无论如何,我给你的答案加一,因为它也解决了这个问题,非常感谢! 这其实是个好主意。我会更彻底地看一下 - 我是在尝试自己的项目时错过了它,还是有其他原因?【参考方案2】:好的,
在尝试了一点之后,我找到了一个似乎可以解决问题的解决方案。我仍然不确定这是否是最好的解决方案,但我会在这里发布我所做的,以便收集您的反馈。
基本上,我必须更改 test-require.js 中的加载机制,以默认包含我的所有包。更新后的 test-require.js 应如下所示:
更新了 Test-require.js
var allTestFiles = [];
var modules = [];
var TEST_REGEXP = /Specs\.js$/;
var SRC_REGEXP = /src\//;
var JS_REGEXP = /\.js$/;
/**
* This function converts a given js path to requirejs module
*/
var jsToModule = function (path)
return path.replace(/^\/base\//, '').replace(/\.js$/, '');
;
Object.keys(window.__karma__.files).forEach(function (file)
if (TEST_REGEXP.test(file))
allTestFiles.push(file);
else if (SRC_REGEXP.test(file) && JS_REGEXP.test(file))
modules.push(jsToModule(file));
);
var startTest = function ()
//loading all the existing requirejs src modules before
//triggering the karma test
require(modules, function ()
window.__karma__.start();
);
;
require.config(
baseUrl: '/base/',
paths:
....
,
// dynamically load all test files
deps: allTestFiles,
callback: startTest,
waitSeconds: 20
);
现在,当我运行测试测试时,覆盖范围包括所有 src 模块,我终于可以得到一致且准确的报告。
【讨论】:
将 karma-coverage 添加到 ember 测试
】将karma-coverage添加到ember测试【英文标题】:Addkarma-coveragetoembertest【发布时间】:2015-01-0910:25:49【问题描述】:我发现了这个非常棒的ember测试样本:https://github.com/toranb/ember-testing-example让它运行,但我无法让业力覆盖工作,这... 查看详情
Karma-Coverage 和伊斯坦布尔 HTML 报告未输出到预期目录
】Karma-Coverage和伊斯坦布尔HTML报告未输出到预期目录【英文标题】:Karma-CoverageandIstanbulHTMLreportnotoutputtoexpecteddirectory【发布时间】:2015-11-2902:04:34【问题描述】:我无法让伊斯坦布尔将其HTML报告输出到我的Karma配置中指定的目录... 查看详情
`Can not load "coverage"!` 尝试运行 Karma Coverage 时的消息
】`Cannotload"coverage"!`尝试运行KarmaCoverage时的消息【英文标题】:`Cannotload"coverage"!`messagewhentryingtorunKarmaCoverage【发布时间】:2016-09-1603:56:53【问题描述】:我提出这个问题的原因是因为我可以在***上找到的唯一Q/As... 查看详情
Karma Coverage + RequireJS:误导性覆盖报告
】KarmaCoverage+RequireJS:误导性覆盖报告【英文标题】:KarmaCoverage+RequireJS:Misleadingcoveragereports【发布时间】:2015-01-0703:54:56【问题描述】:今天我已将KarmaCoverage集成到我现有的RequireJS应用程序中。我添加了karma-requirejs插件,并且... 查看详情
KarmaJS 中的代码覆盖率过高,具有 karma-coverage 和 Jasmine
】KarmaJS中的代码覆盖率过高,具有karma-coverage和Jasmine【英文标题】:toohighCodeCoverageinKarmaJSwithkarma-coverage&Jasmine【发布时间】:2016-04-0214:23:07【问题描述】:我使用Jasmine作为我的AngularJS应用程序的测试框架。我在Grunt&KarmaJS... 查看详情
Karma-coverage 检查 JS 文件中的测试覆盖率,而不是 Angular 2 中的 TS
】Karma-coverage检查JS文件中的测试覆盖率,而不是Angular2中的TS【英文标题】:Karma-coveragecheckstestcoverageinJSfilesinsteadofTSinAngular2【发布时间】:2017-03-1621:33:11【问题描述】:我通过伊斯坦布尔检查TypeScript文件中的测试覆盖率。而且... 查看详情
为啥 Karma Coverage 实际显示“未涵盖的声明”?
】为啥KarmaCoverage实际显示“未涵盖的声明”?【英文标题】:WhyKarmaCoverageisshowing"statementnotcovered"whenitactuallyis?为什么KarmaCoverage实际显示“未涵盖的声明”?【发布时间】:2020-08-2720:42:30【问题描述】:我的业力覆盖率报... 查看详情
即使未达到测试覆盖率阈值,Karma-coverage 退出代码也始终为 0
】即使未达到测试覆盖率阈值,Karma-coverage退出代码也始终为0【英文标题】:Karma-coverageexitcodeisalways0evenwhentestcoveragethresholdisnotmet【发布时间】:2021-02-1921:43:31【问题描述】:我正在尝试为UI5应用程序构建一个gitlab-ci管道,以包... 查看详情
将来自 karma-coverage 的 istanbul 测试覆盖率与来自其他来源的覆盖率合并
】将来自karma-coverage的istanbul测试覆盖率与来自其他来源的覆盖率合并【英文标题】:Mergeistanbultestcoveragefromkarma-coveragewithcoveragefromothersources【发布时间】:2015-12-1917:26:51【问题描述】:我有几个使用伊斯坦布尔生成覆盖率报告的... 查看详情
使用 karma-coverage 和 angularjs 对每个源文件进行代码覆盖
】使用karma-coverage和angularjs对每个源文件进行代码覆盖【英文标题】:codecoverageforeachsourcefileusingkarma-coverageandangularjs【发布时间】:2016-01-2906:42:06【问题描述】:我正在尝试为Angular项目的单元测试设置代码覆盖率。但是它给了我... 查看详情
.karma+jasmine+karma-coverage
单元测试(模块测试)是开发者编写的一小段代码,用于检验被测代码的一个很小的、很明确的功能是否正确。通常而言,一个单元测试是用于判断某个特定条件(或者场景)下某个特定函数的行为。Karma是一个基于Node.js的JavaSc... 查看详情
Parse Karma-覆盖 |伊斯坦布尔报告
】ParseKarma-覆盖|伊斯坦布尔报告【英文标题】:ParseKarma-Coverage|Istanbulreport【发布时间】:2013-12-2105:29:09【问题描述】:我有一个JavaScript文件,它通过karma-coverage生成代码覆盖率报告。据我了解,Karma-coverage通过伊斯坦布尔生成报... 查看详情
Sonarqube 默认覆盖范围为 0,来自具有绝对路径的 Karma Coverage LCOV 文件
】Sonarqube默认覆盖范围为0,来自具有绝对路径的KarmaCoverageLCOV文件【英文标题】:Sonarqubedefaultcoverageto0fromKarmaCoverageLCOVfilewithabsolutepathjs【发布时间】:2017-04-1303:11:41【问题描述】:当我的lcov文件中的路径是绝对路径时,Sonar不... 查看详情
Angular Code Coverage 错误输出
】AngularCodeCoverage错误输出【英文标题】:AngularCodeCoveragewrongoutput【发布时间】:2015-01-1608:12:06【问题描述】:我的堆栈是:Angular.js、Karma、Karma-coverage(Istanbul)和Jasmine。我一直在对我的应用程序运行代码覆盖率分析,问题是我得... 查看详情
业力覆盖:对象没有方法 isIdentifierPart
...力覆盖:对象没有方法isIdentifierPart【英文标题】:Karma-coverage:ObjecthasnomethodisIdentifierPart【发布时间】:2015-10-2907:14:15【问题描述】:我想使用Karma对我的JQueryMobile项目进行代码覆盖,并使用QUnit或Jasmine进行测试。我已经安装了我... 查看详情
无法加载记者“coverage-istanbul”
】无法加载记者“coverage-istanbul”【英文标题】:Cannotloadreporter"coverage-istanbul"【发布时间】:2020-02-2916:25:16【问题描述】:我正在尝试使用https://webpack.js.org/loaders/istanbul-instrumenter-loader/运行代码覆盖率这里是karma.conf.jsvart... 查看详情
使用 karma 和 webpack 进行单元测试:_karma_webpack_ - 没有这样的文件或目录
...209:46:14【问题描述】:我正在尝试运行覆盖率(使用karma-coverage)和webpack(使用karma-webpack)的单元测试。测试按预期运行, 查看详情
如何使用 karma 在我的 Aurelia 应用程序中获得代码覆盖率结果?
...程序中获得代码覆盖率结果?【英文标题】:HowcanIgetcodecoverageresultsinmyAureliaappusingkarma?【发布时间】:2017-03-0223:39:48【问题描述】:我使用AureliaCLI(aunew)创建了一个Aurelia应用程序,并希望设置代码覆盖率(最好使用karma-coverage,... 查看详情