有条件地忽略使用Karma/Jasmine的个别测试

有条件地忽略使用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块中分离出来,并拥有更多具

我有一些测试在PhantomJS中失败,但在其他浏览器中没有

我希望在我的watch任务中使用PhantomJS运行时忽略这些测试(这样新的浏览器窗口不会聚焦,性能会快一点),但在我的标准测试任务和CI管道中,我希望所有测试都在Chrome、Firefox等中运行

我考虑过一个文件命名约定,比如
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;
    }
});