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 insharedTestTeardown
verursachen kann)this.eventsFireStub
this.sharedCleanup
(mitaddMessageToCleanup
undaddBlockTypeToCleanup
verwenden) (HINWEIS: Sie müssenaddBlockTypeToCleanup
nicht verwenden, wenn Sie den Block mitdefineBlocksWithJsonArray
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 undaddBlockTypeToCleanup
. - 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 undsharedTestTeardown.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 definierenthis.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 vonsharedTestTeardown
- 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 SieworkspaceTeardown.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 zuerstworkspaceTeardown.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 erworkspaceTeardown.call(this, this.workspace)
erneut in der Teardown von für diese innere Suite.
- Wenn Sie
Teststruktur
Unittests folgen in der Regel einer festgelegten Struktur, die sich zusammenfassen lässt als Anordnung, Ausführung, Bestätigung.
- Anordnung: Legen Sie den Status der Welt und alle erforderlichen Bedingungen für das zu testende Verhalten fest.
- Act (Aktion): Rufen Sie den zu testenden Code auf, um das zu testende Verhalten auszulösen.
- 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
undteardown
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 duactual
undexpected
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.
- 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). - 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.
- 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. - 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. - 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. - 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. - 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
- Laden Sie
tests/generators/index.html
in einem Browser. - 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.
- Nehmen Sie alle gewünschten Änderungen oder Ergänzungen an den Blöcken vor.
- Klicken Sie auf „XML“.
- Kopieren Sie die generierte XML-Datei in die entsprechende Datei in
tests/generators/
.