Wie überspringe ich programmgesteuert einen Test in Mokka?

142

Ich habe einen Code, in dem bestimmte Tests in der CI-Umgebung immer fehlschlagen. Ich möchte sie aufgrund einer Umgebungsbedingung deaktivieren.

Wie überspringe ich programmgesteuert einen Test in Mokka während der Laufzeitausführung?

Gajus
quelle
3
Das programmgesteuerte Überspringen eines Tests wird this.skip()in mochajs.org/#inclusive-tests und in der Antwort von @ zatziky unten behandelt. Der Rest der Antworten ist für Mocha v3 +
Patrick
1
descriptione.skip ('description', () => {}) / descriptione.only ('description', () => {}) / it.skip ('description', () => {}) / it. only ('description', () => {})
Jun711
eine akzeptierte Antwort?
Paul Rooney

Antworten:

168

Sie können Tests überspringen, indem Sie ein x vor die Beschreibung oder den Block setzen oder ein x .skipdanach setzen.

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

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

Sie können auch einen einzelnen Test ausführen, indem Sie ein .onlyauf den Test setzen. zum Beispiel

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

In diesem Fall würde nur der Feature-2-Block ausgeführt.

Es scheint keine Möglichkeit zu geben, Tests programmgesteuert zu überspringen, aber Sie können einfach eine beforeEachAnweisung einchecken und den Test nur ausführen, wenn das Flag gesetzt ist.

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
quelle
8
Ihr zweiter Lösungsversuch wird nicht funktionieren, da die Ausführungsreihenfolge nicht Ihrer Meinung nach entspricht. Wenn der beforeEachAufruf ausgeführt wird, zeichnet Mocha die anonyme Funktion (den "Hook") für die zukünftige Verwendung auf. Wenn der describeAufruf ausgeführt wird, führt Mocha sofort die an ihn übergebene anonyme Funktion aus. Wenn die Zeit if (runTest)ausgeführt wird, ist der beforeEach Hook noch nicht ausgeführt.
Louis
22
Wie hat diese Antwort 27 positive Stimmen? Die Frage bezieht sich auf das programmgesteuerte Überspringen von Tests, daher ist das Hinzufügen von ".skip" oder ".only" nicht hilfreich. Dann heißt es ausdrücklich, dass Sie nicht tun können, was das OP tun möchte, obwohl andere Antworten Ihnen sagen, wie es geht.
Graeme Perrow
3
Funktioniert nicht, keine Antwort auf die Frage, siehe stattdessen
@
1
Diese Antwort hat Vorzüge für eine andere Frage, die hier nicht gestellt wurde. Ich habe hier nicht die Macht, etwas zu ändern. Siehe die Antwort this.skip ().
Andrew Martinez
3
Dies beantwortet nicht die Frage
Ingo Renner
109

Es gibt eine undokumentierte Möglichkeit, Tests programmgesteuert zu überspringen:

// test.js

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

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

Laufen:

$ mocha test.js


  foo
    - foo


  0 passing (9ms)
  1 pending

Dies wird unter https://github.com/mochajs/mocha/issues/1901 erläutert .

Gajus
quelle
13
Leser möchten vielleicht wissen, dass dies das Ganze describeals übersprungen markiert (dh alle Tests in der describewerden übersprungen).
Louis
Mochas
lasec0203
descriptione.skip ('description', () => {}) / descriptione.only ('description', () => {}) / it.skip ('description', () => {}) / it. only ('description', () => {})
Jun711
Ich verstehe nicht, warum diese Art von Antwort positiv bewertet wird. Es ist ein Hack - und kein Preety.
Chenop
2
Aktuelle Dokumentation mochajs.org/#inclusive-tests , es ist in keiner Weise ein Hack, sondern die richtige Methode, um einige Tests basierend auf Laufzeiteinstellungen auszuschließen. dh es beantwortet genau das, was die ursprüngliche Frage gestellt hat. Danke @xavdid
WowPress.host
41

Diese Antwort funktioniert für ES6 .

Anstatt:

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

Sie wollen:

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

Dies überspringt bedingt alle Tests im Beschreibungsblock, wenn die Bedingung falsch ist.

Oder statt:

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

Sie wollen:

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

Dies überspringt bedingt einen Test, wenn die Bedingung falsch ist.

