Come saltare programmaticamente un test in moka?


142

Ho un codice in cui alcuni test falliranno sempre in ambiente CI. Vorrei disabilitarli in base a una condizione ambientale.

Come saltare programmaticamente un test in moka durante l'esecuzione di runtime?


3
Saltarethis.skip() a livello di programmazione un test è coperto da mochajs.org/#inclusive-tests e dalla risposta di @ zatziky di seguito. Le altre risposte sono obsolete per Mocha v3 +
Patrick,

1
descrivi.skip ('description', () => {}) / description.only ('description', () => {}) / it.skip ('description', () => {}) / it. only ('description', () => {})
Jun711,

qualche risposta accettata?
Paul Rooney,

Risposte:


168

È possibile saltare i test posizionando una x davanti al blocco descrittivo o bloccato oppure posizionando un .skipdopo.

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

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

È inoltre possibile eseguire un singolo test inserendo un .onlytest. per esempio

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

In questo caso verrebbe eseguito solo il blocco funzione 2.

Non sembra esserci un modo per saltare i test a livello di programmazione, ma potresti semplicemente fare una sorta di controllo in beforeEachun'istruzione ed eseguire il test solo se il flag è stato impostato.

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
Il tuo secondo tentativo di soluzione non funzionerà, perché l'ordine di esecuzione non è quello che pensi. Quando beforeEachviene eseguita la chiamata, Mocha registra la funzione anonima (l '"hook") per uso futuro , quando describeviene eseguita la chiamata, Mocha esegue immediatamente la funzione anonima passata ad essa. Quindi, al momento if (runTest)dell'esecuzione, l' beforeEach hook non avrà funzionato.
Louis,

23
In che modo questa risposta ha 27 voti positivi? La domanda si pone sul salto programmatico dei test, quindi l'aggiunta di ".skip" o ".only" non è utile. Quindi dice esplicitamente che non puoi fare ciò che l'OP vuole fare, nonostante il fatto che altre risposte ti diano come farlo.
Graeme Perrow,

3
Non funzionerà, non una risposta alla domanda, vedi invece la risposta di
@Gajus

1
Questa risposta merita una domanda diversa che non è stata posta qui. Non ho il potere di cambiare nulla qui. Vedi la risposta this.skip ().
Andrew Martinez,

3
questo non risponde alla domanda
Ingo Renner,

110

Esiste un modo non documentato di saltare programmaticamente i test:

// test.js

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

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

in esecuzione:

$ mocha test.js


  foo
    - foo


  0 passing (9ms)
  1 pending

Questo è discusso in https://github.com/mochajs/mocha/issues/1901 .


14
Ai lettori potrebbe piacere sapere che questo segna il tutto describecome saltato (cioè tutti i test nel describevengono saltati).
Louis,

Documentazione "pending test" di Mocha
lasec0203

descrivi.skip ('description', () => {}) / description.only ('description', () => {}) / it.skip ('description', () => {}) / it. only ('description', () => {})
Jun711,

Non so perché questo tipo di risposta sia votato. è un trucco - e non uno preety.
chenop,

2
documentazione effettiva mochajs.org/#inclusive-tests , non è un hack tra l'altro, ma un metodo corretto per escludere alcuni test basati sulle impostazioni di runtime. cioè risponde esattamente a ciò che è stata posta la domanda originale. Grazie @xavdid
WowPress.host,

41

Questa risposta funziona per ES6 .

Invece di:

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

Tu vuoi:

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

Ciò salta condizionalmente tutti i test nel blocco di descrizione SE la condizione è falsa.

Oppure, anziché:

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

Tu vuoi:

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

Ciò salta condizionalmente un test SE la condizione è falsa.


4
Prendo quello che stai suggerendo, ma prima devi definire una descrizione contestuale come questa: const contextualDescribe = shouldAvoidTests ? describe.skip : describe quindi puoi usarla: contextualDescribe('your it block', () => {
Ser

3
@Ser Per arrivare su una sola riga, ho usato qualcosa del genere:(condition ? describe : describe.skip)('your describe block', () => {
joshden,

Come fare questo asincrono? Devo cercare la condizione di salto in base a un flag redis, che è un'operazione asincrona (archiviamo i flag delle funzionalità in redis).
Patrick Finnigan,

è passato un po 'di tempo ma prima avevo anche questo tipo di necessità, penso di aver appena avvolto tutta la roba da moka in una funzione chiamata dopo il completamento della richiamata asincrona - non ricordo i dettagli esatti
danday74

Usavo questa tecnica, ma ora non funziona per me. prova semplicemente a scrivere(it)('my test', () => {})
cyrf

33

Uso il runtime saltando da Mocha per lo stesso scenario che stai descrivendo. È il copia incolla dai documenti :

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

  // make assertions
});

Come puoi vedere, salta il test in base all'ambiente. La mia condizione è if(process.env.NODE_ENV === 'continuous-integration').


2
Concordato! Può essere un one liner facendo un ritorno anticipato forse? Come: if (/* skipTestCondition */) return this.skip();- modifica: funziona: D
SidOfc

12

per saltare i test, usare describe.skipoit.skip

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

per includere test che potresti usare describe.onlyoit.only


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

Maggiori informazioni su https://mochajs.org/#inclusive-tests


6

Dipende da come si desidera saltare il test a livello di programmazione. Se è possibile determinare le condizioni per saltare prima dell'esecuzione di qualsiasi codice di test, è possibile chiamare ito it.skipse necessario, in base a una condizione. Ad esempio, questo salterà alcuni test se la variabile di ambiente ONEè impostata su qualsiasi valore:

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

});

Se le condizioni che si desidera verificare possono essere determinate solo al momento del test, è un po 'più complicato. Se non desideri accedere a qualcosa che non sia strettamente parte dell'API di test, puoi farlo:

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

});

Mentre il mio primo esempio è stato quello di contrassegnare i test come saltati formalmente (aka "in attesa"), il metodo che ho appena mostrato eviterà di eseguire il test effettivo ma i test non saranno contrassegnati come saltati formalmente. Saranno contrassegnati come passati. Se vuoi assolutamente farli saltare, non conosco affatto l'accesso alle parti che non stanno parlando correttamente dell'API di test:

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

Non sono sicuro che ciò si qualifichi come "salto programmatico", ma per saltare selettivamente alcuni test specifici per il nostro ambiente CI, utilizzo la funzione di tagging di Mocha ( https://github.com/mochajs/mocha/wiki/Tagging ). In describe()o it()messaggi, puoi aggiungere un tag come @ no-ci. Per escludere questi test, si potrebbe definire un "target ci" specifica nel vostro package.json e l'uso --grepe --invertparametri come:

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

Questo è uno dei modi per saltare i test. Un piccolo esempio sarebbe davvero utile. Ma sono assolutamente d'accordo che il link che hai condiviso abbia un esempio all'inizio stesso. @martin
Krishna Pravin,

2

Puoi usare il mio pacchetto mocha-assume per saltare i test a livello di codice, ma solo dall'esterno dei test. Lo usi in questo modo:

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

Mocha-assume eseguirà il test solo quando lo myAssumptionè true, altrimenti lo salterà (usando it.skip) con un bel messaggio.

Ecco un esempio più dettagliato:

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

Usandolo in questo modo, puoi evitare guasti a cascata. Supponiamo che il test "Does something cool"fallisca sempre quando someAssumption non regge - Ma questo presupposto è già stato testato sopra (in Tests that verify someAssuption is always true").

Quindi il fallimento del test non ti dà nuove informazioni. In realtà, è persino un falso positivo: il test non è fallito perché "qualcosa di interessante" non ha funzionato, ma perché un prerequisito per il test non è stato soddisfatto. con mocha-assumete puoi spesso evitare tali falsi positivi.


È davvero bello, triste che il progetto sembri abbandonato ...
Victor Schröder,

@ VictorSchröder Bene, ho avuto l'impressione che nessuno lo stesse usando. Potrei cercare di migliorarlo nelle prossime settimane, se avessi il tempo. Puoi aprire un problema su Github e dirmi cosa ti piacerebbe vedere?
David Tanzer

Non lo sto ancora usando, @David Tanzer, ho appena trovato la tua idea davvero interessante . Mi vedo fare la preparazione del test e saltare abbastanza condizionalmente e questo tipo di interfaccia è molto più leggibile. Devo ancora provarlo, ma immagino che sarebbe bello poter concatenare diversi presupposti e supportare funzioni asincrone come presupposti. Forse tutto ciò è già supportato, non ho verificato.
Victor Schröder,

1
C'è un problema, tuttavia, con il secondo esempio in questa risposta. Il beforeAllgancio non è garantito per l'esecuzione prima che tutti i test vengano raccolti. In realtà, è molto probabile che venga eseguito solo in seguito, ma in questo caso assuming(someAssumption)avrebbe già ricevuto il valore iniziale (non definito). È necessario avvolgere anche quella parte in una funzione per ottenere l'effetto desiderato.
Victor Schröder,

2

Possiamo scrivere una bella funzione wrapper pulito per eseguire in modo condizionale i test come segue:

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

Questo può quindi essere richiesto e utilizzato nei test come segue:

ifConditionIt('Should be an awesome test', (done) => {
  // Test things
  done();
});

Penso che questa sia di gran lunga la soluzione più elegante presentata qui. Può essere esteso facilmente per fare una logica più complicata e ha l'ulteriore vantaggio che i test saltati in questo modo sono contrassegnati come saltati nel rapporto di test
Joshua Evans

0

Supponiamo che volessi saltare il mio test parametrizzato se la mia descrizione del test contenesse la stringa "pippo", farei questo:

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

Nel tuo caso, credo che se volessi controllare le variabili di ambiente, potresti usare NodeJS:

process.env.ENV_VARIABLE

Ad esempio (Attenzione: non ho testato questo bit di codice!), Forse qualcosa del genere:

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

Dove puoi impostare ENV_VARIABLE in modo che sia qualsiasi cosa tu stia digitando, e usando quel valore, salta o esegui il test. (Cordiali saluti, la documentazione per process.env di NodeJS è qui: https://nodejs.org/api/process.html#process_process_env )

Non mi prenderò completamente il merito per la prima parte di questa soluzione, ho trovato e testato la risposta e ha funzionato perfettamente per saltare i test basati su una semplice condizione attraverso questa risorsa: https://github.com/mochajs/mocha/issues / 591

Spero che questo ti aiuti! :)


0

Questo non sta davvero usando le funzionalità di moka, ma piuttosto modificandolo per ottenere il comportamento che volevo.

Volevo saltare qualsiasi "è" successivo nei miei test moka per goniometri e uno "esso" non è riuscito. Questo perché una volta fallito un passaggio di un test di viaggio, era quasi certo che il resto avrebbe avuto esito negativo e potrebbe richiedere molto tempo ed eseguire il build server se utilizzano il browser in attesa che gli elementi appaiano su una pagina ecc.

Quando si eseguono semplicemente test moka standard (non goniometro), questo può essere ottenuto con i ganci globali prima di ogni e dopo ogni attacco attaccando un flag 'skipSubsequent' al genitore del test (descrivendolo) in questo modo:

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


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

Quando si tenta di farlo con goniometro e moka, l'ambito di "questo" è cambiato e il codice sopra non funziona. Si finisce con un messaggio di errore del tipo 'error call done ()' e il goniometro si ferma.

Invece ho finito con il codice qui sotto. Non il più bello, ma finisce per sostituire l'implementazione delle funzioni di test rimanenti con questo this.skip (). Questo probabilmente smetterà di funzionare se / quando gli interni di moka cambieranno con le versioni successive.

È stato scoperto attraverso alcuni tentativi ed errori eseguendo il debug e ispezionando gli interni di moka ... aiuta a completare le suite di test del browser prima che i test falliscano.

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

Quando @danielstjules ha risposto qui c'è un modo per saltare il test. L'autore di questo argomento ha copiato la risposta dalla discussione su mochajs github.com, ma non ci sono informazioni su quale versione di mocha è disponibile.

Sto usando il modulo grunt-mocha-test per integrare la funzionalità del test mocha nel mio progetto. Passa all'ultima versione (per ora) - 0.12.7 portami mocha versione 2.4.5 con l'implementazione di this.skip ().

Quindi, nel mio package.json

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

E poi

npm install

E mi rende felice con questo gancio:

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

Per favore, no. Un test che non funziona in modo coerente in tutti gli ambienti dovrebbe essere riconosciuto come tale dall'infrastruttura di build. E può essere molto disorientante quando i build CI hanno un numero diverso di test eseguiti rispetto a quelli locali.

Inoltre, aumenta la ripetibilità. Se diversi test vengono eseguiti sul server e sul locale, posso avere test che falliscono in dev e passano in CI o viceversa. Non esiste alcuna funzione di forzatura e non ho modo di correggere in modo rapido e preciso una build fallita.

Se è necessario disattivare i test tra ambienti, anziché eseguirli in modo condizionale, contrassegnare i test e utilizzare un filtro per eliminare i test che non funzionano in determinati target di build. In questo modo tutti sanno cosa sta succedendo e tempera le loro aspettative. Inoltre, consente a tutti di sapere che esiste un'incoerenza nel framework di test e che qualcuno potrebbe avere una soluzione che li riavvia correttamente. Se si silenzia il test, potrebbero anche non sapere che c'è un problema.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.