Jak programowo pominąć test w mokce?

142

Mam kod, w którym pewne testy zawsze kończą się niepowodzeniem w środowisku CI. Chciałbym je wyłączyć na podstawie warunków środowiskowych.

Jak programowo pominąć test w mokce podczas wykonywania?

Gajus
źródło
3
Programowe pomijanie testu jest omówione this.skip()w mochajs.org/#inclusive-tests i odpowiedzi @ zatziky poniżej. Pozostałe odpowiedzi są nieaktualne dla Mocha v3 +
Patrick
1
opisać.skip ('opis', () => {}) / opisać.only ('opis', () => {}) / it.skip ('opis', () => {}) / it. only ('description', () => {})
Jun711,
jakakolwiek zaakceptowana odpowiedź?
Paul Rooney,

Odpowiedzi:

168

Możesz pominąć testy, umieszczając x przed opisem lub blokując lub umieszczając .skippo nim.

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

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

Możesz również uruchomić pojedynczy test, umieszczając .onlyna teście. na przykład

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

W tym przypadku działałby tylko blok funkcji 2.

Wygląda na to, że nie ma sposobu na programistyczne pominięcie testów, ale można po prostu sprawdzić beforeEachinstrukcję i uruchomić test tylko wtedy, gdy flaga została ustawiona.

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
źródło
8
Twoja druga próba rozwiązania nie zadziała, ponieważ kolejność wykonywania nie jest tą, o której myślisz. Kiedy beforeEachwywołanie jest wykonywane, Mocha zapisuje anonimową funkcję („haczyk”) do wykorzystania w przyszłości , kiedy describewywołanie jest wykonywane, Mocha natychmiast wykonuje przekazaną mu funkcję anonimową. Więc zanim if (runTest)zostanie wykonany, beforeEach hak nie będzie działał.
Louis
22
Jak ta odpowiedź ma 27 głosów za? Pytanie dotyczy programowego pomijania testów, więc dodanie „.skip” lub „.only” nie jest pomocne. Następnie wyraźnie mówi, że nie możesz zrobić tego, co chce PO, pomimo faktu, że inne odpowiedzi mówią ci, jak to zrobić.
Graeme Perrow,
3
To nie zadziała, nie jest odpowiedzią na pytanie, zamiast tego zobacz odpowiedź
@Gajus
1
Ta odpowiedź ma znaczenie dla innego pytania, którego tutaj nie zadano. Nie mam mocy, żeby cokolwiek tu zmienić. Zobacz odpowiedź this.skip ().
Andrew Martinez,
3
to nie odpowiada na pytanie
Ingo Renner
110

Istnieje nieudokumentowany sposób na programowe pomijanie testów:

// test.js

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

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

bieganie:

$ mocha test.js


  foo
    - foo


  0 passing (9ms)
  1 pending

Jest to omówione na https://github.com/mochajs/mocha/issues/1901 .

Gajus
źródło
13
Czytelnicy mogą chcieć wiedzieć, że oznacza to całość describejako pominiętą (tj. Wszystkie testy w sekcji describesą pomijane).
Louis
Dokumentacja "oczekujących testów" Mocha: mochajs.org/#pending-tests
lasec0203
opisać.skip ('opis', () => {}) / opisać.only ('opis', () => {}) / it.skip ('opis', () => {}) / it. only ('description', () => {})
Jun711,
Nie rozumiem, dlaczego taka odpowiedź jest pozytywna. to hack - a nie piękny.
chenop
2
aktualna dokumentacja mochajs.org/#inclusive-tests , nie jest to w żaden sposób hack, ale poprawna metoda wykluczania niektórych testów w oparciu o ustawienia uruchomieniowe. tj. odpowiada dokładnie na to, co zadawano na pierwotnym pytaniu. Dzięki @xavdid
WowPress.host
41

Ta odpowiedź działa w ES6 .

Zamiast:

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

Chcesz:

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

To warunkowo pomija wszystkie testy w bloku opisywania, JEŚLI warunek jest fałszywy.

