Einheitentests

Nach dem Ändern oder Hinzufügen von Code sollten Sie vorhandene Einheitentests ausführen und noch mehr zu schreiben. Alle Tests werden in der unkomprimierten Version des Codes ausgeführt.

Es gibt zwei Sätze von Einheitentests: JS-Tests und Blockgenerator-Tests.

JS-Tests

Die JS-Tests bestätigen die Funktionsweise der internen JavaScript-Funktionen im Blockly-Kern. Wir verwenden Mocha, um Einheitentests durchzuführen, Sinon in Stub-Abhängigkeiten und Chai, um Aussagen zum Code zu machen.

Laufende Tests

Sowohl in Blockly als auch in Blockly-Samples führt npm run test die Unit-Tests aus. In Blockly werden dadurch auch andere Tests wie Lint und Kompilierung ausgeführt. Sie können tests/mocha/index.html auch in einem Browser öffnen, um alle Mocha interaktiv auszuführen Tests durchführen.

Tests schreiben

Für Tests wird die Mocha TDD-Oberfläche verwendet. Tests sind in Suiten organisiert, die sowohl zusätzliche untergeordnete Suiten als auch Tests enthalten kann. Im Allgemeinen Komponente von Blockly (z. B. toolbox oder workspace) hat eine eigene Testdatei die eine oder mehrere Suiten enthält. Jede Suite kann eine setup- und eine teardown-Methode haben, die jeweils vor und nach jedem Test in dieser Suite aufgerufen werden.

Test-Hilfsprogramme

Wir haben eine Reihe von Hilfsfunktionen speziell für Blockly, die nützlich sein können, das Schreiben von Tests. Diese finden Sie in Core-Prozessor und in blockly-Samples.

Zu den Hilfsfunktionen gehören sharedTestSetup und sharedTestTeardown, die Sie müssen vor und nach den Tests aufgerufen werden (siehe „Anforderungen“ Abschnitt).

sharedTestSetup:
  • Richtet falsche Timer ein (in einigen Tests müssen Sie this.clock.runAll.
  • Stubs für Blockly.Events.fire, die sofort ausgelöst werden (konfigurierbar).
  • Hiermit wird die automatische Bereinigung von blockTypes eingerichtet, die über defineBlocksWithJsonArray definiert wurden.
  • Deklariert einige Eigenschaften im this-Kontext, die barrierefrei:
    • this.clock (sollte aber nicht wiederhergestellt werden, da dies Probleme in sharedTestTeardown verursachen kann)
    • this.eventsFireStub
    • this.sharedCleanup (mit addMessageToCleanup und addBlockTypeToCleanup verwenden) (HINWEIS: Sie müssen addBlockTypeToCleanup nicht verwenden, wenn Sie den Block mit defineBlocksWithJsonArray definiert haben)

Die Funktion hat einen optionalen options-Parameter zum Konfigurieren der Einrichtung. Derzeit wird es nur verwendet, um zu bestimmen, ob Blockly.Events.fire sofort ausgelöst werden soll (standardmäßig wird ein Stub erstellt).

sharedTestTeardown:
  • Löscht den Arbeitsbereich this.workspace (je nachdem, wo er definiert wurde, siehe Abschnitt zu Testanforderungen).
  • Stellt alle Stubs wieder her.
  • Bereinigt alle über defineBlocksWithJsonArray hinzugefügten Blocktypen und addBlockTypeToCleanup.
  • Alle Nachrichten, die über addMessageToCleanup hinzugefügt wurden, werden bereinigt.

Testanforderungen

  • Jeder Test muss sharedTestSetup.call(this); als erste Zeile im der äußersten Suite und sharedTestTeardown.call(this); als letzte Zeile im Teardown der äußersten Suite für eine Datei.
  • Wenn Sie einen Arbeitsbereich mit einer generischen Toolbox benötigen, können Sie eine der voreingestellte Toolboxes beim Test index.html. Unten finden Sie ein Beispiel.
  • Sie müssen this.workspace ordnungsgemäß entsorgen. In den meisten Tests definieren this.workspace in der äußersten Suite und verwenden sie für alle nachfolgenden Tests durchführen, aber in manchen Fällen können Sie diese auch in einer inneren Suite definieren oder neu definieren. (Für einen Ihrer Tests ist z. B. ein Arbeitsbereich mit verschiedenen Optionen erforderlich) als ursprünglich eingerichtet). Sie muss am Ende der Prüfung entsorgt werden.
    • Wenn Sie this.workspace in der äußersten Suite definieren und nie neu definieren, sind keine weiteren Maßnahmen erforderlich. Sie wird automatisch entsorgt von sharedTestTeardown
    • Wenn Sie this.workspace zum ersten Mal in einer inneren Suite definieren (d. h. nicht in der äußersten Suite), müssen Sie es manuell beseitigen, indem Sie workspaceTeardown.call(this, this.workspace) beim Abbau dieser Suite aufrufen.
    • Wenn Sie this.workpace in der äußersten Suite definieren, dann aber neu definieren in einer inneren Testsuite verwenden möchten, müssen Sie zuerst workspaceTeardown.call(this, this.workspace) bevor sie neu definiert werden um den ursprünglichen Arbeitsbereich zu entfernen, der in der Suite der obersten Ebene definiert wurde. Ich muss den neuen Wert auch manuell entfernen, indem er workspaceTeardown.call(this, this.workspace) erneut in der Teardown von für diese innere Suite.

