Mocha: this.timeout() schlägt fehl, wenn die Pfeilfunktionen von ES6 verwendet werden

Erstellt am 21. Dez. 2015  ·  59Kommentare  ·  Quelle: mochajs/mocha

Bei Verwendung von Node >= 4 mit "use strict" und ES6-Syntax für Pfeilfunktionen schlägt Mocha fehl:

describe('foo', () => {
  this.timeout(100);
});

# => TypeError: this.timeout is not a function

Die Verwendung der ES5-Syntax funktioniert:

describe('foo', function() {
  this.timeout(100);
});

Also, was für ein hässlicher Trick macht Mokka mit this ?

faq

Hilfreichster Kommentar

Vielen Dank.

Warum so viel "Magie", die am Ende Probleme macht? Warum nicht das?:

var mocha = require('mocha');

mocha.describe('foo', (suite) => {
  suite.timeout(100);

  suite.it('must love bar', () => ... );  
});

Keine Globals, keine problematische Magie... sondern nur JavaScript.

Alle 59 Kommentare

Es bindet die Funktion an den Testkontext, was bei Verwendung von Pfeilfunktionen nicht möglich ist. Von http://mochajs.org/

screen shot 2015-12-21 at 8 06 34 am

Das tut mir leid!

Vielen Dank.

Warum so viel "Magie", die am Ende Probleme macht? Warum nicht das?:

var mocha = require('mocha');

mocha.describe('foo', (suite) => {
  suite.timeout(100);

  suite.it('must love bar', () => ... );  
});

Keine Globals, keine problematische Magie... sondern nur JavaScript.

Was Sie vorschlagen, ist eine wichtige bahnbrechende Änderung und etwas, das in https://github.com/mochajs/mocha/issues/1969#issuecomment-160925915 diskutiert wird. Eine Neufassung könnte diese Arten von Semantik einführen :)

Gut zu wissen. Vielen Dank.

@ibc naja , das müsste es sein

var mocha = require('mocha');

mocha.describe('foo', (suite) => {
  suite.timeout(100);

  suite.it('must love bar', (suite) => ... );  
});

aber sind die beiden verschiedenen Suite-Argumente vom gleichen Typ? wahrscheinlich nicht, also haben Sie verschiedene Variablennamen, um die verschiedenen Typen wie so widerzuspiegeln

var mocha = require('mocha');

mocha.describe('foo', (suite) => {
  suite.timeout(100);

  suite.it('must love bar', (test) => ... );  
});

Der Pfeiloperator kann jedoch nicht in Funktionen verwendet werden, die Kontexte erwarten.

Ich kann mir nicht vorstellen, die BDD-Benutzeroberfläche für #1969 zu knacken - jedenfalls auf Anhieb -, obwohl ich überzeugt sein könnte. Ich hatte gehofft, dass wir die bestehende API beibehalten und ein separates Paket mit der BDD-Benutzeroberfläche einführen. Mocha wird mit einer Version der BDD-Benutzeroberfläche ausgeliefert, die die vorhandene API verwendet, aber dann können wir eine neue Version des BDD-UI-Pakets mit Lambdas danach veröffentlichen - Benutzer können wählen, ob sie explizit auf dieses Paket aktualisieren möchten oder nicht.

Vielleicht könnte eine alternative ES6-Syntax für describe oder suite dieses Problem lösen:

describe({ feature: 'create stuff' , do () {
    it('abc', () => {
    }); 
}})

Dies würde zumindest eine Bindung auf Suite-Ebene ermöglichen.

Gibt es hierzu Neuigkeiten? ich habe das

mocha = require('mocha');

mocha.describe('test', (suite) => {

suite.timeout(500);

suite.it('test', (done)=>
          )
    }
)

Und TypeError: Kann die Eigenschaft 'timeout' von undefined nicht lesen

@mroien das ist kein Mokka-Bug. die Pfeilsyntax ist kein 1:1-Ersatz für function . Bitte informieren Sie sich über die Einschränkungen

Ist daraus was geworden? Ich mag die vorgeschlagene Lösung, allein schon aus Liebe zu Pfeilfunktionen und Abneigung gegen 'dieses', wenn es nicht benötigt wird

Da timeout nur bei done relevant ist, warum nicht einfach die timeout-Funktion an die done-Funktion anhängen.

it('makes sense', done => {
    done.timeout(100);
});

@nomilous das geht immer noch nicht. Ich habe ein ähnliches Problem gehabt. Was für meinen Fall funktioniert, ist das Aufrufen von setTimeout innerhalb des it Blocks. z.B

it('description', done => {
     const func = () => {
          // assertions
     };
     setTimeout(func, 10000);
});

@nomilous synchron oder Fälle, die ein Promise zurückgeben, können ebenfalls eine Zeitüberschreitung haben.

@andela-engmkwalusimbi das soll nicht funktionieren. Wie @boneskull schrieb :

@mroien das ist kein Mokka-Bug. die Pfeilsyntax ist kein 1:1-Ersatz für die Funktion. Bitte informieren Sie sich über die Einschränkungen

Für alle, die sich immer noch darüber Gedanken machen, stellen Sie sicher, dass Sie verstehen, was eine Pfeilfunktion impliziert, dann kommen Sie hierher zurück und lesen Sie weiter (es gibt viele Ressourcen, die dies viel besser erklären können als ich).

Die einzige Möglichkeit, wie diese Pfeilfunktionen in diesem Fall funktionieren würden, besteht darin, die bdd API so zu ändern, dass ein context Objekt an jeden Callback (Hooks, Tests) jedes Runnables (Hooks, Tests) übergeben wird, anstatt this . Das ist keine schlechte Idee, aber es ist ein Erdbeben einer bahnbrechenden Veränderung, also wird es nie passieren. An Stelle von:

it('should do something', function (done) {
  this.timeout(9000);
  // stuff
  done();
});

es würde so aussehen:

it('should do something', (context, done) => {
  context.timeout(9000);
  done();
});

Das würde jeden existierenden asynchronen Mocha-Test brechen, unabhängig davon, ob er ansonsten abwärtskompatibel wäre:

it('should do something', function (context, done) {
  // context is unused, but 'done' is now the second parameter
  this.timeout(9000);
  done();
});

Wir könnten jedoch eine alternative bdd Implementierung bereitstellen, die dies tut - es wäre einfach nicht die Standardeinstellung.

Das ist ungefähr die gründlichste Erklärung, die ich habe, "wo dieses Problem liegt". :Lächeln:

Vielleicht könnte es für die nächste Major-Version berücksichtigt werden? Ich denke nicht, dass die Änderung wichtig genug ist, um eine alternative bdd-Implementierung zu erstellen. Benannte Argumente können auch bei der zukünftigen Entwicklung helfen und möglicherweise eine einfache Möglichkeit schaffen, eine Art Test-Middleware wie folgt hinzuzufügen:

