有条件地忽略 Karma / Jasmine 的个别测试
Conditionally ignore individual tests with Karma / Jasmine
我有一些测试在 PhantomJS 中失败,但在其他浏览器中没有。
当 运行 在我的 watch 任务中使用 PhantomJS 时,我希望忽略这些测试(因此新浏览器 windows 不会获得焦点并且 perf 更快),但是在我的标准测试任务和我的 CI 管道,我希望 所有 测试到 Chrome、Firefox 等中的 运行...
我考虑过像 foo.spec.dont-use-phantom.js
这样的文件命名约定,并排除了我的 Karma 配置中的那些,但这意味着我必须将失败的单个测试分离到它们自己的文件中,将它们分开它们来自它们的逻辑 describe
块,并且拥有更多具有奇怪命名约定的文件通常会很糟糕。
简而言之:
有没有一种方法可以扩展 Jasmine and/or Karma 并以某种方式 注释 个别测试仅 运行 具有某些配置?
我看到的最简单的解决方案是覆盖全局函数 describe
和 it
让它们接受第三个可选参数,它必须是布尔值或返回布尔值的函数 - 到告诉当前 suite/spec 是否应该被执行。当覆盖时,我们应该检查这第三个可选参数是否解析为 true
,如果是,那么我们调用 xdescribe
/xit
(或 ddescribe
/iit
取决于 Jasmine 版本),这是 Jasmine 跳过 suite/spec 的方法,而不是原来的 describe
/it
。这个块必须在测试之前执行,但在 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
});
});
我也偶然发现 this issue 的想法是为 describe
和 it
添加一个链方法 .when()
,这几乎是一样的我已经在上面描述过了。它可能看起来更好,但实现起来有点困难。
describe('foo', function () {
it('bar', function () {
// ...
}).when(anything);
}).when(something);
如果您真的对第二种方法感兴趣,我会很乐意多尝试一下并尝试实现链 .when()
。
更新:
Jasmine 使用第三个参数作为超时选项 (see docs),因此我的代码示例正在替换此功能,这是不正确的。我更喜欢@milanlempera 和@MarcoCI 的回答更好,我的似乎有点老套而且不直观。我会尽快尝试更新我的解决方案,以免破坏与 Jasmine 默认功能的兼容性。
我可以分享我的经验。
在我们的环境中,我们有几个测试 运行 不同的浏览器和不同的技术。
为了 运行 在所有平台和浏览器上始终使用相同的套件,我们在 karma (helper.js
) 中加载了一个帮助文件,并在全局加载了一些功能检测功能。
即
function isFullScreenSupported(){
// run some feature detection code here
}
您也可以使用 Modernizr。
在我们的测试中,我们将内容包装在 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()
,或者在从测试调用的其他函数中调用。
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);
});
});
这里的工作示例:http://plnkr.co/edit/JZtAKALK9wi5PdIkbw8r?p=preview
我认为这是最纯粹的解决方案。在测试结果中,您可以看到完成和跳过的测试数。
试试这个。我在我的项目中使用这个解决方案。
it('should do something', function () {
if (!/PhantomJS/.test(window.navigator.userAgent)) {
expect(true).to.be.true;
}
});
这不会 运行 在 PhantomJS 中进行此特定测试,但会 运行 在其他浏览器中进行。
只需将要禁用的测试重命名为 xit(...)
function xit: A temporarily disabled it. The spec will report as
pending and will not be executed.
我有一些测试在 PhantomJS 中失败,但在其他浏览器中没有。
当 运行 在我的 watch 任务中使用 PhantomJS 时,我希望忽略这些测试(因此新浏览器 windows 不会获得焦点并且 perf 更快),但是在我的标准测试任务和我的 CI 管道,我希望 所有 测试到 Chrome、Firefox 等中的 运行...
我考虑过像 foo.spec.dont-use-phantom.js
这样的文件命名约定,并排除了我的 Karma 配置中的那些,但这意味着我必须将失败的单个测试分离到它们自己的文件中,将它们分开它们来自它们的逻辑 describe
块,并且拥有更多具有奇怪命名约定的文件通常会很糟糕。
简而言之:
有没有一种方法可以扩展 Jasmine and/or Karma 并以某种方式 注释 个别测试仅 运行 具有某些配置?
我看到的最简单的解决方案是覆盖全局函数 describe
和 it
让它们接受第三个可选参数,它必须是布尔值或返回布尔值的函数 - 到告诉当前 suite/spec 是否应该被执行。当覆盖时,我们应该检查这第三个可选参数是否解析为 true
,如果是,那么我们调用 xdescribe
/xit
(或 ddescribe
/iit
取决于 Jasmine 版本),这是 Jasmine 跳过 suite/spec 的方法,而不是原来的 describe
/it
。这个块必须在测试之前执行,但在 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
});
});
我也偶然发现 this issue 的想法是为 describe
和 it
添加一个链方法 .when()
,这几乎是一样的我已经在上面描述过了。它可能看起来更好,但实现起来有点困难。
describe('foo', function () {
it('bar', function () {
// ...
}).when(anything);
}).when(something);
如果您真的对第二种方法感兴趣,我会很乐意多尝试一下并尝试实现链 .when()
。
更新:
Jasmine 使用第三个参数作为超时选项 (see docs),因此我的代码示例正在替换此功能,这是不正确的。我更喜欢@milanlempera 和@MarcoCI 的回答更好,我的似乎有点老套而且不直观。我会尽快尝试更新我的解决方案,以免破坏与 Jasmine 默认功能的兼容性。
我可以分享我的经验。
在我们的环境中,我们有几个测试 运行 不同的浏览器和不同的技术。
为了 运行 在所有平台和浏览器上始终使用相同的套件,我们在 karma (helper.js
) 中加载了一个帮助文件,并在全局加载了一些功能检测功能。
即
function isFullScreenSupported(){
// run some feature detection code here
}
您也可以使用 Modernizr。
在我们的测试中,我们将内容包装在 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()
,或者在从测试调用的其他函数中调用。
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);
});
});
这里的工作示例:http://plnkr.co/edit/JZtAKALK9wi5PdIkbw8r?p=preview
我认为这是最纯粹的解决方案。在测试结果中,您可以看到完成和跳过的测试数。
试试这个。我在我的项目中使用这个解决方案。
it('should do something', function () {
if (!/PhantomJS/.test(window.navigator.userAgent)) {
expect(true).to.be.true;
}
});
这不会 运行 在 PhantomJS 中进行此特定测试,但会 运行 在其他浏览器中进行。
只需将要禁用的测试重命名为 xit(...)
function xit: A temporarily disabled it. The spec will report as pending and will not be executed.