Як програмно пропустити тест на мокко?


142

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

Як програмно пропустити тест на мокко під час виконання програми?


3
Програмний пропуск тесту висвітлюється this.skip()в mochajs.org/#inclusive-tests та відповіді @ zatziky нижче. Решта відповідей застаріла для Mocha v3 +
Патріка

1
description.skip ('опис', () => {}) / description.only ('опис', () => {}) / it.skip ('опис', () => {}) / це. тільки ('опис', () => {})
червень 711,

будь-яка прийнята відповідь?
Пол Руні

Відповіді:


168

Ви можете пропустити тести, поставивши х перед описом або блоком, або розмістивши .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,
         }
    }
}

8
Ваша друга спроба рішення не спрацює, оскільки порядок виконання не такий, як ви думаєте. Коли beforeEachвиклик виконується, Mocha записує анонімну функцію ("гачок") для подальшого використання, коли describeдзвінок виконується, Mocha негайно виконує передану йому анонімну функцію. Тож до моменту if (runTest)виконання beforeEach гачок не запуститься.
Луї

23
Як ця відповідь має 27 результатів? Питання задає питання про тестування програмно пропускання, тому додавання ".skip" або ".only" не є корисним. Потім прямо сказано, що ви не можете робити те, що хоче зробити ОП, незважаючи на те, що інші відповіді говорять вам, як це зробити.
Graeme Perrow

3
Не буде працювати, не відповідь на питання, дивіться на відповідь
@Gajus

1
Ця відповідь має підстави для іншого питання, яке тут не задавали. У мене немає сили щось тут змінити. Дивіться відповідь this.skip ().
Ендрю Мартінес

3
це не відповідає на питання
Інго Реннер

110

Існує недокументований спосіб програмно пропускати тести:

// test.js

describe('foo', function() {
  before(function() {
    this.skip();
  });

  it('foo', function() {
    // will not run
    console.log('This will not be printed');
  });
});

працює:

$ mocha test.js


  foo
    - foo


  0 passing (9ms)
  1 pending

Про це йдеться в https://github.com/mochajs/mocha/isissue/1901 .


14
Читачі, можливо, хочуть знати, що це позначає ціле describeяк пропущене (тобто всі тести в describeпропущених).
Луї

Документація про "очікувані тести" Mocha: mochajs.org/#pending-tests
lasec0203

description.skip ('опис', () => {}) / description.only ('опис', () => {}) / it.skip ('опис', () => {}) / це. тільки ('опис', () => {})
червня

Я не розумію, чому такий варіант відповіді не використовується. його хак - і не претіт.
ченоп

2
фактична документація mochajs.org/#inclusive-tests , це не хакерське btw в будь-якому випадку, а правильний метод виключення деяких тестів на основі налаштувань часу виконання. тобто він відповідає саме тому, що було задано оригінальне запитання. Дякуємо @xavdid
WowPress.host

41

Ця відповідь справді працює для ES6 .

Замість:

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

Ти хочеш:

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

Це умовно пропускає всі тести в описувальному блоці, якщо умова є помилковою.

Або замість:

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

Ти хочеш:

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

Це умовно пропускає один тест, якщо ця умова помилкова.


4
Я отримую те, що ви пропонуєте, але спочатку потрібно визначити такий контекстуальний опис: const contextualDescribe = shouldAvoidTests ? describe.skip : describe потім ви можете використовувати це: contextualDescribe('your it block', () => {
Сер

3
@Ser Щоб потрапити на один рядок, я використав щось подібне:(condition ? describe : describe.skip)('your describe block', () => {
joshden

Як це зробити асинхронізувати? Мені потрібно шукати умову пропуску на основі прапора redis, що є операцією асинхронізації (ми зберігаємо прапорці функції у redis).
Патрік Фінніган

був деякий час, але у Айва була така потреба і раніше, я думаю, що я просто завернув усі моккі речі у функцію, яка була викликана після завершення зворотного виклику async - не можу пригадати точні деталі
da7374

Раніше я використовував цю техніку, але зараз вона не вдається. спробуйте просто написати(it)('my test', () => {})
cyrf

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').


2
Домовились! Може бути одним лайнером, можливо, зробивши раннє повернення? Як: if (/* skipTestCondition */) return this.skip();- редагувати: працює: D
SidOfc

12

пропустити тести, використовувати 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


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!");
    });

});

3

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

"scripts": {
  "test": "mocha",
  "test-ci" : "mocha --reporter mocha-junit-reporter --grep @no-ci --invert"
}