it('should do something', function ({ context, done }) { ...

Wir könnten jedoch eine alternative bdd-Implementierung bereitstellen, die dies tut - es wäre einfach nicht die Standardeinstellung.

@boneskull Eine neue bdd-es6-Schnittstelle wäre toll :)

Obwohl ich in Pfeilfunktionen verliebt bin, die zB für Array-Funktionen wie .filter(i => i.val) wirklich nützlich sind, was ist das Problem bei der Verwendung normaler Funktionen? Ich denke, es ist sehr nützlich, Beschreibungen und sie global zu haben, damit ich sie nicht jedes Mal anfordern muss. Und seit wann ist this Magie, nur weil Sie (Pfeil-)Funktionen nicht verstehen? Ich möchte definitiv nicht jedes Mal eine Variable angeben, wenn ich Versprechen zurückgeben kann, sonst wäre ich schon lange auf so etwas wie ava umgestiegen. In Bezug auf die Einfachheit von Mokka denke ich, dass es keine großen Änderungen an den in #1969 beschriebenen normalen / Pfeilfunktionen geben sollte. Und bitte sagen Sie mir nicht, dass Pfeilfunktionen schneller zu tippen sind, da Ihr Editor ein einzelnes f in function () {\n\t\n} umwandeln kann.

Ich bin mir nicht sicher, gibt es eine Lösung zum Timeout eines before() Aufrufs, der Pfeilfunktionen verwendet?

    before( async function () {
      data = await provider.getData();
      console.log(data);
      this.timeout(30*1000);
    });

Hat keine Wirkung. immer noch 4 Sekunden Timeout hier. Dies ist die einzige langsame Sache in meiner Testsuite. Ich kann in mocha.opts Timeout auf 30s setzen, um das Problem zu lösen, aber ich brauche nicht wirklich alle Tests, um nach 30s ein Timeout zu machen, nur der eine API-Aufruf, wenn 4s für 99% in Ordnung sind.

So habe ich es in der Zwischenzeit gelöst (beachten Sie, dass das erste describe() function anstelle der Fat Arrow-Syntax verwendet:

describe('Search API', function () {
    this.timeout(30*1000);

    context('search', () => {
        let data;

        before( async () => {
          data = await provider.getSearch();
        });

        it('returns results', () => {
          expect(data).to.exist;
          expect(data.results).to.be.instanceOf(Array);
          expect(data.results.length).to.be.above(0);
        });
    })
});

@chovy Sie setzen das Timeout nach dem Timeout in await provider.getData() .
Versuchen Sie es stattdessen mit diesem:

before(async function () {
  this.timeout(30*1000); // set timeout first, then run the function
  data = await provider.getData();
  console.log(data);
});

Ich bin mir nicht sicher, gibt es eine Lösung zum Timeout eines before()-Aufrufs, der Pfeilfunktionen verwendet?

Nur um das klarzustellen: Es gibt derzeit keine Möglichkeit, Mochas timeout mit Pfeilfunktionen aufzurufen. Jede Diskussion über Alternativen (wie verdienstvoll) ist eine Diskussion über mögliche neue (oder zumindest modifizierte) Schnittstellen.

Etwas, das ich seit einiger Zeit im Kopf hatte, war in der Lage zu sein:

it('...', (done) => {
  ...
  done()
})

und

it('...', (t) => {
  t.timeout(500)
  t.tag('integration', 'api')
  ...
  t.done()
})

die gleiche Standardschnittstelle verwenden.

Wenn Sie beide in derselben Standardschnittstelle unterstützen, können Sie mit der Verwendung von Pfeilfunktionen in einer vorhandenen Codebasis beginnen. Es ist erwähnenswert, dass die (done) Syntax, die in vielen Online-Tutorials zu finden ist, immer noch funktioniert, ohne Flags oder ähnliches.

In dieser Implementierung erhalten Sie also als Parameter die traditionelle done Funktion, jedoch mit den Hilfsfunktionen, die als Eigenschaften dieses done Funktionsobjekts hinzugefügt wurden.

Wenn Sie this.timeout() die verstrichene Zeit im Bericht ausgeblendet.

@dasilvacontin keine

@dasilvacontin oh, ich erinnere mich. weil du es anrufen musst. willst du vielleicht nicht.

Entschuldigung, können Sie "muss es nennen", @boneskull? Sprechen Sie über die Probleme, bei denen Mocha denkt, dass der Test asynchron ist?

Am 29. Januar 2017 um 05:54 Uhr schrieb Christopher Hiller [email protected] :

@dasilvacontin oh, ich erinnere mich. weil du es anrufen musst. willst du vielleicht nicht.


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail, zeigen Sie sie auf GitHub an oder schalten Sie den Thread stumm.

Wie deklarieren Sie außerdem Ihre Absicht, einen asynchronen Test durchzuführen, wenn Sie 't' verwenden?

In Tape müssen Sie immer 't.done' ('t.end' in ihrer API) aufrufen oder die erwartete Anzahl von Assertionen einstellen ('t.plan').

Wäre es möglich, it() mit Optionen ein drittes Argument hinzuzufügen? Das würde API nicht brechen.

it ('accepts lambda', (done)=>{ doWork();  done(); }, {timeout:60000});

@knochenschädel

Was wäre, wenn der Kontext nicht an erster Stelle, sondern optional an zweiter Stelle stehen würde?

An Stelle von:

it('should do something', function (done) {
  this.timeout(9000);
  // stuff
  done();
});

es würde so aussehen:

it('should do something', (done, context) => {
  context.timeout(9000);
  done();
});
it('should do something', function (done, context) {
  // context is unused, but 'done' is now the second parameter
  this.timeout(9000);
  done();
});

Wir könnten jedoch eine alternative bdd-Implementierung bereitstellen, die dies tut - es wäre einfach nicht die Standardeinstellung.

Das ist ungefähr die gründlichste Erklärung, die ich habe, "wo dieses Problem liegt". 😄

oder wenn Kontext ein definierter Parameter sein müsste

it('should do something', function (done, override) {
  // context is unused, but 'done' is now the second parameter
  override.timeout(9000);
  done();
});

Aber ich würde auch eine nicht standardmäßige Schnittstelle nehmen :)

Der Nachteil jeder Lösung, die done erfordert, ist, dass Sie done auch wenn die Rückgabe eines Promises einfacher wäre. Ich spreche für mich selbst, ich weiß, dass ich lieber function und return als .then(()=>{done()}, done) !

@Flamenco Das ist eine interessante Idee, obwohl ich es vielleicht vorziehe, die Funktion zuletzt zu haben (ja, es ist technisch gesehen "magischer", aber seien wir ehrlich, es ist einfach genug zu überprüfen, ob der Parameter eine Funktion ist und es ist intuitiv genug zu verwenden und es ist nicht so, dass Mokka in irgendeine andere Abstraktion gespeist wird, die eine solche "Magie" zerstören könnte); Ein solches Optionsobjekt könnte auch verwendet werden, um Tags und/oder Pending-Test-Gründe bereitzustellen, die beide angeforderte Funktionen sind (das Auffinden im GitHub-Suchfeld für Issues/PR-Listen bleibt dem Leser als Übung überlassen), mit denen ich ' Ich gebe zu, Mitleid zu haben (auch wenn es möglich ist, ihre Abwesenheit zu umgehen, hat die reale Sache Vorteile gegenüber den Workarounds).

@ScottFreeCode Ich stimme definitiv zu done Ich möchte es auch nicht verwenden, ich habe nur die Notwendigkeit kommentiert, den Kontext an erster Stelle und an letzter Stelle zu setzen und das oben genannte Beispiel von boneskull zu verwenden.

Ich würde einfach die Option lieben, im Kontext zu übergeben oder einen Schalter auf Mokka für die Ausführung von es6 zu setzen.

In der Zwischenzeit schließe ich nur diese wenigen Testbeschreibungen ein, die Timeout-Unterschiede in einem derpy aussehenden function()-Aufruf erfordern.

Ich habe eine Problemumgehung für den Anwendungsfall gefunden, bei dem ein Versprechen von einer Pfeilfunktion, die ein benutzerdefiniertes Timeout benötigt, an Mokka zurückgegeben wird, die ich teilen möchte, falls andere es nützlich finden.

Durch Hinzufügen der folgenden when Funktion, die unten in einer Testdeklaration definiert ist, wie folgt: it('does something', when(() => someFunctionReturningAPromise, customTimeout)) der Mokka-Timeout gesetzt werden, ohne die Pfeilfunktionen aufzugeben.

In ähnlicher Weise, und da wir nur mit Promises arbeiten, können wir den ersten Parameter erneut einem Test unterziehen und im Kontext anstelle des Callbacks übergeben: it('can access the mocha test context', when(testContext => someFunctionThatNeedsContext(testContext))

const when = (lambda, timeout) =>
  function() { // return a plain function for mocha to bind this to
    this.timeout(timeout || this.timeout() || 1000)
    return lambda(this)
  }

Einige Testfälle zur Veranschaulichung:

const delay = timeout =>
  new Promise((resolve, reject) => setTimeout(resolve, timeout))

const deject = timeout => // similar to above, but a delayed reject
  new Promise((resolve, reject) => setTimeout(reject, timeout))

describe('mocha testing', () => {
  context('with only arrow functions', () => {
    context('tests that do not time out', () => {
      it('passes fast', when(() => delay(10), 100))
      it('does not usually time out', when(() => delay(2000), 2010))
    })
    context('tests that will time out', () => { // these should fail if the 'when' function works properly
      it('times out fast', when(() => delay(1000), 10)) // will fail in 10ms
      it('times out', when(() => delay(1000), 1000)) // will fail in about 1000ms
    })
    context('tests that will reject', () => { // this shows the when function works as expected when a test rejects
      it('fails fast', when(() => deject(10), 100))
    })
  })
})

@astitt-ripple ja, oder schreibst du einfach function () {} ... Wtf?

Ok, Luca, kranker Biss. :-)

Der Unterschied zu einer Pfeilfunktion besteht darin, dass die Rückgabe übersprungen werden kann. In einem (n
es6-Typ-Setup, dies kann bereits ein gängiges Muster für das Versprechen 'dann' sein
Ketten.

Mit einem Funktionsblock, wie Sie vorschlagen, und meines Wissens die Rückgabe für
das Versprechen muss explizit sein. Minimal für eine Promise-basierte Testfunktion
{... } ist falsch, ein Test muss immer sein Versprechen zurückgeben, also das Minimum
gültige Trivialisierung ist eigentlich: function { return ... }. Ansonsten der
test gibt undefined an Mokka zurück und nicht das versendete Versprechen... und das
Testautor hat eine schlechte Zeit.

Wenn der größte Teil des Codes in einer Codebasis bereits Pfeilfunktionen von Promise ist
und/oder ein funktionaler Programmierstil, kann das Hinzufügen einer Funktion return aussehen
inkonsistent. Das vorgeschlagene Wann-Formular ist stattdessen für diejenigen verfügbar, die
bevorzuge Pfeile und einen funktionaleren Stil als die traditionelle Funktion
Rückruf- oder Funktionsrückgabestile. Es ist knapper und passt zu den
Beschreiben Sie den Kontext it dsl Wir sind uns alle einig, dass wir gerne Tests schreiben und dabei berücksichtigen
Konto das Versprechen asynchrone Programmierung Abstraktion Javascript behandelt so
Gut. Auch ist es kürzer als function+return, auch ohne unseren Kumpel lockig:
wenn(() => ...).

Vielleicht ist das nicht der bevorzugte Stil dieses Projekts, das verstehe ich, und
Ich schlage es nicht als Änderung des Projekts vor. Vielleicht ist es sogar
verwerflich, wie Ihr wtf impliziert. Das ist in Ordnung. Mokka muss mit arbeiten
Pre-fp-freundliches js. Abwärtskompatibilität ist ein erstklassiges Anliegen. Dass
macht auch Sinn.

Dies ist ein langer und festgefahrener Thread, und dies ist ein Ausweg. Ein netter
Die Sache mit Javascript ist, dass es nicht einen Weg oder einen Stil geben muss
Aufgaben zuende bringen. Über den Stil müssen wir uns überhaupt nicht einigen. Funktionell
Apropos, mein vorheriger Beitrag gibt den Leuten eine Möglichkeit, Pfeile und Versprechen zu verwenden
konsequent und mit dem test dsl, ohne auf den mokka . zu verzichten
Kontext, in einer sauberen und funktionalen, programmierfreundlichen Weise, die es nicht gab
zuvor vorgeschlagen worden.

Vielen Dank.

Wenn der meiste Code in einer Codebasis bereits ... funktionaler Programmierstil ist ...

...dann ist die Verwendung von this.mutatingMethod(currentConfiguration) zum Festlegen von Verhalten, insbesondere einer bereits ausgeführten Funktion (oder besser einer Unterroutine) viel inkonsistenter als return schreiben zu müssen (was nur Syntax ist) , und ein inkonsistentes Erscheinungsbild würde diese Realität offensichtlicher machen, anstatt die Inkonsistenz tatsächlich einzuführen.

(Versteh mich nicht falsch, ich bin sehr zufrieden mit der steigenden Popularität von Ideen zur funktionalen Programmierung in JS; aber die Syntax von function / return vs => ist nicht wirklich wesentlich für die funktionale Programmierung, sondern nur eine Frage dessen, was in diesem Paradigma sauberer aussieht , während andere Konzepte wie Reinheit und deklarative vs sein Verhalten / Semantik , an welcher Stelle ein Wechsel zu Pfeilfunktionen wahrscheinlich trivial wäre...)

Ich stimme Ihnen zu, dass this.timeout mutationsbedingt ist und mit dem Paradigma der funktionalen Programmierung bricht. Das ist natürlich völlig inkonsistent. Gibt es derzeit eine andere Möglichkeit, ein benutzerdefiniertes Timeout pro Test zu deklarieren als this.timeout?

Bei der aktuellen Implementierung von Mokka scheint es notwendig zu sein, zum Imperativ/Mutations-Paradigma zurückzukehren oder die Einstellung pro Test-Timeouts aufzugeben. Das Eine oder das Andere.

In der obigen when Abstraktion ist ein Timeout der zweite Parameter, der es einem funktionalen Stil ermöglicht, auf der Ebene des Tests zu bleiben. Es verbirgt diese unvermeidliche Flucht aus dem FP-Modus zurück in die zwingende Programmierung, aber an einer Stelle. Außerdem gibt es Pfeilfunktionen Zugriff auf den Mokka-Kontext, was sonst nicht möglich ist, ohne die Parameterkonvention für Testfunktionen zu brechen. Es löst also möglicherweise in der Zwischenzeit einige Probleme für einige Benutzer dieses Projekts (nach der Vorgeschichte dieser Ausgabe zu urteilen), bis jemand Ihre Testläufer-Idee untersucht.

Versteh mich bitte auch nicht falsch. Ich glaube nicht, dass die funktionale Programmierung jemals die von der Turing-Maschine abgeleitete Imperative / Mutations-Programmierung jemals vollständig ersetzen wird oder sollte. Zum Beispiel wird in so ziemlich jedem Fall in einer JS-Laufzeit der Code, ob funktional oder nicht, letztendlich von einem Programm interpretiert, das in diesem traditionelleren Imperativ-Stil geschrieben ist (wahrscheinlich c++, aber nicht unbedingt), das auf einem Betriebssystem läuft, das auch um Mutationen herum geschrieben ist und Imperativ Ideen (wahrscheinlich C). Speicher ist eine feste Ressource, unveränderliche Datenstrukturen sind eine Lüge, sagt uns die Laufzeit. Dieses grundsätzlich zwingende Modell ist der Standard in der Computertechnik und wird es bleiben. Aber das bedeutet nicht, dass funktionale Programmierung nicht gleichzeitig existieren kann. Und wenn ja, ist es unvermeidlich, dass FP-Code von Zeit zu Zeit auf das zugrunde liegende Modell fallen muss. Ich denke nicht, dass das bedeuten sollte, dass wir unsere Hände heben und sagen, es sei alles Syntax, und lass uns einfach Funktion/Return verwenden.

Tatsächlich können wir in C funktionale Programmierung mit einer gewissen Detailtoleranz durchführen, genauso wie Sie funktionale Programmierung mit Funktion/Return statt mit => Funktionen durchführen können. Vergessen Sie nicht, Ihr Versprechen zurückzugeben. FP in C erfordert etwas mehr Tipparbeit, was schließlich nur reine Syntax ist.../s

Letztendlich bringen uns Pfeilfunktionen einer praktikablen und praktischen Arbeitsweise im Lambda-Kalkülmodell in einer gängigen Sprache schrittweise näher. Das Entfernen dieser zusätzlichen Zeichen macht einen kleinen, aber wichtigen Unterschied. Es gibt noch viele praktische Einschränkungen, aber viele davon sind lösbar, das vorliegende Thema ist eines davon.

Wie auch immer. Ich werde meine vorgeschlagene Hilfsfunktion verwenden, und andere können sie jetzt auch verwenden. Ich freue mich auf Ihre Test-Runner-Lösung, aber in der Zwischenzeit weiß ich nicht, ob es besonders produktiv sein wird, weiter zu versuchen, sich gegenseitig von unserer eigenen Meinung darüber zu überzeugen, was Syntax wichtig ist oder nicht, als ob es da wäre ist ein Weg. Ich mag Pfeile und du magst Funktionen. Ich habe kein stichhaltiges Argument gesehen, das meine Ansicht ändert. Ich bin offen für eins, aber es sollte besser durchdacht sein als Kniebeugen wie: "Nur Funktion verwenden, wtf" oder "Sie können immer noch fp mit einer ausführlicheren _syntax_ machen".

Lösen Sie das Problem anders, und dann muss niemand when . sagte Nuff. :-)

Ich denke nicht, dass das bedeuten sollte, dass wir unsere Hände heben und sagen, es sei alles Syntax, und lass uns einfach Funktion/Return verwenden.

Ich mag Pfeile und du magst Funktionen.

...es sollte besser durchdacht sein als Kniebeugen wie: ... "man kann immer noch fp mit einer ausführlicheren Syntax machen".

Das ist jedoch so ziemlich das Gegenteil von dem, was ich gesagt habe - ich ging davon aus, dass Pfeilfunktionen, die immer noch this , nicht FP wären, sondern OO mit Pfeilfunktionen ( die Umkehrung von FP mit traditionellen JS-Funktionen). Mit anderen Worten, weit davon entfernt, dass es sich nur um eine andere Syntax handelt, besteht das eigentliche Problem darin, dass es eine tiefere Paradigma-Inkompatibilität gibt als nur die Syntax-Inkompatibilität (wie Mocha derzeit sowieso entwickelt wird).

Ich bin mir ziemlich sicher, dass es möglich ist, eine alternative Schnittstelle auf Mocha aufzubauen, um this vollständig durch Parameter zu ersetzen. Ich möchte nur klarstellen, dass Sie mehr tun müssen, als nur einen Weg zu finden, Mochas this an Pfeilfunktionen zu übergeben, wenn Sie beim Schreiben von Tests FP werden möchten. Ich bin jedoch sehr dafür , dass ich mich dieser Art von Herausforderung stelle. ;^)

