我有两个我想测试的功能;一个只在“现代浏览器”中运行的另一个只在“较旧”的浏览器中运行。
我使用Jasmine作为我的测试框架和Karma来运行我的测试。 Karma将推出许多运行所有测试的浏览器。
我的问题是在所有浏览器中测试我的所有功能会导致某些测试失败。例如,在IE8中测试时,测试应该只在现代浏览器中运行的函数将会失败。
要测试的代码:
function getStuffFromSmartBrowser() {
return 'foo';
}
function getStuffFromNotSoSmartBrowser() {
return 'bar';
}
if ('intelligence' in browser) {
getStuffFromSmartBrowser();
} else {
getStuffFromNotSoSmartBrowser();
}
原始测试代码:
describe("A suite", function () {
it("for smart browsers", function () {
expect(getStuffFromSmartBrowser()).toEqual('foo');
});
});
describe("A suite", function () {
it("for not so smart browsers", function () {
expect(getStuffFromNotSoSmartBrowser()).toEqual('bar');
});
});
在这些测试用例中,一种测试将在一种类型的浏览器中失败,而另一种测试在另一种类型的浏览器中将失败。
替代测试代码:
describe("A suite", function () {
if ('intelligence' in browser) {
it("for smart browsers", function () {
expect(getStuffFromSmartBrowser()).toEqual('foo');
});
} else {
it("for not so smart browsers", function () {
expect(getStuffFromNotSoSmartBrowser()).toEqual('bar');
});
}
});
替代测试代码在所有经过测试的浏览器中运行良好。
问题:
A - 在测试中使用条件语句是一种好习惯吗?
B - 如果没有,那会是更好的方法吗?
答案 0 :(得分:10)
将测试代码中的条件置于中通常被认为是不好的做法。在测试代码之外稍微可以接受,并且在缺少通过浏览器选择测试规范的内置机制的情况下,您的解决方案可能是最简单的。但是,您将单元测试与特定于浏览器的实现相结合。
“更好”的方法是将您的浏览器特定代码隐藏在单个功能背后,并使用功能检测来执行multiple dispatch。
function getStuff() {
if (browserIsSmart()) {
return getStuffFromSmartBrowser();
}
else {
return getStuffFromNotSoSmartBrowser();
}
}
function browserIsSmart() {
return ('intelligence' in browser); // Or whatever
}
这里变得凌乱。您的两个函数具有不同的返回值。理想情况下,您需要为所有相关函数提供相同的返回值,但这并不总是很简单。例如,IE8中的textarea选择使用与现代浏览器中的textarea选择完全不同的对象。有时您可以隐藏详细信息(例如,使用Strategy Pattern),有时您不能。
如果你不能保持清洁,那就明白了。