Teststruktur

Unittests folgen in der Regel einer festgelegten Struktur, die sich zusammenfassen lässt als Anordnung, Ausführung, Bestätigung.

  1. Anordnung: Legen Sie den Status der Welt und alle erforderlichen Bedingungen für das zu testende Verhalten fest.
  2. Act (Aktion): Rufen Sie den zu testenden Code auf, um das zu testende Verhalten auszulösen.
  3. Assert: Assertions in Bezug auf den Rückgabewert oder Interaktionen mit simuliert, um deren Richtigkeit zu überprüfen.

Bei einem einfachen Test gibt es möglicherweise kein Verhalten, das eingerichtet werden muss. Die Phasen „Aktion“ und „Bestätigung“ können kombiniert werden, indem der Aufruf des zu testenden Codes in die Bestätigung eingefügt wird. Bei komplexeren Fällen sind Ihre Tests besser lesbar, drei Phasen.

Hier sehen Sie eine Beispieltestdatei, die vereinfacht ist.

suite('Flyout', function() {
  setup(function() {
    sharedTestSetup.call(this);
    this.toolboxXml = document.getElementById('toolbox-simple');
    this.workspace = Blockly.inject('blocklyDiv',
        {
          toolbox: this.toolboxXml
        });
  });

  teardown(function() {
    sharedTestTeardown.call(this);
  });

  suite('simple flyout', function() {
    setup(function() {
      this.flyout = this.workspace.getFlyout();
    });
    test('y is always 0', function() {
      // Act and assert stages combined for simple test case
      chai.assert.equal(this.flyout.getY(), 0, 'y coordinate in vertical flyout is 0');
    });
    test('x is right of workspace if flyout at right', function() {
      // Arrange
      sinon.stub(this.flyout.targetWorkspace, 'getMetrics').returns({
        viewWidth: 100,
      });
      this.flyout.targetWorkspace.toolboxPosition = Blockly.TOOLBOX_AT_RIGHT;
      this.flyout.toolboxPosition_ = Blockly.TOOLBOX_AT_RIGHT;

      // Act
      var x = this.flyout.getX();

      // Assert
      chai.assert.equal(x, 100, 'x is right of workspace');
    });
  });
});

Beachten Sie bei diesem Beispiel Folgendes:

  • Eine Suite kann weitere Suiten mit zusätzlichen setup und teardown umfassen .
  • Jede Suite und jeder Test hat einen aussagekräftigen Namen.
  • Chai-Assertions werden verwendet, um Assertions für den Code zu erstellen.
    • Sie können ein optionales Stringargument angeben, das angezeigt wird, wenn der Test fehlschlägt. Dies vereinfacht die Fehlerbehebung bei fehlerhaften Tests.
    • Die Reihenfolge der Parameter ist chai.assert.equal(actualValue, expectedValue, optionalMessage). Wenn du actual und expected tauschst, sind die Fehlermeldungen nicht sinnvoll.
  • Sinon wird verwendet, um Methoden zu stützen, wenn Sie den eigentlichen Code nicht aufrufen möchten. In Hier wollen wir nicht die reelle Messwertfunktion aufrufen, ist für diesen Test nicht relevant. Uns ist nur wichtig, wie die Ergebnisse die zu testende Methode. Sinon erstellt einen Stub für die getMetrics-Funktion, um einen eine Antwortvorlage, die wir in unseren Testaussagen leicht wiederfinden können.
  • Die setup-Methoden für jede Suite sollten nur eine allgemeine Einrichtung enthalten, die gilt für alle Tests. Wenn ein Test für ein bestimmtes Verhalten von einer bestimmten Bedingung abhängt, sollte diese Bedingung im entsprechenden Test klar angegeben sein.

Tests zur Fehlerbehebung

  • Sie können die Tests in einem Browser öffnen und mit den Entwicklertools Haltestellen festlegen, um zu prüfen, ob Ihre Tests unerwartet fehlschlagen (oder unerwartet bestehen).
  • Legen Sie für einen Test oder eine Suite .only() oder .skip() fest, um nur diesen Test bzw. diese Suite auszuführen oder einen Test zu überspringen. Beispiel:

    suite.only('Workspace', function () {
      suite('updateToolbox', function () {
        test('test name', function () {
          // ...
        });
        test.skip('test I don’t care about', function () {
          // ...
        });
      });
    });
    

    Denken Sie daran, diese zu entfernen, bevor Sie Ihren Code committen.

Block Generator Tests

Für jeden Block gibt es eigene Unit-Tests. Diese Tests prüfen, ob Blöcke generiert als beabsichtigt funktioniert.

  1. Lade tests/generators/index.html in Firefox oder Safari. Chrome und Opera haben Sicherheitseinschränkungen, die das Laden der Tests über das lokale „file://“-System verhindern (Probleme 41024 und 47416).
  2. Wählen Sie im Drop-down-Menü den entsprechenden Teil des Systems aus, den Sie testen möchten, und klicken Sie auf „Laden“. Die Blöcke sollten im Arbeitsbereich angezeigt werden.
  3. Klicken Sie auf „JavaScript“.
    Kopieren Sie den generierten Code und führen Sie ihn in einer JavaScript-Konsole aus. Wenn die Ausgabe endet mit „OK“ bestätigen, ist der Test erfolgreich.
  4. Klicken Sie auf „Python“.
    Kopieren Sie den generierten Code und führen Sie ihn in einem Python-Interpreter aus. Wenn die Ausgabe mit „OK“ endet, war der Test erfolgreich.
  5. Klicken Sie auf "PHP".
    Kopieren Sie den generierten Code und führen Sie ihn in einem PHP-Interpreter aus. Wenn die Ausgabe mit „OK“ endet, ist der Test erfolgreich.
  6. Klicken Sie auf „Lua“.
    Kopieren Sie den generierten Code und führen Sie ihn in einem Lua-Interpreter aus. Wenn die Ausgabe mit „OK“ endet, ist der Test erfolgreich.
  7. Klicken Sie auf „Dart“.
    Kopieren Sie den generierten Code und führen Sie ihn in einem Dart-Interpreter aus. Wenn die Ausgabe mit „OK“ endet, ist der Test erfolgreich.

Blockgenerator-Tests bearbeiten

  1. Laden Sie tests/generators/index.html in einem Browser.
  2. Wählen Sie im Drop-down-Menü den entsprechenden Teil des Systems aus und klicken Sie auf „Laden“. Blöcke sollten im Arbeitsbereich angezeigt werden.
  3. Nehmen Sie alle gewünschten Änderungen oder Ergänzungen an den Blöcken vor.
  4. Klicken Sie auf „XML“.
  5. Kopieren Sie die generierte XML-Datei in die entsprechende Datei in tests/generators/.