(Es gibt auch einige andere Verhaltensweisen von Mocha, die zustandsorientiert, global oder – schlimmer – beides sind, aber ich habe im Moment keine Zeit, um sie kurz aufzulisten. Wenn Sie jemals gesehen haben die Probleme, Mocha mehr als einmal laufen zu lassen, das ist jedoch ein Beispiel dafür.)

Gibt es derzeit eine andere Möglichkeit, ein benutzerdefiniertes Timeout pro Test zu deklarieren als this.timeout?

Leider bin ich mir ziemlich sicher, dass es das nicht gibt; Der Vorschlag, einen zusätzlichen Parameter für it zu akzeptieren, der eine Schlüsselwertzuordnung (als JS-Objekt) von Konfigurationseinstellungen wäre, klingt wie eine anständige zukünftige Lösung in Mocha, wenn jemand möchte versuche es umzusetzen.

Gibt es derzeit eine andere Möglichkeit, ein benutzerdefiniertes Timeout pro Test zu deklarieren als this.timeout?

Leider bin ich mir ziemlich sicher, dass es das nicht gibt;

Vielen Dank für die Bestätigung dieses Details. Dies festigt den Punkt, den ich gemacht habe.

Der Vorschlag, einen zusätzlichen Parameter zu akzeptieren, der eine Schlüssel-Wert-Zuordnung (als JS-Objekt) von Konfigurationseinstellungen wäre, klingt spontan nach einer anständigen zukünftigen Lösung in Mocha, wenn jemand versuchen möchte, sie zu implementieren.