danday74
quelle
4
Ich verstehe, was Sie vorschlagen, aber Sie müssen zuerst eine kontextbezogene Beschreibung wie diese definieren: const contextualDescribe = shouldAvoidTests ? describe.skip : describe Dann können Sie sie verwenden: contextualDescribe('your it block', () => {
Ser
3
@ Ser Um in eine einzelne Zeile zu kommen, habe ich so etwas verwendet:(condition ? describe : describe.skip)('your describe block', () => {
Joshden
Wie mache ich das asynchron? Ich muss die Sprungbedingung basierend auf einem Redis-Flag nachschlagen, was eine asynchrone Operation ist (wir speichern Feature-Flags in Redis).
Patrick Finnigan
Ich glaube, ich habe gerade das ganze Mokka-Zeug in eine Funktion eingewickelt, die aufgerufen wurde, nachdem der asynchrone Rückruf abgeschlossen war - ich kann mich nicht an die genauen Details erinnern
danday74
Früher habe ich diese Technik verwendet, aber jetzt schlägt sie für mich fehl. versuchen Sie einfach zu schreiben(it)('my test', () => {})
Cyrf
33

Ich verwende das Laufzeit-Überspringen von Mocha für dasselbe Szenario, das Sie beschreiben. Es ist das Kopieren und Einfügen aus den Dokumenten :

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

  // make assertions
});

Wie Sie sehen können, wird der Test basierend auf der Umgebung übersprungen. Mein eigener Zustand ist if(process.env.NODE_ENV === 'continuous-integration').

Amio.io
quelle
2
Einverstanden! Kann man ein Einzeiler sein, wenn man vielleicht früh zurückkehrt? Wie: if (/* skipTestCondition */) return this.skip();- bearbeiten: funktioniert: D
SidOfc
12

um Tests zu überspringen, verwenden Sie describe.skipoderit.skip

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

um Tests einzuschließen, die Sie verwenden könnten describe.onlyoderit.only


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

Weitere Informationen unter https://mochajs.org/#inclusive-tests

lfender6445
quelle
6

Dies hängt davon ab, wie Sie den Test programmgesteuert überspringen möchten. Wenn die Bedingungen für das Überspringen festgelegt werden können, bevor ein Testcode ausgeführt wird, können Sie einfach itoder it.skipnach Bedarf basierend auf einer Bedingung anrufen . Dies überspringt beispielsweise einige Tests, wenn die Umgebungsvariable ONEauf einen beliebigen Wert festgelegt ist:

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

});

Wenn die Bedingungen, die Sie überprüfen möchten, nur zur Testzeit ermittelt werden können, ist dies etwas komplizierter. Wenn Sie nicht auf etwas zugreifen möchten, das nicht unbedingt Teil der Test-API ist, können Sie Folgendes tun:

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

});

Während mein erstes Beispiel darin bestand, die Tests als formal übersprungen (auch als "ausstehend" bezeichnet) zu markieren, wird mit der soeben gezeigten Methode die Durchführung des eigentlichen Tests vermieden, aber die Tests werden nicht als formal übersprungen markiert. Sie werden als bestanden markiert. Wenn Sie sie unbedingt überspringen lassen möchten, weiß ich nicht, wie Sie auf Teile zugreifen können, die nicht richtig Teil der Test-API sind:

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
quelle
3

