我使用Istanbul
进行代码覆盖,但是覆盖率却很低,尤其是在Models
文件中。
考虑以下是模型文件:
ModelA.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
var app = require('../server')
var db = require('../db/dbConnection');
var config = require('../configs/config')
const Schema1 = new Schema({ 'configurations': [] });
exports.save = function (aa, data, callback) {
var logMeta = {
file: 'models/modelA',
function: 'save',
data: {},
error: {}
}
if (!aa) {
return callback('aa is required')
}
global.logs[aa].log('info', 'AA: ' + aa, logMeta);
db.connectDatabase(aa, function(error, mongoDB){
if(error){
logMeta.data['error'] = error
global.logs[aa].log('error', 'error', logMeta);
return callback(error)
}
const ModelA = mongoDB.model('bbb', cccc);
ModelA.findOneAndUpdate({}, data, {upsert: true, new: true, runValidators: true}, function(error ,result){
if (error) {
logMeta.data['error'] = error
global.logs[aa].log('error', 'error', logMeta);
}
else {
logMeta.data = {}
logMeta.data['result'] = JSON.parse(JSON.stringify(result))
global.logs[aa].log('info', 'result', logMeta);
}
callback(error, result);
});
})
}
TestA.js:
var should = require('should'),
sinon = require('sinon'),
ModelA= require("../models/ModelA");
describe('Model test', function () {
it('Should save Model', function (done) {
var todoMock = sinon.mock(new ModelA({'configurations': []}));
var todo = todoMock.object;
todoMock
.expects('save')
.yields(null, 'SAVED');
todo.save(function(err, result) {
todoMock.verify();
todoMock.restore();
should.equal('SAVED', result, "Test fails due to unexpected result")
done();
});
});
});
但是我得到的是代码覆盖率20
。所以我如何增加百分比:
也:
1。如果需要,我是否必须嘲笑db.connectDatabase
?
是否必须使用TestDb运行所有UnitTest?还是我必须assert
??
代码覆盖率将适用于单元测试或集成测试?
请分享您的想法。谢谢
答案 0 :(得分:0)
我一直在使用Istanbul
来100%的代码覆盖我的大多数客户端/服务器项目,因此我可能会找到您要的答案。
工作方式
每当您需要一些本地文件时,它就会被包装在各处,以了解您的代码是否可以访问其每个部分。
不仅需要的文件被污染,您的运行测试也受到污染。 但是,尽管很容易编写代码来覆盖正在运行的测试文件,但是模拟类及其代码可能永远不会执行。
todoMock.expects('save')
使用模拟函数覆盖
todo. save
并返回它。
如果Istanbul
污染了真实的save
方法,那么就不会达到该范围内的任何值,因此您实际上是在测试该模拟程序是否有效,而不是您的真实代码有效。
这应该回答您的问题:代码覆盖率将适用于单元测试或集成测试?
答案是它涵盖了代码,从代码覆盖的角度来看,这是您唯一感兴趣的内容。覆盖Sinon JS并不是没有目标。
无需断言...但是
一旦您了解了Istanbul
的工作原理,它就会自然而然地了解,无论您是否assert
都没有关系,重要的是您可以获取真实的代码和执行它。
声明只是预防失败的方法,并不是任何Istanbul
测试中本身有趣的机制。当您的断言失败时,您的测试也将执行,因此,让您知道事情不正常,并且无需继续测试其余代码(早期失败,更快的修复程序)对您很有帮助。
是否必须模拟db.connectDatabase
是的,至少对于您发布的代码。您可以将db
作为通用对象模拟物分配给global
上下文和expect
方法以进行调用,但是您也可以通过编写以下代码简化您的工作:
function createDB(err1, err2) {
return {
connectDatabase(aa, callback) {
callback(err1, {
model(name, value) {
return {
findOneAndUpdate($0, $1, $3, fn) {
fn(err2, {any: 'object'});
}
};
}
});
}
};
}
global.db = createDB(null, null);
您可以使用测试文件中的此代码创建全局db
,该行为在传递的错误数量上会相应地表现不同,从而使您能够以不同的期望多次运行同一测试文件。
如何多次运行同一测试
测试完成后,先delete require.cache[require.resolve('../test/file')]
,然后再require('../test/file')
。
根据需要执行多次。
有条件特征检测时
我通常会多次运行测试,以删除全局构造函数,以防它们带有后备补丁。我通常还会存储它们,以便以后将它们放回原处。
当代码很明显但不应到达
时如果您有if (err) process.exit(1);
,则很少希望到达代码的那部分。 Istanbul
可以理解各种注释,这些注释可以帮助您跳过部分测试,例如/* istanbul ignore if */
或ignore else
,甚至通用的ignore next
。
请考虑三思,如果只是您是懒惰,还是真的可以安全地跳过那一部分……我被错误处理的问题咬了好几次,这是灾难,因为发生的时间是您需要最多的代码来保持运行和/或为您提供所需的所有信息。
涵盖了什么?
也许您已经知道这一点,但是可以立即使用任何浏览器打开的coverage/lcov-report/index.html
文件将向您显示测试中未涵盖的所有部分。