Lub zamiast:

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

Chcesz:

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

To warunkowo pomija jeden test, JEŚLI warunek jest fałszywy.

danday74
źródło
4
Rozumiem, co sugerujesz, ale najpierw musisz zdefiniować kontekstowy opis w ten sposób: const contextualDescribe = shouldAvoidTests ? describe.skip : describe następnie możesz go użyć: contextualDescribe('your it block', () => {
Ser
3
@Ser Aby dostać się do jednej linii, użyłem czegoś takiego:(condition ? describe : describe.skip)('your describe block', () => {
joshden
Jak to zrobić asynchronicznie? Muszę sprawdzić warunek pominięcia oparty na fladze redis, która jest operacją asynchroniczną (przechowujemy flagi funkcji w redis).
Patrick Finnigan,
minęło trochę czasu, ale ja też miałem taką potrzebę wcześniej, myślę, że właśnie zawinąłem wszystkie rzeczy mokki w funkcji, która została wywołana po zakończeniu wywołania zwrotnego asynchronicznego - nie pamiętam dokładnych szczegółów
danday74
Kiedyś używałem tej techniki, ale teraz mi się nie udaje. spróbuj po prostu napisać(it)('my test', () => {})
cyrf
33

Używam pomijania w czasie wykonywania z Mocha dla tego samego scenariusza, który opisujesz. To jest kopia wklej z dokumentów :

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

  // make assertions
});

Jak widać, pomija test oparty na środowisku. Mój własny stan to if(process.env.NODE_ENV === 'continuous-integration').

Amio.io
źródło
2
Zgoda! Czy może to być jeden liniowiec, być może dokonując wcześniejszego powrotu? Na przykład: if (/* skipTestCondition */) return this.skip();- edit: works: D
SidOfc
12

aby pominąć testy, użyj describe.skiplubit.skip

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

aby uwzględnić testy, których możesz użyć describe.onlylubit.only


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

Więcej informacji na https://mochajs.org/#inclusive-tests

lfender6445
źródło
6

Zależy to od tego, jak chcesz programowo pominąć test. Jeśli warunki pomijania można określić przed uruchomieniem kodu testowego, możesz po prostu wywołać itlub it.skipw razie potrzeby, na podstawie warunku. Na przykład spowoduje to pominięcie niektórych testów, jeśli zmienna środowiskowa ONEma dowolną wartość:

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

});

Jeśli warunki, które chcesz sprawdzić, można określić tylko w czasie testu, jest to nieco bardziej skomplikowane. Jeśli nie chcesz uzyskać dostępu do niczego, co nie jest ściśle mówiąc częścią testowego API, możesz zrobić to:

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

});

Podczas gdy moim pierwszym przykładem było oznaczanie testów jako formalnie pominiętych (inaczej „oczekujących”), metoda, którą właśnie pokazałem, pozwoli po prostu uniknąć wykonywania rzeczywistego testu, ale testy nie zostaną oznaczone jako formalnie pominięte. Zostaną oznaczone jako zaliczone. Jeśli absolutnie chcesz je pominąć, nie znam żadnego sposobu na dostęp do części, które nie są poprawnie mówiącą częścią testowego 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!");
    });

});
Louis
źródło
3

Nie jestem pewien, czy kwalifikuje się to jako „programowe pomijanie”, ale aby wybiórczo pominąć niektóre testy dla naszego środowiska CI, używam funkcji tagowania Mocha ( https://github.com/mochajs/mocha/wiki/Tagging ). W wiadomościach describe()lub it()możesz dodać znacznik, taki jak @ no-ci. Aby wykluczyć te testy, można zdefiniować specyficzny „ci docelowej” w package.json i użytkowania --greporaz --invertparametrów takich jak:

"scripts": {
  "test": "mocha",
  "test-ci" : "mocha --reporter mocha-junit-reporter --grep @no-ci --invert"
}
jaskółka oknówka
źródło
To jeden ze sposobów na pominięcie testów. Mały przykład byłby naprawdę przydatny. Ale zdecydowanie zgadzam się, że udostępniony link ma przykład na samym początku. @martin
Krishna Pravin
2

Możesz użyć mojego pakietu mocha-zakładaj, aby pominąć testy programowo, ale tylko spoza testów. Używasz tego w ten sposób:

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

Mocha-zakładaj uruchomi twój test tylko wtedy , gdy myAssumptionjest true, w przeciwnym razie pominie go (używającit.skip ) z ładnym komunikatem.

Oto bardziej szczegółowy przykład:

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... */
        });
    });
});

