Javascript expect()没有实际的期望
问题: 最近,在回顾我们现有的测试代码库时,我注意到当使用Javascript expect()没有实际的期望,javascript,testing,jasmine,protractor,end-to-end,Javascript,Testing,Jasmine,Protractor,End To End,问题: 最近,在回顾我们现有的测试代码库时,我注意到当使用expect()时,在没有“匹配”部分的情况下出现了一种危险的键入/错误: 我很确定toEqual()应该在这里使用: expect(page.filters.fromDateLabel.getText()).toEqual("After"); 问题是在这种情况下,jasmine不会辜负期望值(很明显,因为实际上没有期望值)。这让我们遇到了一个更严重的问题——在一个测试用例中没有实际测试过任何东西——它在没有任何期望的情况下通过了。我们
expect()
时,在没有“匹配”部分的情况下出现了一种危险的键入/错误:
我很确定toEqual()
应该在这里使用:
expect(page.filters.fromDateLabel.getText()).toEqual("After");
问题是在这种情况下,jasmine
不会辜负期望值(很明显,因为实际上没有期望值)。这让我们遇到了一个更严重的问题——在一个测试用例中没有实际测试过任何东西——它在没有任何期望的情况下通过了。我们对所测试的东西有一种错误的感觉
问题:
我想尽快抓住这些错误。你认为我应该如何处理这个问题
想法:
- 如果测试用例中没有任何期望,那么它会以某种方式失败(不确定
是否有类似的内置功能)jasmine
- “修补”expect(),并在“expect”部分未调用任何内容时发出警告/引发错误
- 使用静态代码分析-定义自定义规则
expect
返回的期望,并创建一个代理,跟踪是否曾经使用过期望的任何属性:
var unusedExpectations = new Set();
var originalExpect = window.expect; // Should be empty after every spec
var expect = function() {
var rawExpectation = originalExpect.apply(this, arguments);
unusedExpectations.add(rawExpectation); // Assume unused until used
// Traverse expectation and its prototypes, copying all properties to
// our proxy object. (Note that this becomes much simpler if you have
// ES6 Proxy in your environment.)
var proxy = {}
for(var proto = rawExpectation; proto; proto = proto.__proto__) {
Object.getOwnPropertyNames(proto).forEach(function(prop) {
if(Object.getOwnPropertyDescriptor(proxy, prop))
return;
Object.defineProperty(
proxy, prop, {
get: function() {
// Aha! Somebody used this expectation for _something_.
unusedExpectations.delete(rawExpectation);
return rawExpectation[prop];
}
}
);
});
}
return proxy;
}
把它放在一个地方,在你的规格中隐藏Jasmine的expect
,然后:
beforeEach(function() {
unusedExpectations.clear();
});
afterEach(function() {
expect(unusedExpectations.size).toEqual(0);
});
注意事项:
expect(foo).toBeFalsy代码>(缺少参数)
expect(foo).toString()
可以添加代码来检查堆栈跟踪并提取有问题的
expect()
,但我认为标记哪个规范有未使用的expect()
就足够了。答案中提供的自定义ESLint规则现在是1.6.0的一部分:
旧答案: 以下是我最后得出的结论:
module.exports = function (context) {
return {
// checking "expect()" arguments
CallExpression: function (node) {
if (node.callee.name === 'expect') {
if (node.arguments.length > 1) {
context.report(node, 'More than one argument passed to expect()')
} else if (node.arguments.length === 0) {
context.report(node, 'No arguments passed to expect()')
}
}
},
// nothing called on "expect()"
'CallExpression:exit': function (node) {
if (node.callee.name === 'expect' && node.parent.type === 'ExpressionStatement') {
context.report(node, 'Nothing called on expect()')
}
}
}
}
它检查三件事:
- 传递给
expect()
- 未将任何参数传递给
expect()
expect()
expect()
用法示例:
expect(page.filters.fromDateLabel.getText(), "After");
expect("After");
expect();
至于选项#1,实际上,[
ESLint插件jasmine
]已经实现了一个非常相关和有用的ESLint
规则,并将其开源:
arguments.length>1
@Phil yup制定了一个自定义的ESLint规则(答案中提供),则覆盖期望抛出错误会更简单。谢谢参与!这是一个有趣的邪恶想法!:)我一定会在实践中尝试的!我还发布了选项1和选项3的解决方案——我想我们现在已经有了一个完整的画面,包括所有不同的方法。谢谢
expect(page.filters.fromDateLabel.getText(), "After");
expect("After");
expect();