有条件地忽略使用Karma/Jasmine的个别测试
我有一些测试在PhantomJS中失败,但在其他浏览器中没有 我希望在我的watch任务中使用PhantomJS运行时忽略这些测试(这样新的浏览器窗口不会聚焦,性能会快一点),但在我的标准测试任务和CI管道中,我希望所有测试都在Chrome、Firefox等中运行 我考虑过一个文件命名约定,比如有条件地忽略使用Karma/Jasmine的个别测试,jasmine,karma-runner,karma-jasmine,Jasmine,Karma Runner,Karma Jasmine,我有一些测试在PhantomJS中失败,但在其他浏览器中没有 我希望在我的watch任务中使用PhantomJS运行时忽略这些测试(这样新的浏览器窗口不会聚焦,性能会快一点),但在我的标准测试任务和CI管道中,我希望所有测试都在Chrome、Firefox等中运行 我考虑过一个文件命名约定,比如foo.spec.dont-use-phantom.js,并排除了我的Karma配置中的那些,但这意味着我必须将失败的单个测试分离到它们自己的文件中,将它们从逻辑descripe块中分离出来,并拥有更多具
foo.spec.dont-use-phantom.js
,并排除了我的Karma配置中的那些,但这意味着我必须将失败的单个测试分离到它们自己的文件中,将它们从逻辑descripe
块中分离出来,并拥有更多具有奇怪命名约定的文件通常会很糟糕
简言之:
是否有一种方法可以扩展Jasmine和/或Karma,并以某种方式注释单个测试,使其仅在特定配置下运行?我看到的最简单的解决方案是覆盖全局函数
description
和it
,使它们接受第三个可选参数,它必须是一个布尔值或返回布尔值的函数-以指示是否应执行当前套件/规范。重写时,我们应该检查第三个可选参数是否解析为true
,如果解析为true,则调用xdescripe
/xit
(或ddescribe
/iit
,具体取决于Jasmine版本),这是Jasmine跳过套件/规范的方法,是原始description
/的istead。此块必须在测试之前执行,但在页面中包含Jasmine之后执行。在Karma中,只需将此代码移动到一个文件中,并在Karma.conf.js
中的测试文件之前包含它。代码如下:
(function (global) {
// save references to original methods
var _super = {
describe: global.describe,
it: global.it
};
// override, take third optional "disable"
global.describe = function (name, fn, disable) {
var disabled = disable;
if (typeof disable === 'function') {
disabled = disable();
}
// if should be disabled - call "xdescribe" (or "ddescribe")
if (disable) {
return global.xdescribe.apply(this, arguments);
}
// otherwise call original "describe"
return _super.describe.apply(this, arguments);
};
// override, take third optional "disable"
global.it = function (name, fn, disable) {
var disabled = disable;
if (typeof disable === 'function') {
disabled = disable();
}
// if should be disabled - call "xit" (or "iit")
if (disable) {
return global.xit.apply(this, arguments);
}
// otherwise call original "it"
return _super.it.apply(this, arguments);
};
}(window));
和使用示例:
describe('foo', function () {
it('should foo 1 ', function () {
expect(true).toBe(true);
});
it('should foo 2', function () {
expect(true).toBe(true);
});
}, true); // disable suite
describe('bar', function () {
it('should bar 1 ', function () {
expect(true).toBe(true);
});
it('should bar 2', function () {
expect(true).toBe(true);
}, function () {
return true; // disable spec
});
});
我还偶然发现了在哪里添加链方法。when()
用于description
和it
,这与我上面描述的方法基本相同。它看起来可能更好,但实施起来有点困难
describe('foo', function () {
it('bar', function () {
// ...
}).when(anything);
}).when(something);
如果您真的对第二种方法感兴趣,我很乐意再多玩一点,并尝试实现chain.when()
更新:
Jasmine使用第三个参数作为超时选项(),所以我的代码示例将替换此功能,这是不正确的。我更喜欢@milanlempera和@MarcoCI的答案,我的答案似乎有点粗糙,不直观。我会尽快更新我的解决方案,不会破坏与Jasmine默认功能的兼容性。我可以分享我的经验
在我们的环境中,我们有几个使用不同浏览器和不同技术运行的测试。
为了在所有平台和浏览器上始终运行相同的套件,我们在karma(helper.js
)中加载了一个helper文件,并全局加载了一些功能检测函数
即
您也可以使用它
在我们的测试中,我们将事物包装在if/else
块中,如下所示:
it('should work with fullscreen', function(){
if(isFullScreenSupported()){
// run the test
}
// don't do anything otherwise
});
或用于异步测试
it('should work with fullscreen', function(done){
if(isFullScreenSupported()){
// run the test
...
done();
} else {
done();
}
});
虽然有点冗长,但它会为您所面临的场景节省时间
在某些情况下,您可以使用用户代理嗅探来检测特定的浏览器类型或版本-我知道这是一种不好的做法,但有时实际上没有其他方法。Jasmine支持pending()
函数
如果调用规范正文中的任何地方的pending()
,无论期望值如何,规范都将标记为pending
您可以在测试中直接调用pending()
,也可以在从测试调用的其他函数中调用
function skipIfCondition() {
pending();
}
function someSkipCheck() {
return true;
}
describe("test", function() {
it("call pending directly by condition", function() {
if (someSkipCheck()) {
pending();
}
expect(1).toBe(2);
});
it("call conditionally skip function", function() {
skipIfCondition();
expect(1).toBe(3);
});
it("is executed", function() {
expect(1).toBe(1);
});
});
此处的工作示例:
我认为这是最纯粹的解决办法。在测试结果中,您可以看到已完成和跳过测试的计数。试试这个。我正在我的项目中使用此解决方案
it('should do something', function () {
if (!/PhantomJS/.test(window.navigator.userAgent)) {
expect(true).to.be.true;
}
});
这不会在PhantomJS中运行此特定测试,但会在其他浏览器中运行。只需将要禁用的测试从(…)重命名为xit(…)
函数xit:临时禁用它的函数。规范将报告为
挂起,将不会执行
伟大的我用它来禁止fdescribe和fit-in-build-env。只需覆盖fdescribe和fit并抛出异常。这种方法不适用于量角器,因为由于响应,规范将被标记为失败,但这实际上并不能解决问题。当我问这个问题时,我正在寻找一种有条件地跳过测试的方法xit
无条件跳过测试。
it('should do something', function () {
if (!/PhantomJS/.test(window.navigator.userAgent)) {
expect(true).to.be.true;
}
});