Це один із способів пропустити тести. Невеликий приклад був би дійсно корисним. Але я безумовно згоден, що посилання, яким ви поділилися, має приклад на самому початку. @martin
Krishna Pravin

2

Ви можете використовувати мій пакунок mocha-припустити, щоб пропустити тести програмно, але тільки ззовні тестів. Ви використовуєте його так:

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

Mocha-припустимо, запустить ваш тест лише тоді, коли він 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 і сказати мені, що ви хотіли б побачити?
Девід Танзер

Я його ще не використовую, @David Tanzer, я просто визнав вашу ідею дуже цікавою . Я бачу, що я дуже багато роблю підготовку до тесту і умовно пропускаю цей інтерфейс набагато читабельніший. Я все ще мушу спробувати це, але я думаю, що було б здорово мати можливість ланцюжка кількох припущень та підтримки асинхронних функцій як припущень. Можливо, все це вже підтримується, я не перевіряв.
Віктор Шредер

1
Однак є проблема з другим прикладом цієї відповіді. beforeAllКрюк не гарантована працювати , перш ніж всі тести зібрані. Насправді, дуже ймовірно, що він буде запущений лише після цього, але в цьому випадку він assuming(someAssumption)би вже отримав початкове (невизначене) значення. Цю частину потрібно також загорнути у функцію, щоб досягти бажаного ефекту.
Віктор Шредер

2

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

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();
});

Я думаю, що це далеко не найелегантніше рішення, представлене тут. Це може бути легко розширено, щоб зробити більш складну логіку, і він має додатковий бонус, який тести, пропущені таким чином, позначені як пропущені у звіті про тест
Джошуа Еванс

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 таким, яким ви не користуєтесь відключенням і використовуючи це значення, пропустіть або запустіть тест. (FYI документація для NodeJS 'process.env знаходиться тут: https://nodejs.org/api/process.html#process_process_env )

Я не візьму на себе повну оцінку за першу частину цього рішення, я знайшов і перевірив відповідь, і він прекрасно працював, щоб пропустити тести на основі простої умови через цей ресурс: https://github.com/mochajs/mocha/isissue / 591

Сподіваюся, це допомагає! :)


0

Це насправді не використовує особливості моккі, скоріше налаштовуючи її, щоб отримати таку поведінку, яку я хотів.

Я хотів пропустити будь-яке наступне "це" в моїх тестах транспортування мотора, і одне "це" не вдалося. Це було тому, що коли один крок тестування не вдався, майже було впевнене, що решта не вдасться, і це може зайняти тривалий час та зависнути сервер збірки, якщо вони використовують браузер, чекає, коли елементи з’являться на сторінці тощо.

Якщо ви просто виконуєте стандартні тести на мокко (не транспортир), це можна досягти за допомогою глобальних гаків передEEE і AfterEach, додавши прапор 'skipSubsequent' до батьківського тесту (опишіть) так:

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


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

При спробі цього за допомогою транспортира та мокше його сфера застосування "це" змінилася, і код вище не працює. У вас з'являється повідомлення про помилку, наприклад "помилка виклику зроблено ()" і транспортир зупиняється.

Натомість я опинився з кодом нижче. Не найкрасивіший, але він закінчується заміною реалізації інших тестових функцій на 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'
    }
});


-2

Як тут відповів @danielstjules є спосіб пропустити тест. @author з цієї теми скопіював відповідь з дискусії github.com mochajs, але немає інформації, у якій версії mocha вона доступна.

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

Отже, в моєму пакеті.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();
        }

        ...

-2

Будь ласка, не варто. Тест, який не працює послідовно в різних середовищах, повинен бути визнаний вашою інфраструктурою побудови. І це може бути дуже дезорієнтуючим, коли в побудовах CI працює інша кількість тестів, ніж у місцевих.

Також він прикручує повторюваність. Якщо на сервері та локальному сервері працюють різні тести, я можу мати тести, що не спрацьовують у програмі dev та проходять у CI або навпаки. Немає функції примушування, і я не маю можливості швидко та точно виправити помилкову збірку.

Якщо ви повинні вимкнути тести між середовищами, замість умовно запущених тестів, позначте свої тести та використовуйте фільтр для усунення тестів, які не працюють у певних цілях збирання. Таким чином, всі знають, що відбувається, і це гартує їхні очікування. Це також дає всім знати, що в тестовій структурі є непослідовність, і хтось може мати рішення, яке знов запустить їх належним чином. Якщо ви просто заглушите тест, вони можуть навіть не знати, що є проблема.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.