+1 für eine allgemeinere Lösung.

Soweit ich das beurteilen kann, scheint es jedoch praktikabel zu sein, einen einzelnen Parameter noch zu übergeben. Kombinieren Sie this mit dem done Callback (so wird this zu einer Funktion). Lassen Sie dann jeden Test mit einem Versprechen (naja, eigentlich zwei, einen für die Behandlung des Timeouts und einen für die tatsächliche Ausführung des Tests) ausführen, unabhängig von der Parameteranzahl (abweichend von der heutigen Funktionsweise). Es könnte dann überprüfen, ob das Ergebnis der Funktion ein Versprechen war oder nicht. Wenn nicht, rufen Sie done nachdem die synchrone Funktion zurückkehrt, um den Test abzuschließen. Wenn das Ergebnis der Funktion stattdessen ein Promise ist, warten Sie, bis es aufgelöst (oder abgelehnt) wird. Wenn die Zeitüberschreitung auftritt, stoppen Sie den Test (wie zuvor). Für den Fall, dass es einem Test gelingt, done aufzurufen und auch ein Promise zurückzugeben. Entweder done wird vor der Auflösung aufgerufen. In diesem Fall sollte Mocha auf das Versprechen warten und dann den Test auf eine mehrdeutige Abschlusssequenz nicht bestehen. Oder done wird irgendwann nach der Lösung aufgerufen, in welchem ​​Fall der Test irgendwie rückwirkend fehlgeschlagen sein muss - oder das Problem auf andere vernünftige Weise signalisiert wird. Entschuldigung, das sind viele grobe Striche, aber das ist das Verständnis meines Außenstehenden dafür, was Mokka zu tun versucht und auf welche Macken es stößt. Welche anderen Überlegungen könnten verhindern, dass dies eine praktikable Lösung ist?

