Как программно пропустить тест в мокко?

149

У меня есть код, в котором определенные тесты всегда терпят неудачу в среде CI. Я хотел бы отключить их в зависимости от условий окружающей среды.

Как программно пропустить тест в мокко во время выполнения?

Gajus
источник
3
Программный пропуск теста описанthis.skip() в ответах mochajs.org/#inclusive-tests и @ zatziky ниже. Остальные ответы устарели для Mocha v3 +
Патрик
1
description.skip ('description', () => {}) / describe.only ('description', () => {}) / it.skip ('description', () => {}) / it. only ('description', () => {})
июнь 711,
любой принятый ответ?
Пол Руни

Ответы:

172

Вы можете пропустить тесты, поместив x перед блоком description или it или поставив .skipпосле него.

xit('should work', function (done) {});

describe.skip('features', function() {});

Вы также можете запустить одиночный тест, поместив .onlyна него значок. например

describe('feature 1', function() {});
describe.only('feature 2', function() {});
describe('feature 3', function() {});

В этом случае будет работать только блок функции 2.

Кажется, не существует способа программно пропустить тесты, но вы могли бы просто выполнить какую-то проверку в beforeEachинструкции и запустить тест только в том случае, если был установлен флаг.

beforeEach(function(){
    if (wrongEnvironment){
        runTest = false
    }
}

describe('feature', function(){
    if(runTest){
         it('should work', function(){
            // Test would not run or show up if runTest was false,
         }
    }
}
KJ3
источник
10
Ваша вторая попытка решения не сработает, потому что порядок выполнения не тот, который вы думаете. Когда beforeEachвызов выполняется, Mocha записывает анонимную функцию («ловушку») для будущего использования, при выполнении describeвызова Mocha немедленно выполняет переданную ему анонимную функцию. Таким образом, к моменту if (runTest)выполнения beforeEach хук не сработает.
Луи
27
Как этот ответ получил 27 голосов? Вопрос касается программного пропуска тестов, поэтому добавление «.skip» или «.only» не помогает. Затем он явно говорит, что вы не можете делать то, что хочет сделать OP, несмотря на то, что другие ответы говорят вам, как это сделать.
Грэм Перроу,
3
Не сработает, это не ответ на вопрос, вместо этого см. Ответ @Gajus
NorTicUs
1
Этот ответ имеет значение для другого вопроса, который здесь не задавался. Я не в силах что-либо изменить здесь. См. Ответ this.skip ().
Эндрю Мартинес
3
это не ответ на вопрос
Инго Реннер
118

Используйте skip()функцию Mocha

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

Вот пример использования среды выполнения:

it('should only test in the correct environment', function() {
  if (/* check test environment */) {
    // make assertions
  } else {
    this.skip();
  }
});
Gajus
источник
16
Читателям может быть интересно узнать, что это помечает все describeкак пропущенное (т.е. все тесты в describeсписке пропускаются).
Луи
Документация Mocha по «ожидающим тестам»: mochajs.org/#pending-tests
lasec0203
description.skip ('description', () => {}) / describe.only ('description', () => {}) / it.skip ('description', () => {}) / it. only ('description', () => {})
июнь 711,
Я не понимаю, почему такой ответ получил поддержку. это хак - и не прелестный.
chenop
2
фактическая документация mochajs.org/#inclusive-tests , это ни в коем случае не взлом, а правильный метод исключения некоторых тестов на основе настроек времени выполнения. т.е. он точно отвечает на исходный вопрос. Спасибо @xavdid
WowPress.host
44

Этот ответ работает для ES6 .

Вместо того:

describe('your describe block', () => {

Вы хотите:

(condition ? describe : describe.skip)('your describe block', () => {

Это условно пропускает все тесты в блоке описания, ЕСЛИ условие ложно.

Или вместо:

it('your it block', () => {

Вы хотите:

(condition ? it : it.skip)('your it block', () => {

Это условно пропускает один тест, ЕСЛИ условие ложно.

danday74
источник
4
Я понимаю то, что вы предлагаете, но сначала вам нужно определить контекстное описание следующим образом: const contextualDescribe = shouldAvoidTests ? describe.skip : describe затем вы можете его использовать: contextualDescribe('your it block', () => {
Сер,
3
@Ser Чтобы попасть в единственную строку, я использовал что-то вроде этого:(condition ? describe : describe.skip)('your describe block', () => {
joshden
Как сделать это асинхронно? Мне нужно найти условие пропуска на основе флага redis, который является асинхронной операцией (мы храним флаги функций в redis).
Патрик Финниган
было некоторое время, но у ive была такая потребность и раньше, я думаю, что я просто обернул все вещи мокко в функцию, которая была вызвана после завершения асинхронного обратного вызова - не могу вспомнить точные детали
danday74
1
Использование стрелочных функций с mocha не рекомендуется: mochajs.org/#arrow-functions Просто передайте functionили, async functionа затем вы можете вызывать по this.skip()мере необходимости, возможно, после выполнения некоторой асинхронной операции, чтобы проверить, нужно ли вам запускать тест.
Джейсон Хётгер,
33

Я использую пропуск времени выполнения из Mocha для того же сценария, который вы описываете. Это копипаст из документов :

it('should only test in the correct environment', function() {
  if (/* check test environment */) return this.skip();

  // make assertions
});

Как видите, тест пропускается в зависимости от среды. Мое собственное состояние такое if(process.env.NODE_ENV === 'continuous-integration').

Amio.io
источник
2
Согласовано! Может ли быть одним лайнером, сделав, возможно, ранний возврат? Нравится: if (/* skipTestCondition */) return this.skip();- редактировать: работает: D
SidOfc
16

чтобы пропустить тесты, используйте describe.skipилиit.skip

describe('Array', function() {
  it.skip('#indexOf', function() {
    // ...
  });
});

включить тесты, которые вы могли бы использовать, describe.onlyилиit.only


describe('Array', function() {
  it.only('#indexOf', function() {
    // ...
  });
});

Больше информации на https://mochajs.org/#inclusive-tests

lfender6445
источник
6

Это зависит от того, как вы хотите программно пропустить тест. Если условия пропуска могут быть определены до запуска любого тестового кода, вы можете просто вызвать itили по it.skipмере необходимости в зависимости от условия. Например, это приведет к пропуску некоторых тестов, если для переменной среды ONEустановлено любое значение:

var conditions = {
    "condition one": process.env["ONE"] !== undefined
    // There could be more conditions in this table...
};

describe("conditions that can be determined ahead of time", function () {
    function skip_if(condition, name, callback) {
        var fn = conditions[condition] ? it.skip: it;
        fn(name, callback);
    };

    skip_if("condition one", "test one", function () {
        throw new Error("skipped!");
    });

    // async.
    skip_if("condition one", "test one (async)", function (done) {
        throw new Error("skipped!");
    });

    skip_if("condition two", "test two", function () {
        console.log("test two!");
    });

});

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

describe("conditions that can be determined at test time", function () {
    var conditions = {};
    function skip_if(condition, name, callback) {
        if (callback.length) {
            it(name, function (done) {
                if (conditions[condition])
                    done();
                else
                    callback(done);
            });
        }
        else {
            it(name, function () {
                if (conditions[condition])
                    return;
                callback();
            });
        }
    };

    before(function () {
        conditions["condition one"] = true;
    });

    skip_if("condition one", "test one", function () {
        throw new Error("skipped!");
    });

    // async.
    skip_if("condition one", "test one (async)", function (done) {
        throw new Error("skipped!");
    });

    skip_if("condition two", "test two", function () {
        console.log("test two!");
    });

});

В то время как в моем первом примере тесты помечались как формально пропущенные (также известные как «ожидающие»), метод, который я только что показал, просто не будет выполнять фактический тест, но тесты не будут отмечены как формально пропущенные. Они будут отмечены как пройденные. Если вы абсолютно хотите, чтобы они были пропущены, я не знаю другого способа получить доступ к частям, которые, собственно, не являются частью API тестирования:

describe("conditions that can be determined at test time", function () {
    var condition_to_test = {}; // A map from condition names to tests.
    function skip_if(condition, name, callback) {
        var test = it(name, callback);
        if (!condition_to_test[condition])
            condition_to_test[condition] = [];
        condition_to_test[condition].push(test);
    };

    before(function () {
        condition_to_test["condition one"].forEach(function (test) {
            test.pending = true; // Skip the test by marking it pending!
        });
    });

    skip_if("condition one", "test one", function () {
        throw new Error("skipped!");
    });

    // async.
    skip_if("condition one", "test one (async)", function (done) {
        throw new Error("skipped!");
    });

    skip_if("condition two", "test two", function () {
        console.log("test two!");
    });

});
Луи
источник
4

Я не уверен, можно ли это квалифицировать как «программный пропуск», но для того, чтобы выборочно пропустить некоторые конкретные тесты для нашей среды CI, я использую функцию тегов Mocha ( https://github.com/mochajs/mocha/wiki/Tagging ). В сообщениях describe()или it()вы можете добавить тег, например @ no-ci. Чтобы исключить эти испытания, можно определить специфический «CI целевой» в вашем package.json и использования --grepи --invertпараметров , как:

"scripts": {
  "test": "mocha",
  "test-ci" : "mocha --reporter mocha-junit-reporter --grep @no-ci --invert"
}
Мартин
источник
Это один из способов пропустить тесты. Небольшой пример был бы действительно полезен. Но я определенно согласен с тем, что ссылка, которой вы поделились, содержит пример в самом начале. @martin
Кришна Правин
3

Мы можем написать красивую чистую функцию-оболочку для условного запуска тестов следующим образом:

function ifConditionIt(title, test) {
  // Define your condition here
  return condition ? it(title, test) : it.skip(title, test);
}

Затем это может потребоваться и использоваться в ваших тестах следующим образом:

ifConditionIt('Should be an awesome test', (done) => {
  // Test things
  done();
});
dcr24
источник
Я думаю, что это, безусловно, самое элегантное решение, представленное здесь. Его можно легко расширить для выполнения более сложной логики, и он имеет дополнительный бонус, заключающийся в том, что пропущенные таким образом тесты помечаются как пропущенные в отчете об испытаниях
Джошуа Эванс,
2

Вы можете использовать мой пакет mocha-accept для программного пропуска тестов, но только вне тестов. Вы используете это так:

assuming(myAssumption).it("does someting nice", () => {});

Mocha-accept будет запускать ваш тест только тогда , когда он myAssumptionесть true, иначе он пропустит его (используя it.skip) с приятным сообщением.

Вот более подробный пример:

describe("My Unit", () => {
    /* ...Tests that verify someAssuption is always true... */

    describe("when [someAssumption] holds...", () => {
        let someAssumption;

        beforeAll(() => {
            someAssumption = /* ...calculate assumption... */
        });

        assuming(someAssumption).it("Does something cool", () => {
            /* ...test something cool... */
        });
    });
});

Таким образом можно избежать каскадных сбоев. Скажем, тест "Does something cool"всегда будет терпеть неудачу, если какое-то предположение не выполняется - но это предположение уже было проверено выше (в Tests that verify someAssuption is always true").

Таким образом, ошибка теста не дает вам никакой новой информации. Фактически, это даже ложноположительный результат: тест не прошел, потому что «что-то классное» не сработало, а потому, что предварительное условие для теста не было выполнено. с mocha-assumeвами часто можно избежать таких ложных срабатываний.

Дэвид Танзер
источник
Это действительно круто, грустно, что проект кажется заброшенным ...
Виктор Шредер
@ VictorSchröder Что ж, у меня создалось впечатление, что никто им не пользуется. Если бы у меня было время, возможно, я постараюсь улучшить его в ближайшие несколько недель. Можете ли вы открыть вопрос на github и сказать мне, что бы вы хотели увидеть?
Дэвид Танзер
Я еще не использую его, @ Дэвид Танзер, я только что нашел вашу идею действительно крутой . Я вижу, что довольно много занимаюсь подготовкой к тестам и условным пропуском, и такой интерфейс намного удобнее. Мне все еще нужно попробовать, но я полагаю, что было бы здорово иметь возможность связать несколько предположений и поддерживать асинхронные функции в качестве предположений. Может все это уже поддерживается, не проверял.
Виктор Шредер,
1
Однако со вторым примером в этом ответе есть проблема. Работа beforeAllловушки не гарантируется, пока не будут собраны все тесты. На самом деле, скорее всего, он запустится только после этого, но в этом случае assuming(someAssumption)он уже получил бы начальное (неопределенное) значение. Эту часть также необходимо обернуть функцией, чтобы добиться желаемого эффекта.
Виктор Шредер,
1

На самом деле это не использование функций мокко, а скорее настройка его для получения желаемого поведения.

Я хотел пропустить любое последующее «это» в моих тестах на транспортир мокко, и одно «оно» не удалось. Это было связано с тем, что после того, как один шаг теста не пройден, почти наверняка остальное не удастся, и это может занять много времени и перегружать сервер сборки, если они используют браузер, ожидая появления элементов на странице и т. Д.

При запуске стандартных тестов мокко (не транспортира) это может быть достигнуто с помощью глобальных хуков beforeEach и afterEach, прикрепив флаг skipSubsequent к родительскому элементу теста (описать) следующим образом:

    beforeEach(function() {
      if(this.currentTest.parent.skipSubsequent) {
            this.skip();
      }
    }); 


    afterEach(function() {
      if (this.currentTest.state === 'failed') {
        this.currentTest.parent.skipSubsequent = 'true'
      }
    })

При попытке сделать это с транспортиром и мокко он изменился, и приведенный выше код не работает. Вы получаете сообщение об ошибке, такое как «вызов ошибки done ()», и транспортир останавливается.

Вместо этого я получил код ниже. Не самое красивое, но в итоге реализация оставшихся тестовых функций заменяется this.skip (). Это, вероятно, перестанет работать, если / когда внутреннее устройство мокко изменится с более поздними версиями.

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

beforeEach(function() {

    var parentSpec = this.currentTest.parent;

    if (!parentSpec.testcount) {
        parentSpec.testCount = parentSpec.tests.length;
        parentSpec.currentTestIndex = 0;
    } else {
        parentSpec.currentTestIndex = parentSpec.currentTestIndex + 1;
    }

    if (parentSpec.skipSubsequent) {

        parentSpec.skipSubsequent = false;
        var length = parentSpec.tests.length;
        var currentIndex = parentSpec.currentTestIndex;

        for (var i = currentIndex + 1; i < length; i++) {
            parentSpec.tests[i].fn = function() {
                this.skip();
            };
        }
    }
});


afterEach(function() {
    if (this.currentTest.state === 'failed') {
        this.currentTest.parent.skipSubsequent = 'true'
    }
});
Пол Сильвестр
источник
0

Скажем, я хотел бы пропустить параметризованный тест, если бы мое описание теста содержало строку «foo», я бы сделал следующее:

// Skip parametrized test if description contains the string "foo"
(test.description.indexOf("foo") === -1 ? it : it.skip)("should test something", function (done) {
    // Code here
});

// Parametrized tests
describe("testFoo", function () {
        test({
            description: "foo" // This will skip
        });
        test({
            description: "bar" // This will be tested
        });
});

В вашем случае я считаю, что если вы хотите проверить переменные среды, вы можете использовать NodeJS:

process.env.ENV_VARIABLE

Например (Предупреждение: я не тестировал этот фрагмент кода!), Может быть что-то вроде этого:

(process.env.NODE_ENV.indexOf("prod") === -1 ? it : it.skip)("should...", function(done) {
    // Code here
});

Где вы можете установить ENV_VARIABLE как то, что вы отключили, и, используя это значение, пропустить или запустить тест. (К вашему сведению, документация для NodeJS process.env находится здесь: https://nodejs.org/api/process.html#process_process_env )

Я не буду полностью доверять первой части этого решения, я нашел и протестировал ответ, и он отлично сработал, чтобы пропустить тесты на основе простого условия через этот ресурс: https://github.com/mochajs/mocha/issues / 591

Надеюсь это поможет! :)

Рубикон
источник
-2

Как @danielstjules отвеченного здесь есть способ , чтобы пропустить тест. @author этой темы скопировал ответ из обсуждения mochajs на github.com, но нет информации, в какой версии mocha он доступен.

Я использую модуль grunt-mocha-test для интеграции функциональности теста мокко в свой проект. Переходим к последней (на данный момент) версии - 0.12.7, принеси мне версию мокко 2.4.5 с реализацией this.skip ().

Итак, в моем package.json

  "devDependencies": {
    "grunt-mocha-test": "^0.12.7",
    ...

А потом

npm install

И меня радует этот крючок:

describe('Feature', function() {

    before(function () {

        if (!Config.isFeaturePresent) {

            console.log('Feature not configured for that env, skipping...');
            this.skip();
        }
    });
...

    it('should return correct response on AB', function (done) {

        if (!Config.isABPresent) {

           return this.skip();
        }

        ...
Виктор Перов
источник
-3

Пожалуйста, не надо. Тест, который не работает единообразно в разных средах, должен признаваться вашей инфраструктурой сборки. И это может очень дезориентировать, когда в CI-сборках выполняется другое количество тестов, чем локальных.

Также это портит повторяемость. Если разные тесты выполняются на сервере и локально, у меня могут быть тесты, которые не проходят в dev и проходят в CI или наоборот. Нет функции принуждения, и у меня нет возможности быстро и точно исправить неудачную сборку.

Если вам необходимо отключить тесты между средами, вместо условного запуска тестов, пометьте свои тесты и используйте фильтр для исключения тестов, которые не работают в определенных целях сборки. Таким образом, все знают, что происходит, и это умеряет их ожидания. Это также позволяет всем узнать, что в тестовой среде есть несоответствия, и у кого-то может быть решение, которое снова заставит их работать правильно. Если вы просто отключите звук теста, они могут даже не знать о проблеме.

Джейсон
источник
Принимая во внимание, что функциональный тест работает непоследовательно между средами (локальными и разработчиками), это нормально. Ваш CI должен соответственно выйти из строя до того, как ваш Pull Request завершится. Код - это правильное место для документирования этих несоответствий. Обходные пути файла конфигурации с большей вероятностью скроют ситуацию. Вот почему it.skip находится в коде, а не в файле конфигурации.
TamusJRoyce,