Używając go w ten sposób, możesz uniknąć kaskadowych awarii. Powiedzmy, że test "Does something cool"zawsze kończy się niepowodzeniem, gdy jakieś założenie nie jest spełnione - ale to założenie zostało już przetestowane powyżej (wTests that verify someAssuption is always true" ).

Zatem niepowodzenie testu nie daje żadnych nowych informacji. W rzeczywistości jest to nawet fałszywie dodatni wynik: test nie zakończył się niepowodzeniem, ponieważ „coś fajnego” nie zadziałało, ale dlatego, że warunek wstępny testu nie został spełniony. z mocha-assumetobą często można uniknąć takich fałszywych alarmów.

David Tanzer
źródło
To naprawdę fajne, smutne, że projekt wydaje się być porzucony ...
Victor Schröder
@ VictorSchröder Cóż, miałem wrażenie, że nikt go nie używa. Gdybym miał na to czas, mógłbym pomyśleć o jego poprawie w ciągu najbliższych kilku tygodni. Czy możesz otworzyć zgłoszenie na githubie i powiedzieć mi, co chcesz zobaczyć?
David Tanzer
Jeszcze go nie używam, @David Tanzer, właśnie uznałem twój pomysł za naprawdę fajny . Widzę siebie robiącego przygotowanie do testów i warunkowe pomijanie całkiem sporo, a ten rodzaj interfejsu jest dużo bardziej czytelny. Nadal muszę spróbować, ale wyobrażam sobie, że fajnie byłoby móc połączyć kilka założeń i obsługiwać funkcje asynchroniczne jako założenia. Może to wszystko jest już obsługiwane, nie sprawdzałem.
Victor Schröder
1
Jest jednak problem z drugim przykładem w tej odpowiedzi. Nie beforeAllma gwarancji, że hak będzie działał przed zebraniem wszystkich testów. W rzeczywistości jest bardzo prawdopodobne, że zostanie uruchomiony dopiero później, ale w tym przypadku assuming(someAssumption)otrzymałby już początkową (nieokreśloną) wartość. Konieczne jest również owinięcie tej części funkcji, aby osiągnąć pożądany efekt.
Victor Schröder
2

Możemy napisać ładną, czystą funkcję opakowującą do warunkowego uruchamiania testów w następujący sposób:

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

Może to być następnie wymagane i użyte w testach w następujący sposób:

ifConditionIt('Should be an awesome test', (done) => {
  // Test things
  done();
});
dcr24
źródło
Myślę, że jest to zdecydowanie najbardziej eleganckie rozwiązanie przedstawione tutaj. Można go łatwo rozszerzyć, aby wykonać bardziej skomplikowaną logikę, i ma dodatkową zaletę, że testy pominięte w ten sposób są oznaczone jako pominięte w raporcie z testu
Joshua Evans
0

Powiedzmy, że chcę pominąć sparametryzowany test, jeśli opis testu zawiera ciąg „foo”, zrobiłbym to:

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

W twoim przypadku uważam, że jeśli chcesz sprawdzić zmienne środowiskowe, możesz użyć NodeJS:

process.env.ENV_VARIABLE

Na przykład (Ostrzeżenie: nie testowałem tego fragmentu kodu!), Może coś takiego:

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

Tam, gdzie możesz ustawić ENV_VARIABLE na wszystko, od czego wyłączasz, i używając tej wartości, pomiń lub uruchom test. (FYI dokumentacja dotycząca process.env NodeJS jest tutaj: https://nodejs.org/api/process.html#process_process_env )

Nie będę w pełni zasługiwał na pierwszą część tego rozwiązania, znalazłem i przetestowałem odpowiedź i działało idealnie, aby pominąć testy oparte na prostym warunku za pośrednictwem tego zasobu: https://github.com/mochajs/mocha/issues / 591

Mam nadzieję że to pomoże! :)

Rubicon
źródło
0

To nie jest tak naprawdę korzystanie z funkcji mokki, a raczej ulepszanie jej, aby uzyskać zachowanie, które chciałem.

Chciałem pominąć kolejne „to” w moich testach mokki z kątomierzem i jedno „to” nie powiodło się. Dzieje się tak, ponieważ gdy jeden etap testu podróży się nie powiódł, było prawie pewne, że reszta się nie powiedzie i może zająć dużo czasu i obciążać serwer kompilacji, jeśli używają przeglądarki, która czeka na pojawienie się elementów na stronie itp.

Po prostu uruchamiając standardowe testy mokka (nie kątomierz) można to osiągnąć za pomocą haków global beforeEach i afterEach, dołączając flagę „skipSubsequent” do elementu nadrzędnego testu (opisz) w następujący sposób:

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


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

Przy próbie tego z kątomierzem i mokką zakres „tego” uległ zmianie i powyższy kod nie działa. Kończy się komunikatem o błędzie, takim jak „błąd wywoływania funkcji done ()” i zatrzymanie kątomierza.

Zamiast tego otrzymałem poniższy kod. Nie jest to najładniejsze, ale kończy się zastąpieniem implementacji pozostałych funkcji testowych metodą this.skip (). To prawdopodobnie przestanie działać, jeśli / kiedy wewnętrzne elementy mokki zmienią się w późniejszych wersjach.

Zostało to ustalone metodą prób i błędów, debugując i sprawdzając wewnętrzne elementy mokki ... pomaga jednak w szybszym ukończeniu zestawów testów przeglądarki, gdy testy kończą się niepowodzeniem.

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'
    }
});
Paul Silvester
źródło
-2