Wenn Sie beim Schreiben von Tests FP werden möchten, müssen Sie mehr tun, als nur einen Weg zu finden, um Mochas this to arrow Funktionen zu übergeben

einverstanden. Es gibt einen definitiven Wechsel zu einem anderen Rechenmodell, und außerdem ist Javascript ein komplexes Ökosystem, in dem viel zu beachten ist. In meinem speziellen Anwendungsfall ist jedoch das Festlegen des Timeouts von Zeit zu Zeit (z wenigstens). Was großartig ist. :+1:

Trotzdem würde ich gerne wissen, was Sie sonst noch als bevorstehende Hindernisse sehen, die speziell mit Mokka zu tun haben (im Gegensatz zu dem, was das Schreiben von Tests in FP im Allgemeinen bedeuten könnte).

Das ist aber so ziemlich das Gegenteil von dem, was ich gesagt habe

Es tut mir leid, wenn ich mich falsch dargestellt oder falsch verstanden habe. Bei vielem von dem, was ich geschrieben habe, bin ich mir aufgrund der Antworten auch nicht sicher, ob ich so rübergekommen bin, wie es beabsichtigt war. Was bedauerlich ist, denn ich denke, wenn wir es angehen würden, würden wir uns wahrscheinlich ziemlich einig werden, wie FP _theoretisch_ aussehen sollte_. Hier scheinen wir uns jedoch nicht einig zu sein, wie eine praktikable Reduktion auf _Practice_ in den aktuell verfügbaren Versionen von Mocha aussehen könnte, zumindest für einige Benutzer/Anwendungsfälle. Ich bin mir also nicht ganz sicher, was das Hauptproblem mit der vorgeschlagenen Add-On-Funktion ist, die ich von Ihrer Seite vorgeschlagen habe.

(Zitiert und geantwortet der Reihe nach, aber das Wichtigere ist wohl eher später als früher.)


Soweit ich das beurteilen kann, scheint es jedoch praktikabel zu sein, einen einzelnen Parameter noch zu übergeben. Kombinieren Sie dies mit dem erledigten Callback (so wird dies zu einer Funktion). Dann... Welche anderen Überlegungen könnten verhindern, dass dies eine praktikable Lösung ist?

Wenn wir die Abwärtskompatibilität brechen, gibt es viel einfachere Designs, zu denen wir wechseln könnten.

Wenn wir die Abwärtskompatibilität beibehalten, müssen diese beiden Tests bestehen und dürfen nicht ablaufen:

it("runs immediately", () => {
  // call functions and assert whatever
})
it("runs asynchronously", doneWithSomeOtherName => {
  setTimeout(() => {
    // call functions and assert whatever
    doneWithSomeOtherName()
  }, 100)
})

Sie können gerne versuchen, etwas Beispielcode zu entwickeln, um das Gegenteil zu beweisen (obwohl ich vorschlagen würde, sich stattdessen auf den Vorschlag am Ende dieses Kommentars zu konzentrieren), aber ich bin mir ziemlich sicher, dass kein Design dazu in der Lage sein wird und auch weiter machen diesen Test und nicht die Zeit aus:

it("looks just like an asynchronous test with a different name for `done`, but never tells Mocha it's done", context => {
  context.configureByMutation("some value")
  // call functions and assert whatever
})

Beachten Sie aber auch die Mutation dort. Mehr dazu weiter unten.


In meinem speziellen Anwendungsfall ist jedoch das Festlegen des Timeouts von Zeit zu Zeit (z wenigstens). Was großartig ist.

:+1:!


Trotzdem würde ich gerne wissen, was Sie sonst noch als bevorstehende Hindernisse sehen, die speziell mit Mokka zu tun haben (im Gegensatz zu dem, was das Schreiben von Tests in FP im Allgemeinen bedeuten könnte).

Ich glaube, ich habe dies vielleicht nicht ganz konzentriert kommuniziert, also lass mich sehen, ob ich es ein bisschen weiter reduzieren kann. (Es tut mir auch leid, wenn etwas davon als antagonistisch rübergekommen ist; es ist sicherlich nicht beabsichtigt, obwohl ich zugeben muss, dass ich hier versuche, die Denkweise zu ändern.) Die Codebasis von Mocha entspricht sehr stark der Klassenhierarchie und dem Getter- und Setter-Stil von "Objektorientierung" (und es gibt mehrere Probleme oder potenzielle Probleme, die Mocha hat, von denen ich glaube, dass sie auf ihren veränderlichen Zustand zurückzuführen sind), aber das wirkt sich im Allgemeinen nicht auf Ihren Testcode aus , wenn Sie nur Tests schreiben und Mocha ausführen lassen . Sie können mit Mochas zwingender Mutationskonfiguration seltsame Dinge tun:

it("imperatively sets the timeout multiple times", function(done) {
  this.timeout(5000)
  var context = this
  setTimeout(function() {
    context.timeout(1000)
    setTimeout(done, 500)
  }, 4000)
})

...muss aber nicht. Wie bei so vielen Elementen der funktionalen Programmierung in nicht-funktionalen Sprachen: Missbrauche einfach nicht das Imperativ.