Ich bin nicht sicher, ob dies als „programmatisches Überspringen“ qualifiziert ist, aber um einige spezifische Tests für unsere CI-Umgebung selektiv zu überspringen, verwende ich die Tagging-Funktion von Mocha ( https://github.com/mochajs/mocha/wiki/Tagging ). In describe()oder it()Nachrichten können Sie ein Tag wie @ no-ci hinzufügen. Um diese Tests auszuschließen, können Sie in Ihrer package.json ein bestimmtes "ci-Ziel" definieren --grepund folgende --invertParameter verwenden:

"scripts": {
  "test": "mocha",
  "test-ci" : "mocha --reporter mocha-junit-reporter --grep @no-ci --invert"
}
Martin
quelle
Dies ist eine der Möglichkeiten, Tests zu überspringen. Ein kleines Beispiel wäre wirklich nützlich. Aber ich stimme definitiv zu, dass der Link, den Sie geteilt haben, am Anfang selbst ein Beispiel hat. @martin
Krishna Pravin
2

Sie können mein Paket Mokka-Annahme verwenden , um Tests programmgesteuert zu überspringen, jedoch nur von außerhalb der Tests. Sie verwenden es so:

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

Mokka-Annahme führt Ihren Test nur dann aus, wenn dies der Fall myAssumptionist true. Andernfalls wird er it.skipmit einer netten Nachricht übersprungen.

Hier ist ein detaillierteres Beispiel:

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

Auf diese Weise können Sie Kaskadenfehler vermeiden. "Does something cool"Angenommen, der Test würde immer fehlschlagen, wenn someAssumption nicht zutrifft. Diese Annahme wurde jedoch bereits oben (in Tests that verify someAssuption is always true") getestet .

Der Testfehler gibt Ihnen also keine neuen Informationen. Tatsächlich ist es sogar falsch positiv: Der Test ist nicht fehlgeschlagen, weil "etwas Cooles" nicht funktioniert hat, sondern weil eine Voraussetzung für den Test nicht erfüllt war. mit können mocha-assumeSie oft solche Fehlalarme vermeiden.

David Tanzer
quelle
Das ist wirklich cool, traurig, dass das Projekt aufgegeben zu sein scheint ...
Victor Schröder
@ VictorSchröder Nun, ich hatte den Eindruck, dass niemand es benutzte. Könnte versuchen, es in den nächsten Wochen zu verbessern, wenn ich die Zeit dazu hätte. Können Sie eine Ausgabe auf Github eröffnen und mir sagen, was Sie sehen möchten?
David Tanzer
Ich benutze es noch nicht, @David Tanzer, ich fand deine Idee einfach cool . Ich sehe mich ziemlich oft in der Vorbereitung von Tests und im bedingten Überspringen, und diese Art von Benutzeroberfläche ist viel besser lesbar. Ich muss es noch versuchen, aber ich stelle mir vor, dass es cool wäre, mehrere Annahmen zu verketten und asynchrone Funktionen als Annahmen zu unterstützen. Vielleicht wird das alles schon unterstützt, ich habe es nicht überprüft.
Victor Schröder
1
Es gibt jedoch ein Problem mit dem zweiten Beispiel in dieser Antwort. Es beforeAllwird nicht garantiert, dass der Haken läuft, bevor alle Tests gesammelt wurden. Eigentlich ist es sehr wahrscheinlich, dass es erst danach ausgeführt wird, aber in diesem Fall assuming(someAssumption)hätte der bereits den anfänglichen (undefinierten) Wert erhalten. Es ist auch erforderlich, diesen Teil in eine Funktion einzuschließen, um den gewünschten Effekt zu erzielen.
Victor Schröder
2

Wir können eine schöne Clean-Wrapper-Funktion schreiben, um Tests wie folgt bedingt auszuführen:

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

Dies kann dann wie folgt erforderlich und in Ihren Tests verwendet werden:

ifConditionIt('Should be an awesome test', (done) => {
  // Test things
  done();
});
dcr24
quelle
Ich denke, dies ist bei weitem die eleganteste Lösung, die hier vorgestellt wird. Es kann leicht erweitert werden, um kompliziertere Logik zu erstellen, und hat den zusätzlichen Vorteil, dass auf diese Weise übersprungene Tests im Testbericht als übersprungen markiert werden
Joshua Evans
0

Angenommen, ich wollte meinen parametrisierten Test überspringen, wenn meine Testbeschreibung die Zeichenfolge "foo" enthält. Ich würde dies tun:

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

In Ihrem Fall glaube ich, dass Sie NodeJS verwenden könnten, wenn Sie Umgebungsvariablen überprüfen möchten:

process.env.ENV_VARIABLE

Zum Beispiel (Warnung: Ich habe diesen Code nicht getestet!), Vielleicht so etwas:

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

Wenn Sie ENV_VARIABLE so einstellen können, dass es sich um das handelt, was Sie gerade eingeben, und diesen Wert verwenden, überspringen Sie den Test oder führen Sie ihn aus. (Zu Ihrer Information, die Dokumentation für die process.env von NodeJS finden Sie hier: https://nodejs.org/api/process.html#process_process_env )

Ich werde den ersten Teil dieser Lösung nicht vollständig anerkennen. Ich habe die Antwort gefunden und getestet und es hat perfekt funktioniert, Tests basierend auf einer einfachen Bedingung über diese Ressource zu überspringen: https://github.com/mochajs/mocha/issues / 591

Hoffe das hilft! :) :)

Rubicon
quelle
0

Hierbei werden die Funktionen von Mokka nicht wirklich verwendet, sondern optimiert, um das gewünschte Verhalten zu erzielen.

Ich wollte jedes nachfolgende "es" in meinen Winkelmesser-Mokka-Tests überspringen und eines "es" schlug fehl. Dies lag daran, dass nach dem Fehlschlagen eines Schritts eines Reisetests fast sicher war, dass der Rest fehlschlagen würde. Dies kann lange dauern und den Build-Server belasten, wenn der Browser darauf wartet, dass Elemente auf einer Seite usw. angezeigt werden.

Wenn nur Standard-Mokka-Tests (nicht Winkelmesser) ausgeführt werden, kann dies mit globalen Vor-Jeder- und Nach-jedem-Hooks erreicht werden, indem dem übergeordneten (beschriebenen) Flag des Tests ein 'skipSubsequent'-Flag wie folgt hinzugefügt wird:

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


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

Wenn Sie dies mit Winkelmesser und Mokka versuchen, hat sich der Umfang von 'dies' geändert und der obige Code funktioniert nicht. Am Ende wird eine Fehlermeldung wie "Fehleraufruf erledigt ()" angezeigt und der Winkelmesser wird angehalten.

Stattdessen habe ich den folgenden Code erhalten. Nicht die schönste, aber am Ende wird die Implementierung der verbleibenden Testfunktionen durch this.skip () ersetzt. Dies wird wahrscheinlich nicht mehr funktionieren, wenn sich die Interna von Mokka mit späteren Versionen ändern.

Es wurde durch einige Versuche und Irrtümer herausgefunden, indem Mochas Interna debuggt und inspiziert wurden. Dies hilft dabei, Browser-Testsuiten schneller abzuschließen, wenn die Tests fehlschlagen.

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
quelle
-2

Wie @danielstjules hier antwortete , gibt es eine Möglichkeit, den Test zu überspringen. @author dieses Themas hat die Antwort von github.com mochajs Diskussion kopiert, aber es gibt keine Informationen darüber, welche Version von Mokka verfügbar ist.

Ich verwende das Grunt-Mocha-Test-Modul zur Integration der Mocha-Test-Funktionalität in mein Projekt. Wenn ich zur letzten (vorerst) Version - 0.12.7 springe, bekomme ich die Mokka-Version 2.4.5 mit der Implementierung von this.skip ().

Also, in meinem package.json

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

Und dann

npm install

Und es macht mich glücklich mit diesem Haken:

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
quelle
-2

Bitte nicht. Ein Test, der in allen Umgebungen nicht konsistent funktioniert, sollte von Ihrer Build-Infrastruktur als solcher anerkannt werden. Und es kann sehr verwirrend sein, wenn in den CI-Builds eine andere Anzahl von Tests ausgeführt wird als in den lokalen.

Auch vermasselt es die Wiederholbarkeit. Wenn verschiedene Tests auf dem Server und lokal ausgeführt werden, kann es vorkommen, dass Tests in dev fehlschlagen und in CI bestanden werden oder umgekehrt. Es gibt keine Forcierungsfunktion und ich habe keine Möglichkeit, einen fehlgeschlagenen Build schnell und genau zu korrigieren.

Wenn Sie Tests zwischen Umgebungen deaktivieren müssen, anstatt Tests unter bestimmten Bedingungen auszuführen, kennzeichnen Sie Ihre Tests und verwenden Sie einen Filter, um Tests zu entfernen, die in bestimmten Build-Zielen nicht funktionieren. Auf diese Weise weiß jeder, was los ist und es erfüllt seine Erwartungen. Außerdem erfahren alle, dass das Testframework inkonsistent ist und dass jemand möglicherweise eine Lösung hat, mit der er wieder ordnungsgemäß ausgeführt werden kann. Wenn Sie den Test nur stumm schalten, wissen sie möglicherweise nicht einmal, dass ein Problem vorliegt.

Jason
quelle