Подтвердить что ты не робот

Условно проигнорировать индивидуальные тесты с помощью кармы/жасмина

У меня есть некоторые тесты, которые не работают в PhantomJS, но не в других браузерах.

Я бы хотел, чтобы эти тесты игнорировались при запуске с помощью PhantomJS в моей задаче о часах (поэтому новые окна браузера не фокусируются, а perf быстрее), но в моей стандартной тестовой задаче и моем конвейере CI я хотите, чтобы все тесты выполнялись в Chrome, Firefox и т.д.

Я рассмотрел соглашение об именах файлов, например foo.spec.dont-use-phantom.js, и исключая их в моей конфигурации Karma, но это означает, что мне придется отделить отдельные тесты, которые попадают в их собственные файлы, отделяя их от их логических describe блокирует и имеет больше файлов со странными соглашениями об именах, как правило, сосать.

Короче:

Есть ли способ расширить Jasmine и/или Karma и каким-то образом аннотировать отдельные тесты, чтобы работать только с определенными конфигурациями?

4b9b3361

Ответ 1

Я могу поделиться своим опытом с этим.

В нашей среде у нас есть несколько тестов, работающих с разными браузерами и различными технологиями. Для того чтобы всегда запускать одни и те же комплекты на всех платформах и в браузерах, у нас есть вспомогательный файл, загруженный в карму (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();
  }
});

Пока он немного подробный, это сэкономит вам время на тот сценарий, с которым вы столкнулись.

В некоторых случаях вы можете использовать обнюхиватель пользовательского агента для обнаружения определенного типа браузера или версии - я знаю, что это плохая практика, но иногда нет другого способа.

Ответ 2

Функция ожидания поддержки жасмина.

Если вы вызываете функцию в ожидании в любом месте тела спецификации, независимо от ожиданий, спецификация будет отмечена как ожидающая.

Вы можете позвонить в ожидании непосредственно в тесте или в какой-либо другой функции, вызванной тестом.

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

Я думаю, что это чистое решение. В результатах теста вы можете увидеть количество завершенных и пропущенных тестов. Он более информативен по отношению к тесту на замещение по условиям.

Ответ 3

Самое простое решение, которое я вижу, - переопределить глобальные функции describe и it, чтобы заставить их принять третий необязательный аргумент, который должен быть логическим или функцией, возвращающей логическое значение - чтобы сообщить, действительно ли текущий пакет /spec должен быть выполнен. При переопределении мы должны проверить, разрешает ли этот третий необязательный аргумент на true, и если это так, то мы вызываем xdescribe/xit (или ddescribe/iit в зависимости от версии Jasmine), которые являются методами Жасмина пропустить пакет/спецификацию, istead оригинала describe/it. Этот блок должен быть выполнен перед тестами, но после того, как Жасмин включен на страницу. В 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() для describe и it, который будет делать довольно почти то же, что я описал выше. Он может выглядеть лучше, но его сложнее реализовать.

describe('foo', function () {

  it('bar', function () {
    // ...
  }).when(anything);      

}).when(something);

Если вы действительно заинтересованы в этом втором подходе, я буду счастлив сыграть с ним немного больше и попытаться реализовать цепочку .when().

Update:

Жасмин использует третий аргумент в качестве параметра тайм-аута (см. документы), поэтому мой пример кода заменяет эту функцию, что не совсем нормально. Мне нравится @milanlempera, а @MarcoCI лучше отвечает, мой кажется довольно хакивым и не интуитивным. В любом случае я попытаюсь обновить решение, чтобы не разорвать совместимость с функциями Jasmine по умолчанию.

Ответ 4

Попробуйте это. Я использую это решение в своих проектах.

it('should do something', function () {
    if (!/PhantomJS/.test(window.navigator.userAgent)) {
        expect(true).to.be.true;
    }
});

Это не будет запускать этот конкретный тест в PhantomJS, но будет запускаться в других браузерах.