Jak odpowiedział @danielstjules tutaj , jest sposób na pominięcie testu. @autor tego tematu skopiował odpowiedź z dyskusji mochajs na github.com, ale nie ma informacji w jakiej wersji mocha jest dostępna.

Używam modułu grunt-mocha-test do integracji funkcji testu mokka w moim projekcie. Przeskakuję do ostatniej (na razie) wersji - 0.12.7, przynieś mi mokkę w wersji 2.4.5 z implementacją this.skip ().

Tak więc w moim pliku package.json

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

I wtedy

npm install

I cieszy mnie ten haczyk:

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

        ...
Victor Perov
źródło
-2

Proszę nie. Test, który nie działa konsekwentnie w różnych środowiskach, powinien zostać uznany za taki przez infrastrukturę kompilacji. Może to być bardzo dezorientujące, gdy kompilacje CI mają inną liczbę testów niż lokalne.

To także psuje powtarzalność. Jeśli różne testy są uruchamiane na serwerze i lokalne, mogę mieć testy, które kończą się niepowodzeniem w tworzeniu i przechodzą w CI lub odwrotnie. Nie ma funkcji wymuszającej i nie mam możliwości szybkiego i dokładnego poprawienia nieudanej kompilacji.

Jeśli musisz wyłączyć testy między środowiskami, zamiast warunkowo uruchamiać testy, otaguj testy i użyj filtru, aby wyeliminować testy, które nie działają w niektórych celach kompilacji. W ten sposób każdy wie, co się dzieje, a to osłabia ich oczekiwania. Dzięki temu wszyscy wiedzą, że we frameworku testowym jest niespójność i ktoś może mieć rozwiązanie, które sprawi, że znów będą działać poprawnie. Jeśli po prostu wyciszysz test, mogą nawet nie wiedzieć, że jest problem.

Jason
źródło