Условно проигнорировать индивидуальные тесты с помощью кармы/жасмина
У меня есть некоторые тесты, которые не работают в PhantomJS, но не в других браузерах.
Я бы хотел, чтобы эти тесты игнорировались при запуске с помощью PhantomJS в моей задаче о часах (поэтому новые окна браузера не фокусируются, а perf быстрее), но в моей стандартной тестовой задаче и моем конвейере CI я хотите, чтобы все тесты выполнялись в Chrome, Firefox и т.д.
Я рассмотрел соглашение об именах файлов, например foo.spec.dont-use-phantom.js
, и исключая их в моей конфигурации Karma, но это означает, что мне придется отделить отдельные тесты, которые попадают в их собственные файлы, отделяя их от их логических describe
блокирует и имеет больше файлов со странными соглашениями об именах, как правило, сосать.
Короче:
Есть ли способ расширить Jasmine и/или Karma и каким-то образом аннотировать отдельные тесты, чтобы работать только с определенными конфигурациями?
Ответы
Ответ 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, но будет запускаться в других браузерах.