(Es muss auch argumentiert werden, dass Ausnahmen unrein sind, aber ich bin noch nicht davon überzeugt, dass dies auf Ausnahmen zutrifft, die basierend auf der Eingabe ausgelöst

(Wichtiger Teil hier:) Was ich erreichen möchte, ist, dass wir möglicherweise entweder eine Komplikation zu einer bereits komplexen Codebasis hinzufügen oder eine abwärts-inkompatible Änderung vornehmen. Für beides brauchen wir eine Rechtfertigung. Wenn die Begründung "Tests funktionaler machen" lautet , ist das gut (jedenfalls in meinem Buch). Ein Design, das Tests funktionaler macht, kann die Mühe wert sein (je nachdem, wie viel Mühe es gibt). Aber wenn Sie mit "Tests funktionaler machen" meinen, "Pfeilfunktionen mutieren lassen", dh "Pfeilfunktionen weniger funktional machen", schwächt das den Fall stark ab (wenn es nicht nur widersprüchlich ist). Genauer gesagt: Ich glaube nicht, dass es fast so überzeugend ist, Tests funktionaler aussehen zu lassen (so sauber wie Pfeilfunktionen aussehen!), während das eine bisschen Mutation beibehalten wird, egal wie klein dieses bisschen anfangs war, eine fast so zwingende Rechtfertigung wie tatsächlich dieses Stück Mutation loszuwerden wäre – zumindest wenn es darum geht, Tests funktionaler zu machen.

Allerdings hätte ich bei dieser Tangente wahrscheinlich nicht einmal so weit weg sein sollen; siehe unten zu Lösungen. 😸


Ich bin mir also nicht ganz sicher, was das Hauptproblem mit der vorgeschlagenen Add-On-Funktion ist, die ich von Ihrer Seite vorgeschlagen habe.

(Auch wichtiger Teil hier:) Nun, ich mag es, dass timeout als Parameter anstelle eines Methodenaufrufs verwendet wird! Wenn Sie eine Möglichkeit finden, dies auf den Rest der Konfigurationsmethoden von Mocha zu verallgemeinern (es gibt viele davon -- und einige gelten für synchrone Tests, wenn ich mich richtig erinnere, deshalb können wir nicht einfach die gleichen Methoden hinzufügen wie Eigenschaften auf done und lassen Sie die Leute asynchrone Tests schreiben, die die Konfiguration über done aufrufen können, aber ich schweife ab), dann würde ich mir das auf jeden Fall ansehen. Zumindest möchten wir es vielleicht als Empfehlung aussprechen, und wir können die Implementierung möglicherweise sogar in it wenn ein dritter Parameter übergeben wird (oder so ähnlich, vielleicht it.configured oder it(...).configured(...) wenn wir nicht mehr Spielereien mit der Anzahl von Parametern wollen ...) -- was meiner Meinung nach eine abwärtskompatible Lösung wäre, die die zugrunde liegende Mutation / Imperativ angeht und die Pfeilfunktionsunterstützung "das richtige" erhält Weise" (wobei ich sowieso so argumentiere): weil es zum neuen Verhalten passt. Ich schätze, was ich hätte sagen sollen, anstatt im Workaround nach this zu suchen, ist: Erweitern wir den Parameterteil davon!

Ich schwöre, ich habe irgendwo gelesen, dass Sie so etwas tun können:

describe('a slow thing', () => {
 // test code...
}).timeout(5000);

was den Parametervertrag nicht an die bereitgestellte Funktion ändert. Jetzt kann ich keinen Hinweis auf so etwas finden, also habe ich es mir vielleicht nur eingebildet.

@thom-nic das funktioniert! Ich denke, es macht Sinn, da alle Funktionen von Mocha ihren Kontext zurückgeben

return this;

Bei mir funktioniert es beim Ersetzen der Pfeilfunktionsform durch die normale Funktion

Funktion() { ..... }

Hallo Leute. Ich entschuldige mich dafür, dass ich nach dem Entzünden der Diskussion im August dunkel geworden bin, ich war ziemlich beschäftigt und habe diese Arbeit größtenteils abgeschlossen / fortgeführt.

Ich schätze die detaillierte Antwort auf die verschiedenen Anwendungsfälle und wie schwierig es ist, sie miteinander zu verzahnen. Das war die prägnanteste Darstellung der verschiedenen Setups, die Mokka unterstützen muss, die ich gelesen habe. Also danke für deine Zeit dafür.

Rückblickend ist es klar, dass ich den Zugang zum Mokka-Kontext ( this ) überbetont haben muss, obwohl dieser Aspekt eigentlich eher ein bequemer Nachdenken war. Mir war nicht klar, wie leicht es die Aufmerksamkeit von dem ablenken würde, was ich eigentlich versuchte: Es machte Spaß, indem ich dem Test-DSL eine temporale Erweiterung ( when ) hinzufügte, um einzelne zu rationalisieren Zeitüberschreitungsanpassungen (plus Beseitigung eines häufigen Fehlers für einen bestimmten Teststil, den ich weiter unten erläutern werde). Die Rückgabe von this war nur eine weitere lustige Sache, die ich hinzufügen wollte. Die Hauptidee (daher der Name when ) bestand darin, Fälle zu behandeln, die andere Zeitüberschreitungen als normal benötigten.

Wenn ich auf den gebundenen Kontext zugreifen wollte, könnte ich natürlich einfach function direkt verwenden, wie viele vorgeschlagen haben, anstatt ihn mit einem Wrapper herauszuziehen. Das ist nicht das Problem. 😄 Es ist mir nicht entgangen, wie seltsam das auf den ersten Blick erscheinen mag. Ich hoffe, dass es das Bild vielleicht abrundet, wenn ich zeige, wie ich einige der Tests eingerichtet habe, die mich zunächst auf diesen Weg geführt haben. Um es klar zu sagen, ich versuche hier nicht, einen bestimmten Stil zu verkaufen, sondern zu verwenden, was für Sie funktioniert. Das hat bei mir funktioniert.

Okay
Beginnen Sie zunächst mit der Annahme, dass wir ein Setup testen, das im Wesentlichen eine Funktion erfüllt, dies jedoch für eine Vielzahl von Eingaben tut. Daher müssen wir diese Sache in einer Reihe von Szenarien testen, um sicherzustellen, dass die Ausgaben korrekt sind . Da der jeweilige Anwendungscode jedoch „eine Sache“ macht, ist die zugrunde liegende Testprozedur so gut wie immer gleich. Ich möchte den Testkörper auch nicht unnötig duplizieren / mutieren, da dies verlangsamt, wie schnell ich weitere Testfälle für neue Eingaben hinzufügen kann und die Wartung schließlich unzumutbar würde.

Stattdessen schreiben wir eine Funktion, die allgemein genug ist, um den Anwendungscode mit allen potenziell unterstützten Eingaben zu starten, die Testaktion durchzuführen und dann die Ergebnisse zu bestätigen ... Fügen Sie hinzu, dass ich in meinem Fall mit der Promise-Abstraktion gearbeitet habe (aus Gründen, die Ich lasse es weg), also muss diese verallgemeinerte Testverfahrensfunktion natürlich diese Versprechen.dann-Kette zurückgeben. Brot und Butter es6 Sachen, so weit so gut.

Jetzt kommen die Testszenarien, da wir alles in unsere Testverfahrensfunktion gepackt haben, die Testfälle definieren effektiv die Eingaben und rufen die Funktion auf.

Vielleicht schreibe ich also eine Reihe von Tests wie diesen, und alles _scheint_ zu funktionieren:

it('does something', function() {
  testProcedureFunction('something','1')
})

Wenn Sie genau mitverfolgen, haben Sie wahrscheinlich schon bemerkt, dass dieses Beispiel einen Fehler enthält. Es fehlt sein return , und da testProcedureFunction auf Promises aufbaut (Wortspiel beabsichtigt), wird es immer erfolgreich sein, egal ob die Assertionen am Ende erfolgreich sind oder fehlschlagen. Dies ist ein Fehler, und es kann manchmal sehr subtil sein, ihn aufzuspüren. Zur Veranschaulichung, je nachdem, wie wir testProcedureFunction geschrieben haben und wie die Anwendung geschrieben ist, nehmen wir an, dass es zu Beginn etwas synchronen Code gibt, der anstelle der Testende-Assertionen explodiert, der Testfall könnte sogar fehlschlagen - was uns anführt zu denken, dass alles in Ordnung ist.

Der Test sollte natürlich mit einer Rückgabe wirklich so aussehen:

it('does something', function() {
  return testProcedureFunction('something','1')
})

Jetzt weiß ich, dass dieser Test in den meisten Fällen eine Zeile sein wird. Tatsächlich ist jeder Fall eine Zeile, außer wenn die Eingaben so sind, dass eine größere Zeitüberschreitung erforderlich ist. Unter den Unterschieden zwischen klassischen js-Funktionen und Pfeilen gibt es einen besonderen Aspekt von Pfeilfunktionen, der hier nützlich ist: Eine Pfeilfunktion mit einer einzelnen Anweisung hat eine implizite Rückgabe, wenn geschweifte Klammern weggelassen werden. Wenn ein Test, anstatt function {...} schreiben, => ... , kann ich diese Fälle leicht nach dem Pfeil und dem Fehlen von geschweiften Klammern durchsuchen und schnell folgern, dass sie dieses fehlende return nicht haben können

Wie so:

it('does something', () => testProcedureFunction('something','1'))

Was nun, wenn einer dieser Fälle länger dauert als die anderen! Wir können das Timeout natürlich so einstellen:

it('does something slow', function() {
  this.timeout(10000)
  return testProcedureFunction('somethingSlow','2')
})

Oder vielleicht macht jemand einen Fehler und tut dies zuerst (was natürlich nicht funktioniert):

it('does something slow', () => {
  this.timeout(10000)
  return testProcedureFunction('somethingSlow','2')
})

Aber jetzt sind wir wieder da, wo wir angefangen haben, die Codebasis hat ein Muster, das reif für die Wiederholung ist, das anfällig für den fehlenden Rückgabefehler ist (entweder von mir oder der nächsten Person, die ein Feature hinzufügt - der Punkt ist, es ist einfach machen, kann es unbemerkt bleiben und es kann schwer sein, es aufzuspüren). Die Funktion when löst dies und lässt uns wieder konsequent Pfeile verwenden:

it('does something slow', when(() => testProcedureFunction('somethingSlow','2'), 10000))

(Anmerkung, ich war nicht in der Lage, den obigen Vorschlag zur Punktverkettung von .timeout(5000) Laufen zu bringen, möglicherweise lag es an der Version von Mokka, die ich verwenden musste, ich erinnere mich nicht mehr, werde das geben Versuchen!)
(Anmerkung2, beachten Sie, dass die Verwendung von when nicht den this Parameter-Hebe-Trick verwendet - es war wirklich nur ein nachträglicher Gedanke).

Vielleicht gibt es Linters, die fehlende Returns-for-Promise-Bugs markieren können (oder wahrscheinlich realistischer, eine return-Anweisung mit einem rhs für jede Funktion erzwingen). Dies war jedoch zu dieser Zeit keine Option, und ich denke, die Pfeilsyntax ist kürzer und ich finde sie (subjektiv / persönlich) einfacher zu lesen und zu bearbeiten, was für mich die Waage von function kippte .

Da hast du es also.

Ich weiß nicht, ob ich bald wieder Zeit haben werde, um zu antworten, also hoffe ich, dass das zumindest informativ und klar war und vielleicht sogar einige der Kontroversen um den gesamten "Zugang zum Mokka-Kontext von Pfeilen" auf den Punkt bringt Bett.

Da ich Funktion vs => lange Zeit verwirrend fand, lasse ich diesen Link schließlich fallen, falls nicht klar ist, warum Pfeile nicht auf this zugreifen können. Es war die klarste Erklärung von Funktionen und Pfeilen, die ich gefunden habe, und hat mir geholfen, die Unterschiede endlich gut genug zu verstehen, um sie mit vollem Vertrauen zu verwenden.

https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/

@thom-nic Es funktioniert auf it , aber nicht auf describe .

describe('my test suite', () => {

  it('test case 1', () => {
    // ...
  }).timeout('10s');  // Works on `it`. This test case doesn't timeout

  it('test case 2', () => {
    // ...
  });  // This test case timeouts.

}).timeout('10s');  // Doesn't work on `describe`. Tests are already created when runs to here.

@thom-nic , Sie können die normale Funktionsform verwenden

describe('my test suite', function() {
this.timeout(n);

...
}

Wer sich darüber beschwert, versteht die Pfeilfunktionen nicht.

Pfeilfunktionen sind KEINE neue schicke Sache ES6 soll das klassische function () {} ersetzen. Der einzige Zweck von Pfeilfunktionen besteht darin, dass sie this von ihrem übergeordneten Element erbt, während das klassische function () seine eigenen this .

Ja, selbst wenn Sie die vollständige ES6-Syntax verwenden, sollten Sie immer noch function () wenn Sie this im richtigen Kontext Ihrer Funktion verwenden möchten. Sie sollten in Ihrer ES6-Anwendung sowohl function () als auch () => je nachdem, was Sie tun möchten.

this.timeout() funktioniert nicht mit it('....', () => { ... }) weil der Callback this von der übergeordneten describe() Funktion erbt, in der this.timeout() dies nicht tut auf dieser Ebene sinnvoll.

Ermöglichen Lambda-Funktionen Ihnen nicht auch, automatisch ein einzelnes Argument an die Funktion zu senden, ohne es im Aufruf zu deklarieren?

(param)=>aFunktion
...dann(aFunktion)

function(){} kann an 'this' gebunden werden, aber ()=> ist 'eingesperrt'

Pfeilfunktionen sollten die traditionelle Funktion ersetzen, wenn der Empfänger ein vorgegebenes 'this' im selben Kontext erwartet , aus dem er aufgerufen wird (und auch davon profitieren, weniger Code einzugeben).

Ich würde sogar so weit gehen zu sagen, dass ich nie function() verwende, es sei denn, Sie möchten, dass 'this' etwas anderes ist als 'this', wenn Sie es aufrufen.

@Flamenco...

Ermöglichen Lambda-Funktionen Ihnen nicht auch, automatisch ein einzelnes Argument an die Funktion zu senden, ohne es im Aufruf zu deklarieren?

Ich bin mir nicht sicher, ob ich _genau_ verstehe, wie Sie das ausdrücken.
Was das "Senden von Argumenten an die Funktion" angeht, funktionieren fette Pfeile wie normale Funktionen mit einer einzigen Ausnahme: Wenn Sie genau 1 Argument haben, können Sie die Klammer weglassen.

() => console.log("hi"); //zero arguments requires empty parenthesis
a => console.log(a); //you can optionally leave the parenthesis off for 1 argument
(a,b) => console.log(`${a} ${b}`); //2..n arguments requires parenthesis

Was Sie vielleicht erreicht haben ist, dass Sie mit dicken Pfeilen einen Wert _zurückgeben_ können, indem Sie die geschweiften Klammern und das Schlüsselwort return weglassen, solange Ihre Funktion ein einzelner Ausdruck ist.
Also wenn du...

setTimeout(function(a,b) { doSomething(); return calculateSomething(a,b); }, 5000);

...und Sie dies in eine Fettpfeilfunktion umwandeln wollten, könnten Sie die geschweiften Klammern und das Schlüsselwort return nicht verschieben, da der Funktionsrumpf mehrere Anweisungen enthält. Du würdest es so machen...

setTimeout((a,b) => { doSomething(); return calculateSomething(a,b); }, 5000);

Wenn Sie eher mit...

setTimeout(function(a,b) { return calculateSomething(a,b); }, 5000);

... dann haben Sie es mit einer Funktion zu tun, die so einfach ist, dass sie nur einen einzigen Ausdruck zurückgibt und Sie verwenden könnten ...

setTimeout((a,b) => calculateSomething(a,b), 5000);

Das ist viel einfacher zu lesen!
Ich habe ein bisschen mehr darüber unter codefoster.com/levelup-arrays geschrieben .

Es gibt viele verschiedene Codierungsstile in JavaScript – von OOP bis FP, von strikter Typsicherheit bis hin zu Mixin/Duck-Typing. Darüber hinaus gibt es in jedem dieser Stile fortgeschrittene Muster (zB Abhängigkeitsinjektion im OOP-Lager, Currying/Monade im FP-Lager).

Wenn Ihr Codierungsstil näher an FP ist, wo this nicht verwendet wird und Pfeilfunktionen verwendet werden, um die Boilerplate zu reduzieren, ist die Beibehaltung von this ein zusätzlicher Aufwand für erweitertes Testen (z. B. parametrisiertes Testen, Erstellen von DSL).

Jeder erfahrene Entwickler kann das Test-Framework einfach so umwickeln, dass es seinem Codierungsstil entspricht, aber das bedeutet, dass das Framework weniger "out-of-the-box" ist. Das bedeutet zusätzliche Arbeit für Upgrades, die Einführung von Plugins und das Onboarding neuer Ingenieure.

Ich mag die Idee einer alternativen bdd Schnittstelle, die nicht this und stattdessen das, was normalerweise das Kontextobjekt wäre, als Parameter an describe , it übergibt

Aber es ist nicht so einfach zu implementieren, IIRC. Wäre aber cool, einen Versuch zu sehen.

Ich weiß, dass dies in ernsthafte Nebeneffekte gerät, aber könnten Sie nicht so etwas mit dem Done-or-Context-Parameter umgehen?

it("runs immediately", () => {
  // call functions and assert whatever
})
it("runs asynchronously", doneOrContext => {
  setTimeout(() => {
    // call functions and assert whatever
    doneOrContext();
  }, 100)
})



md5-b1fe6f00c87a2916712cf6a4df16e142



it("runs immediately using the parameter as a context", doneOrContext => {
  doneOrContext.configureByMutation("some value");
  // As well as changing config, also flags to Mocha that this test is treating the
  // parameter as a context object and is therefore not async.
  // Call functions and assert whatever
})



md5-b1fe6f00c87a2916712cf6a4df16e142



it("runs asynchronously using the parameter as a context", doneOrContext => {
  doneOrContext.configureByMutation("some value");
  doneOrContext.setAsync(); // Flags to Mocha that even though the parameter has been used as
  // a context object, the test is in fact asynchronous.
  setTimeout(() => {
    // call functions and assert whatever
    doneOrContext();
    // or doneOrContext.done()
  }, 100)
})

Ich habe das folgende Skript verwendet, aber ich habe den gleichen Timeout-Überschreitungsfehler erhalten.

Mein Skript:

describe("getBillingDetail", asynchrone Funktion (){
this.timeout(55000);
it.only("Überprüfe einen gültigen Jobnamen",async-Funktion (erledigt){
this.timeout(55000);
var result = wait url.getBillingDetail('12254785565647858');
Konsole.log (Ergebnis);
behaupten.equal(Ergebnis,wahr);
});
});

Fehler: Timeout von 55000ms überschritten. Stellen Sie bei asynchronen Tests und Hooks sicher, dass "done()" aufgerufen wird; Wenn Sie ein Versprechen zurückgeben, stellen Sie sicher, dass es aufgelöst wird.

Übergeben Sie einen abgeschlossenen Rückruf nicht an eine asynchrone Funktion

Ich habe eine Prototyplösung erstellt, die abwärtskompatibel ist. Im Moment ist es ein separates Modul, aber die Funktionalität könnte leicht in mocha .

https://github.com/papercuptech/mocha-lambda

schneller Weg

require('mocha-lambda')
// now a global '_tst' can be used where 'this' was before

describe('suite', () => {
  beforeEach(() => {
    _tst.answer = 42
  })

  it('provides "this" as "_tst"', function() {
    assert(this === _tst)
  })

  it('works', () => {
    assert(_tst.answer === 42)
    _tst.skip()
  })
})

zur expliziten Benennung (und funktioniert mit TypeScript)

// if you were previously explicitly importing api (describe, it, etc.) from 'mocha',
// you will have to change to importing from 'mocha-lambda', until (or if) this
// gets merged into mocha proper
import ctx, {describe as d, it as i} from 'mocha-lambda'

d('suite', () => {
  // ctx() is a function that returns "this" as appropriate
  i('works using ctx()', () => {
    ctx().skip()
  })
})

import {Context} from 'mocha'
// ctx() can also rename global
ctx('t')
declare var t: Context
d('suite', () => {
  // ctx() is a function that returns "this" as appropriate
  i('works using renamed global', () => {
    t.skip()
  })
})

@papercuptech Der Link ist 404 nicht gefunden.

Woops.. war ein privates Repo. jetzt öffentlich

Kann auch npm i mocha-lambda

@aleung @linesh-simplicity, dies wird durch #3485 ersetzt

Vielen Dank.

Warum so viel "Magie", die am Ende Probleme macht? Warum nicht das?:

var mocha = require('mocha');

mocha.describe('foo', (suite) => {
  suite.timeout(100);

  suite.it('must love bar', () => ... );  
});

Keine Globals, keine problematische Magie... sondern nur JavaScript.

siehe @thom-nic Antwort, sauber und hat den Trick gemacht

Ich schwöre, ich habe irgendwo gelesen, dass Sie so etwas tun können:

describe('a slow thing', () => {
 // test code...
}).timeout(5000);

was den Parametervertrag nicht an die bereitgestellte Funktion ändert. Jetzt kann ich keinen Hinweis auf so etwas finden, also habe ich es mir vielleicht nur eingebildet.

@thom-nic Lösung hat bei mir funktioniert, danke!

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen