Heim - Windows
Einführung in die testgetriebene Entwicklung in JavaScript. Tests zur Kenntnis von Web-Technologien. Testen von Javascript

Bei großen Projekten, bei denen sich das Verhalten von Teilen der Anwendung aus verschiedenen Gründen ändern kann, kann die Erstellung effektiver Testfälle äußerst wichtig sein. Das vielleicht häufigste Problem entsteht, wenn eine große Gruppe von Entwicklern an denselben oder verwandten Modulen arbeitet. Dies kann zu ungeplanten Änderungen im Verhalten von Funktionen führen, die von anderen Programmierern geschrieben wurden. Oder das Arbeiten unter engen Fristen führt zu unbeabsichtigten Änderungen an kritischen Teilen der Anwendung.

Das Testen einer Webanwendung umfasst in der Regel die visuelle Beurteilung von Seitenelementen und die empirische Beurteilung der Funktionalität der Funktionalität. Mit anderen Worten, beim Navigieren durch Abschnitte und beim Ausführen von Aktionen an dynamischen Elementen.

Im Laufe der Zeit wird das Projekt mit Neuem gefüllt Funktionalität, was den Prozess der Funktionsüberprüfung verlängert und erschwert. Zur Automatisierung werden Unit-Tests verwendet.

Es gibt zwei Ansätze zum Erstellen von Testszenarien:

  • Whitebox-Testing – Das Schreiben von Tests basiert auf der Implementierung von Funktionalität. Diese. Wir prüfen mit denselben Algorithmen, auf denen die Arbeit unserer Systemmodule basiert. Dieser Ansatz garantiert nicht den korrekten Betrieb des Systems als Ganzes.
  • Blackbox-Tests – Die Skripterstellung basiert auf Systemspezifikationen und -anforderungen. Auf diese Weise können Sie die Richtigkeit der Ergebnisse der gesamten Anwendung überprüfen, aber mit diesem Ansatz können Sie kleine und seltene Fehler nicht erkennen.
Was zu testen ist

Es mag den Anschein erwecken, dass es sich lohnt, jede implementierte Funktion zu testen. Das ist nicht ganz richtig. Das Schreiben von Tests nimmt die Zeit eines Entwicklers in Anspruch. Um den Prozess der Anwendungserstellung zu optimieren, lohnt es sich daher, Tests nur für komplexe, kritische Funktionen oder für Funktionen vorzubereiten, die von den Ergebnissen anderer Systemmodule abhängen. Decken Sie mehrdeutige Logik mit Tests ab, die potenziell Fehler verursachen könnten. Es lohnt sich auch, Tests für diejenigen Codeabschnitte zu erstellen, die in Zukunft optimiert werden sollen, damit Sie nach dem Optimierungsprozess überprüfen können, ob sie korrekt ausgeführt werden.

Im Allgemeinen ist es äußerst wichtig, die Testkosten im Verhältnis zur Enge der Entwicklungsfristen zu bewerten. Wenn Sie zeitlich nicht begrenzt sind, können Sie natürlich zulassen, dass jede Funktion mit Tests abgedeckt wird. Da die Entwicklung jedoch in der Regel unter hohem Zeitdruck erfolgt, besteht die Aufgabe eines Analysten oder eines erfahrenen Entwicklers darin, zu verstehen, wo Tests erforderlich sind. Darüber hinaus erhöht das Schreiben von Tests die Kosten des Projekts.

Somit können wir drei Fälle formulieren, in denen der Einsatz von Unit-Tests gerechtfertigt ist:

1) Wenn Tests es ermöglichen, Fehler schneller zu erkennen als bei der normalen Suche.

2) Reduzieren Sie die Debugging-Zeit

3) Ermöglicht das Testen von häufig geändertem Code.

Von den 3 Hauptkomponenten des Frontends (HTML, CSS, JavaScript) muss möglicherweise nur der JavaScript-Code getestet werden. Es wird ausschließlich CSS geprüft visuelle Methode, wenn der Entwickler/Tester/Kunde die GUI in verschiedenen Browsern betrachtet. HTML-Markup wird mit der gleichen Methode überprüft.

So testen Sie

Bei der Erstellung von Testszenarien sollten Sie sich an folgenden Grundsätzen orientieren:

  • Ihre Tests sollten so einfach wie möglich sein.
  • Dann ist die Wahrscheinlichkeit größer, dass die Ergebnisse der Implementierung durch genau den Fehler beeinflusst werden, den Sie wiederholen möchten.
  • Zerlegen Sie große Unit-Tests.
  • Es ist besser, den genauen Ort des Fehlers zu finden.
  • Machen Sie Tests unabhängig.
Das Ergebnis eines Tests sollte in keiner Weise von den Ergebnissen eines anderen Tests abhängen.

Es gibt mehrere Bibliotheken zum Unit-Testen von JS-Code. Am gebräuchlichsten ist vielleicht QUnit. Um Unit-Tests mit dieser Bibliothek durchzuführen, müssen wir eine „Sandbox“ erstellen – eine einfache HTML-Seite, in der die zu testende Bibliothek, der zu testende Code und die Tests selbst verbunden werden.

Funktionen für Tests:

(function() ( window.stepen = function(int) ( var result = 2; for (var i = 1; i< int; i ++) { result = result * 2; } return result; } window.returnFunc = function() { return "ok"; } })();

Testliste:

Test("stepen()", function() ( equal(stepen(2), 4, "2^2 - equal method"); ok(stepen(3) === 8, "2^3 - ok method" ); deepEqual(stepen(5), 32, "2^5 - deepEqual-Methode"); asyncTest("returnFunc()", function() ( setTimeout(function() ( equal(returnFunc(), "ok", "Async Func Test"); start(); , 1000); ));

Wie Sie sehen, unterstützt QUnit drei Funktionen zum Vergleichen der Ergebnisse der Codeausführung mit den erwarteten:

  • ok() – betrachtet den Test als erfolgreich, wenn das zurückgegebene Ergebnis = wahr ist
  • equal() – vergleicht das Ergebnis mit dem erwarteten
  • deepEqual() – vergleicht das Ergebnis mit dem erwarteten und prüft seinen Typ

Ausführungsergebnis:

Wie Sie sehen, testet die QUnit-Bibliothek Code für mehrere Browser gleichzeitig.

Es gibt eine Reihe anderer Unit-Test-Bibliotheken. Das Konzept zum Erstellen von Testszenarien ist jedoch dasselbe. Sobald Sie also eines verstanden haben, wird es Ihnen nicht schwer fallen, zu einem anderen zu wechseln.

Wichtig zu merken

Ein Merkmal des modernen JS-Codes ist seine asynchrone Ausführung. Testbibliotheken verfügen normalerweise über die Möglichkeit, asynchrone Tests durchzuführen. Wenn Sie jedoch beispielsweise versuchen, eine Funktion zu testen, die beispielsweise eine Get-Anfrage an das Backend sendet und eine Antwort von diesem zurückgibt, müssen Sie zum Durchführen von Tests den Thread mit der Funktion stop() stoppen und starten Funktion zu testen, und starten Sie dann den Thread mit der start()-Methode neu, indem Sie ihn in setTimeout() „umschließen“. Diese. Sie müssen einen bestimmten Zeitraum festlegen, in dem die Funktion die Ausführung abschließen soll. Sie müssen die Dauer dieses Abschnitts sorgfältig auswählen. Auf der einen Seite lange Arbeit Eine Methode kann entweder eine Funktion oder sogar eine Notwendigkeit für eine bestimmte Implementierung der Anwendungsfunktionalität oder ein falsches Verhalten sein.

Testen von Backbone-Anwendungen

Als Beispiel für das Testen von Anwendungen, die mit Backbone.js geschrieben wurden, verwenden wir das in beschriebene Projekt.

Sie können Unit-Tests verwenden, um Folgendes zu überprüfen:

  • Korrekte Erstellung von Modellen und Controllern
  • Korrektheit der Daten in Modellen
  • Ausführung von Controller-Methoden (dazu müssen sie ein Ergebnis zurückgeben)
  • Zeigt den Ladeerfolg an

Testcode:

Test("Backbone.js", function() ( ok(sample, "Namespace check"); ok(sample.routers.app, "Router check"); ok(sample.core.pageManager.open("chat") , „Seitenöffnungstest (Controller-Methodenaufruf)“) ok(sample.core.state, „Model check“); equal(sample.core.state.get(“content“), „sintel“, „Model data get test " "); stop(); ok(function() ( $.ajax(( url: "app/templates/about.tpl", dataType: "text")).done(function(data) ( self.$el . html(data); return data; ))), „Vorlagenladeprüfung“;

Ergebnis der Arbeit mit Testfehlern:

Testlaufautomatisierung

Typischerweise ist die Bereitstellung einer Anwendung eine Aufgabe, die während einer intensiven Entwicklung häufig ausgeführt werden muss. Daher ist dieser Vorgang normalerweise automatisiert. In unserer Arbeit nutzen wir Jenkins, ein Tool zur kontinuierlichen Integration. Die Idee besteht darin, die Bereitstellung über Jenkins mit automatisierten Tests zu kombinieren.

QUnit-Tests werden im Browser ausgeführt. Phantomjs, eine Software, die die Funktionsweise eines Browsers emuliert, wird uns dabei helfen, diese Funktion zu umgehen. Die Entwickler von phantomjs haben bereits ein Skript zum Ausführen von QUnit-Tests bereitgestellt, das jedoch geringfügig geändert werden musste, um ordnungsgemäß zu funktionieren.

/** * Warten, bis die Testbedingung wahr ist oder eine Zeitüberschreitung auftritt.< Default Max Timout is 3s start = new Date().getTime(), condition = false, interval = setInterval(function() { if ((new Date().getTime() - start < maxtimeOutMillis) && !condition) { // If not time-out yet and condition not yet fulfilled condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code } else { if(!condition) { // If condition still not fulfilled // (timeout but condition is "false") console.log(""waitFor()" timeout"); phantom.exit(1); } else { // Condition fulfilled (timeout and/or condition is //"true") console.log(""waitFor()" finished in " + (new Date().getTime() - start) + "ms."); typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it"s supposed to do once the // condition is fulfilled clearInterval(interval); //< Stop this interval } } }, 100); // repeat check every 250ms }; }; if (phantom.args.length === 0 || phantom.args.length >2) console.log("Verwendung: run-qunit.js URL");

phantom.exit(); ) var page = new WebPage(); // „console.log()“-Aufrufe aus dem Seitenkontext // an den Haupt-Phantomkontext (d. h. das aktuelle „dies“) weiterleiten page.onConsoleMessage = function(msg) ( console.log(msg); ); page.open(phantom.args, function(status)( if (status !== "success") ( console.log("Unable to access network"); phantom.exit(); ) else ( waitFor(function() ( return page.evaluate(function())( var el = document.getElementById("qunit-testresult"); if (el && el.innerText.match("completed")) ( return true; ) return false; )) ; ), function())( var failedNum = page.evaluate(function())( var el = document.getElementById("qunit-testresult"); console.log(el.innerText); try ( return document.getElementsByClassName( "fail" ). innerHTML.length; ) catch (e) ( return 0; ) return phantom.exit((parseInt(failedNum, 10) ? 1: ));

Um Meldungen über Ergebnisse an die Konsole auszugeben, müssen Sie dem Testskript eine Protokollierungsfunktion hinzufügen.

Am Beispiel einer einfachen Taschenrechneranwendung auf Node.js. Wir werden mit dem Mocha-Framework testen.

  • Was unsere Anwendung können sollte:
  • Addiere, subtrahiere, dividiere und multipliziere zwei beliebige Zahlen;
  • Eine Warnung anzeigen und beenden, wenn etwas anderes als eine Zahl eingegeben wurde; Es muss auch eine Schnittstelle vorhanden sein Befehlszeile

damit der Endbenutzer die Anwendung nutzen kann.

  • Was wir brauchen:
  • Node.js und npm;

Kenntnisse in JavaScript: Codesyntax und -struktur, Datentypen, mathematische Operationen und bedingte Ausdrücke.

Nachdem Sie nun Ihre Ziele festgelegt haben, können Sie mit der Einrichtung Ihrer Test- und Entwicklungsumgebung beginnen.

Einrichten der Umgebung

Da wir Node.js verwenden, müssen wir eine lokale Umgebung für die Dateien und Abhängigkeiten erstellen. Erstellen neuer Ordner kalk . Gehen Sie in der Befehlszeile in dieses Verzeichnis und erstellen Sie mit dem Befehl npm init ein neues Projekt, wodurch eine neue Datei erstellt wird package.json

für unser Programm. Sie werden aufgefordert, den Paketnamen, die Version, die Beschreibung und andere Informationen zum Paket einzugeben. Sie können einen Namen eingeben calc.js weiter drücken Eingeben

Standardwerte zuzuweisen. Wenn Sie zum Testbefehl gelangen, geben Sie mocha ein – dies ist das Test-Framework, das wir verwenden werden:

Testbefehl: mocha . Gehen Sie in der Befehlszeile in dieses Verzeichnis und erstellen Sie mit dem Befehl npm init ein neues Projekt, wodurch eine neue Datei erstellt wird Nach Eingabe aller Informationen erstellt das Skript eine Datei

( „name“: „calc.js“, „version“: „1.0.0“, „description“: „Einfacher Rechner auf Node.js“, „main“: „index.js“, „scripts“: ( „ test“: „mocha“ ), „author“: „“, „license“: „ISC“ )

Letzter Schritt weiter in diesem Stadium- Installation von Mokka. Geben Sie zur Installation den folgenden Befehl ein:

Npm install --save-dev Mokka

Nach Verwendung dieses Befehls wird der Ordner angezeigt node_modules, Datei package-lock.json, und in der Datei . Gehen Sie in der Befehlszeile in dieses Verzeichnis und erstellen Sie mit dem Befehl npm init ein neues Projekt, wodurch eine neue Datei erstellt wird Es erscheinen folgende Zeilen:

„devDependencies“: („mocha“: „^4.0.1“)

Erstellen Sie eine Datei test.js. Wir werden das in Node.js integrierte Modul verwenden behaupten um zu überprüfen, ob true und true wahr sind. Da dies wahr ist, sollte der Test bestehen:

Const behaupten = require("assert"); it("sollte true zurückgeben", () => ( Assert.equal(true, true); ));

Führen Sie nun den Test über die Befehlszeile aus:

$ npm test > mocha ✓ sollte true 1 Passing (8 ms) zurückgeben

Der Test verlief wie erwartet, daher sind wir mit der Einrichtung der Umgebung fertig. Entfernen von test.js alles außer der Zeile const behaupten = require("assert"); .

Wir werden die Datei verwenden test.js während des gesamten Anwendungserstellungsprozesses. Erstellen Sie zwei weitere Dateien: operationen.js für Rechen- und Validierungsfunktionen und Sie werden aufgefordert, den Paketnamen, die Version, die Beschreibung und andere Informationen zum Paket einzugeben. Sie können einen Namen eingeben für die Anwendung selbst. Wir verwenden so viele Dateien, dass sie nicht zu lang und komplex werden. Hier ist unsere aktuelle Dateiliste:

  • Sie werden aufgefordert, den Paketnamen, die Version, die Beschreibung und andere Informationen zum Paket einzugeben. Sie können einen Namen eingeben;
  • node_modules;
  • operationen.js;
  • package-lock.json;
  • . Gehen Sie in der Befehlszeile in dieses Verzeichnis und erstellen Sie mit dem Befehl npm init ein neues Projekt, wodurch eine neue Datei erstellt wird;
  • test.js;

Fügen wir den ersten echten Test für unsere Anwendung hinzu.

Mathematische Operationen hinzufügen

Zunächst muss unsere Anwendung in der Lage sein, zwei beliebige Zahlen zu addieren, zu subtrahieren, zu dividieren und zu multiplizieren. Das bedeutet, dass wir für jede dieser Operationen eine separate Funktion erstellen müssen.

Beginnen wir mit der Addition. Wir werden einen Test schreiben, bei dem man mit Sicherheit die erwartete Summe zweier Zahlen erhält. Im folgenden Code prüfen wir mithilfe der add()-Funktion 4, ob die Summe von 1 und 3 gleich ist:

Const behaupten = require("assert"); it("findet die Summe von 1 und 3 korrekt", () => ( Assert.equal(add(1, 3), 4); ));

Nachdem wir den Test mit dem Befehl npm test ausgeführt haben, sehen wir Folgendes:

> mocha 0 bestanden (9 ms) 1 fehlgeschlagen 1) findet die Summe von 1 und 3 korrekt: ReferenceError: add is nicht definiert bei Context.it (test.js:5:16) npm ERR! Test fehlgeschlagen. Weitere Einzelheiten finden Sie oben.

Der Test ist mit der Meldung ReferenceError: add ist nicht definiert fehlgeschlagen. Wir testen die Funktion add(), die noch nicht existiert, daher ist dieses Ergebnis durchaus zu erwarten.

Erstellen wir die Funktion add() in der Datei operationen.js:

Const add = (x, y) => (+x) + (+y);

Diese Funktion benötigt zwei Argumente x und y und gibt deren Summe zurück. Sie haben vielleicht bemerkt, dass wir (+x) + (+y) statt x + y schreiben. Wir verwenden den unären Operator, um das Argument in eine Zahl umzuwandeln, falls die Eingabe eine Zeichenfolge ist.

Hinweis: Hierbei werden die in ES6 hinzugefügte Pfeilfunktion und die implizite Rückgabe verwendet.

Da wir Node.js verwenden und den Code in mehrere Dateien aufteilen, müssen wir module.exports verwenden, um den Code zu exportieren:

Const add = (x, y) => (+x) + (+y); module.exports = (hinzufügen)

Am Anfang der Datei test.js Wir importieren den Code von operationen.js mit require() . Da wir die Funktion über die Operations-Variable verwenden, müssen wir add() in Operations.add() ändern:

Const Operations = require("./operations.js"); const affirm = require("assert"); it("findet die Summe von 1 und 3 korrekt", () => ( Assert.equal(operations.add(1, 3), 4); ));

Lassen Sie uns den Test durchführen:

$ npm test > mocha ✓ ermittelt korrekt die Summe von 1 und 3 1 Pass (8 ms)

Wir haben jetzt eine funktionierende Funktion und die Tests werden bestanden. Da die anderen Operationsfunktionen ähnlich funktionieren, ist das Hinzufügen von Tests für subtract() , multiply() und Divide() einfach:

It("findet die Summe von 1 und 3 korrekt", () => ( Assert.equal(operations.add(1, 3), 4); )); it("findet die Summe von -1 und -1 korrekt", () => ( Assert.equal(operations.add(-1, -1), -2); )); it("findet den Unterschied zwischen 33 und 3 richtig", () => ( Assert.equal(operations.subtract(33, 3), 30); )); it("findet das Produkt von 12 und 12 korrekt", () => ( Assert.equal(operations.multiply(12, 12), 144); )); it("findet den Quotienten von 10 und 2 korrekt", () => ( Assert.equal(operations.divide(10, 2), 5); ));

Lassen Sie uns nun alle Funktionen erstellen und exportieren test.js:

Const add = (x, y) => (+x) + (+y); const subtract = (x, y) => (+x) - (+y); const multiply = (x, y) => (+x) * (+y); const dividieren = (x, y) => (+x) / (+y); module.exports = ( addieren, subtrahieren, multiplizieren, dividieren, )

Und lassen Sie uns neue Tests durchführen:

$ npm test > mocha ✓ ermittelt korrekt die Summe von 1 und 3 ✓ ermittelt korrekt die Summe von -1 und -1 ✓ ermittelt korrekt die Differenz von 33 und 3 ✓ ermittelt korrekt das Produkt von 12 und 12 ✓ ermittelt korrekt den Quotienten von 10 und 2 5 Durchgänge (8ms)

Alle Tests werden erfolgreich bestanden, sodass wir jetzt sicher sein können, dass die Hauptfunktionen unserer Anwendung ordnungsgemäß funktionieren. Jetzt können Sie eine zusätzliche Validierung durchführen.

Validierung hinzufügen

Wenn der Benutzer zunächst eine Nummer eingibt und den gewünschten Vorgang auswählt, funktioniert alles einwandfrei. Was passiert jedoch, wenn Sie versuchen, die Summe einer Zahl und einer Zeichenfolge zu ermitteln? Die Anwendung versucht, den Vorgang auszuführen, da sie jedoch eine Zahl erwartet, gibt sie NaN zurück.

Anstatt einen seltsamen Wert zurückzugeben, ist es an der Zeit, die zweite Aufgabe zu erledigen – dafür zu sorgen, dass die Anwendung eine Warnung anzeigt und beendet wird, wenn das eingegebene Argument keine Zahl ist.

Zuerst müssen Sie eine Funktion schreiben, die prüft, ob die Eingabe eine Zahl ist oder nicht. Die Anwendung darf nur mit Zahlen funktionieren, daher werden wir drei Situationen behandeln:

  • Beide Eingaben sind Zahlen.
  • Eine Eingabe ist eine Zahl und die andere eine Zeichenfolge.
  • Beide Eingaben sind Zeichenfolgen.
  • it("meldet einen Fehler, wenn eine Zeichenfolge anstelle einer Zahl verwendet wird", () => ( behaupten.equal(operations.validateNumbers("sammy", 5), false); )); it("meldet einen Fehler, wenn zwei Zeichenfolgen anstelle von Zahlen verwendet werden", () => ( Assert.equal(operations.validateNumbers("sammy", "sammy"), false); )); it("Erfolg bei der Verwendung von zwei Zahlen", () => ( behaupten.equal(operations.validateNumbers(5, 5), true); ));

    Die Funktion „validateNumbers()“ prüft beide Parameter. Die Funktion isNaN() prüft, ob der Parameter eine Zahl ist, und gibt andernfalls false zurück. Andernfalls wird „true“ zurückgegeben, was auf eine erfolgreiche Validierung hinweist.

    Const validierenNumbers = (x, y) => ( if (isNaN(x) && isNaN(y)) ( return false; ) return true; )

    Vergessen Sie nicht, „validateNumbers“ zu „module.exports“ am Ende der Datei hinzuzufügen. Jetzt können Sie neue Tests ausführen:

    $ npm test 1) meldet einen Fehler, wenn eine Zeichenfolge anstelle einer Zahl verwendet wird ✓ meldet einen Fehler, wenn zwei Zeichenfolgen anstelle einer Zahl verwendet werden ✓ Erfolg, wenn zwei Zahlen verwendet werden 7 bestanden (12 ms) 1 fehlgeschlagen 1) meldet einen Fehler, wenn eine Zeichenfolge verwendet wird anstelle einer Zahl: AssertionError: true == false + erwartet - tatsächlich -true +false

    Zwei Tests wurden bestanden, aber einer schlug fehl. Der Test für zwei Zahlen wurde erfolgreich bestanden, ebenso der Test für zwei Zeichenfolgen. Das Gleiche gilt nicht für die Überprüfung der Eingabe von Zeichenfolgen und Zahlen.

    Wenn Sie sich unsere Funktion noch einmal ansehen, werden Sie das bemerken beide Parameter müssen NaN sein, damit die Funktion false zurückgibt. Wenn wir den gleichen Effekt erzielen möchten, wenn mindestens einer der Parameter NaN ist, müssen wir && durch || ersetzen :

    Const validierenNumbers = (x, y) => ( if (isNaN(x) || isNaN(y)) ( return false; ) return true; )

    Wenn Sie npm test nach diesen Änderungen erneut ausführen, werden alle Tests bestanden:

    ✓ meldet einen Fehler, wenn ein String anstelle einer Zahl verwendet wird ✓ meldet einen Fehler, wenn zwei Strings anstelle einer Zahl verwendet werden ✓ Erfolgreich, wenn zwei Zahlen verwendet werden 8 übergeben (9 ms)

    Wir haben die gesamte Funktionalität unserer Anwendung getestet. Die Funktionen führen erfolgreich mathematische Operationen durch und validieren Eingaben. Der letzte Schritt ist die Erstellung der Benutzeroberfläche.

    Erstellen einer Schnittstelle

    Wir verfügen bereits über die notwendigen Funktionen, der Benutzer kann sie jedoch noch nicht nutzen. Dafür brauchen wir eine Schnittstelle. Wir werden eine Befehlszeilenschnittstelle für unsere Anwendung erstellen.

    Derzeit die Datei Sie werden aufgefordert, den Paketnamen, die Version, die Beschreibung und andere Informationen zum Paket einzugeben. Sie können einen Namen eingeben sollte leer sein. Hier wird unsere Bewerbung gespeichert. Zuerst müssen Sie Funktionen importieren operationen.js:

    Const Operations = require("./operations.js");

    Die Schnittstelle selbst verwendet das in Node.js integrierte Readline-CLI-Modul:

    Const readline = require("readline");

    Nachdem Sie alles importiert haben, was Sie benötigen, können Sie mit der Erstellung Ihrer Anwendung beginnen. Um die Schnittstelle zu erstellen, verwenden wir readline, auf das über die Variable rl zugegriffen werden kann:

    Const rl = readline.createInterface(( Eingabe: Process.stdin, Ausgabe: Process.stdout));

    Das erste, was der Benutzer nach dem Start des Programms sehen sollte, ist eine Willkommensnachricht und eine Gebrauchsanweisung. Dazu verwenden wir console.log() :

    Console.log(` Calc.js Sie haben einen Taschenrechner in Node.js geöffnet! Version: 1.0.0. Verwendung: Der Benutzer muss zwei Zahlen eingeben und dann auswählen, was mit ihnen geschehen soll. `);

    Bevor wir uns mit den Rechnerfunktionen selbst befassen, überprüfen wir, ob console.log() wie erwartet funktioniert. Wir veranlassen das Programm, eine Nachricht auszugeben und zu beenden. Fügen Sie dazu am Ende einen Aufruf der Methode rl.close() hinzu.

    Um die Anwendung auszuführen, geben Sie den Knoten- und Dateinamen ein:

    $ node calc.js Calc.js Sie haben einen Node.js-Rechner geöffnet! Version: 1.0.0. Verwendung: Der Benutzer muss zwei Zahlen eingeben und dann auswählen, was mit ihnen geschehen soll.

    Das Programm zeigt eine Willkommensnachricht an und wird beendet. Jetzt müssen wir Benutzereingaben hinzufügen. Der Benutzer muss Folgendes tun: zwei Zahlen auswählen und eine Operation ausführen. Jede Eingabe wird von der Methode rl.question() angefordert:

    Rl.question("Geben Sie die erste Zahl ein: ", (x) => ( rl.question("Geben Sie die zweite Zahl ein: ", (y) => ( rl.question(` Wählen Sie eine der folgenden Operationen: Addition ( +) Subtraktion (-) Multiplikation (*) Division (/) Ihre Wahl: `, (Auswahl) => ( // der Code rl.close(); ));

    Der Variablen x wird die erste Zahl zugewiesen, y die zweite und wählt die ausgewählte Operation aus. Jetzt bittet unser Programm um Eingaben, macht aber nichts mit den empfangenen Daten.

    Nach der dritten Eingabe müssen Sie überprüfen, ob nur Zahlen eingegeben wurden. Dazu verwenden wir die Funktion „validateNumbers()“. Mit dem NOT-Operator prüfen wir, ob Zahlen eingegeben wurden und beenden andernfalls das Programm:

    If (!operations.validateNumbers(x, y)) ( console.log("Es können nur Zahlen eingegeben werden! Bitte starten Sie das Programm neu."); )

    Wenn alles korrekt eingegeben wurde, müssen Sie nun die Methode ausführen, die der zuvor erstellten Operation entspricht. Um vier zu verarbeiten mögliche Optionen Wahl verwenden wir den Schalterausdruck und zeigen das Ergebnis der Operation an. Wenn ein nicht vorhandener Vorgang ausgewählt wurde, wird ein Standardblock ausgeführt, der den Benutzer auffordert, es erneut zu versuchen:

    If (!operations.validateNumbers(x, y)) ( console.log("Es können nur Zahlen eingegeben werden! Bitte starten Sie das Programm neu."); ) else ( switch (choice) ( case "1": console.log(` Die Summe von $(x) und $(y) ist gleich $(operations.add(x, y)).`); break; y) ist $( Operations.subtract(x, y)).`); break; case „3“: console.log(`Das Produkt von $(x) und $(y) ist $(operations.multiply(x , y)).`) ; break; case "4": console.log(`Der Quotient von $(x) und $(y) ist $(operations.divide(x, y)).`); Starten Sie das Programm neu und wählen Sie eine Zahl von 1 bis 4."); break; ) )

    Hinweis: Die console.log()-Funktionen verwenden hier Vorlagenzeichenfolgen, die Ausdrücke zulassen.

    /** * Ein einfacher Rechner in Node.js, der die Rechner-App verwendet, die * die integrierte Readline-Befehlszeilenschnittstelle verwendet.

    */ const operationen = require("./operations.js"); const readline = require("readline"); // Verwenden Sie readline, um die Schnittstelle zu erstellen const rl = readline.createInterface(( input:process.stdin, output:process.stdout)); console.log(` Calc.js Sie haben einen Taschenrechner in Node.js geöffnet! Version: 1.0.0. Verwendung: Der Benutzer muss zwei Zahlen eingeben und dann auswählen, was mit ihnen geschehen soll. `); rl.question("Geben Sie die erste Zahl ein: ", (x) => ( rl.question("Geben Sie die zweite Zahl ein: ", (y) => ( rl.question(` Wählen Sie eine der folgenden Operationen: Addition ( +) Subtraktion (-) Multiplikation (*) Division (/) Ihre Wahl: `, (Auswahl) => ( if (!operations.validateNumbers(x, y)) ( console.log("Es können nur Zahlen eingegeben werden! Bitte Starten Sie das Programm neu. "); ) else ( switch (choice) ( case "1": console.log(`Die Summe von $(x) und $(y) ist $(operations.add(x, y)). `); break; case „2“: console.log(`Der Unterschied zwischen $(x) und $(y) ist $(operations.subtract(x, y)).`); console.log(`Das Produkt von $( x) und $(y) ist gleich $(operations.multiply(x, y)).`); break; $(x) und $(y) ist gleich $(operations. Divide(x, y)).`); default: console.log("Bitte starten Sie das Programm neu und wählen Sie eine Zahl von 1 bis 4." ); brechen; ; ));

    Jetzt ist unsere Bewerbung fertig. Lassen Sie uns ein letztes Mal seine Funktion überprüfen. Geben wir 999 und 1 ein und wählen die Subtraktionsoperation aus:

    $ node calc.js Geben Sie die erste Zahl ein: 999 Geben Sie die zweite Zahl ein: 1 Ihre Wahl: 2 Die Differenz zwischen 999 und 1 beträgt 998.

    Das Programm hat seine Arbeit erfolgreich abgeschlossen und das korrekte Ergebnis geliefert. Herzlichen Glückwunsch, Sie haben mit Node.js einen einfachen Rechner geschrieben und die Grundlagen der TDD-Entwicklung erlernt. Codetests sind ein integraler Entwicklungszyklus Software

    . Neue Entwicklungsteams unterschätzen oft ihre Rolle und überprüfen die Funktionalität der Anwendung auf die altmodische Art und Weise: „Es funktioniert, okay.“ Früher oder später scheitert diese Strategie und der Bugtracker wird von einer zahllosen Armee an Aufgaben überfordert. Um nicht in eine solche Falle zu tappen, empfehle ich, sich ein für alle Mal mit den Nuancen des Testens von JavaScript-Code vertraut zu machen.

    JavaScript ist nicht mehr dasselbe Heutzutage ist JavaScript nicht nur eine Sprache, um Dinge aufzupeppen Anwendungen. Die Zeiten, in denen JavaScript für Witze oder die Erstellung von Menüs verwendet wurde, sind unwiderruflich vorbei. Es handelt sich nun um eine eigenständige Sprache, die sowohl auf dem Client als auch auf dem Server gleichermaßen gut funktioniert. Die Rolle von JavaScript hat erheblich zugenommen, was bedeutet, dass Sie beim Schreiben von Code nicht davor zurückschrecken sollten, auf Praktiken zurückzugreifen, die sich in anderen Programmiersprachen bewährt haben.

    Was meine ich mit Praktiken und Paradigmen? Natürlich das MVC-Architekturmuster (Model View Controller) und die Code-Organisationsmuster. Wenn Sie diese einfachen Tricks befolgen, können Sie besseren Code schreiben, der nicht nur einfach zu warten ist, sondern auch automatisch getestet werden kann.

    Fehler der meisten Tester

    Es ist kein Geheimnis, dass die beliebteste Testmethode schon immer ein banaler Sehtest war. Sein Wesen ist bis zur Schande einfach: Sie schreiben ein paar tausend Zeilen Code, lösen das Problem und starten Ihre Kreation. Ich habe herumgespielt, geklickt, alles schien zu funktionieren, ich konnte es auf den Produktionsserver hochladen. Alles ist äußerst einfach und mit der gebotenen Aufmerksamkeit des Entwicklers (idealerweise einer Einzelperson mit dem Spitznamen „Tester“) können Sie sich auf den korrekten Betrieb der Anwendung verlassen.

    In der Praxis läuft alles etwas anders ab. In der Regel gibt es keinen separaten Tester. Der Entwickler selbst versucht, die Funktionalität des Programms zu überprüfen, indem er die in den technischen Spezifikationen festgelegte Abfolge von Aktionen durchführt. Fortgeschrittenere Codefälschungen automatisieren diese Art von Integrationstests mithilfe von Dingen wie Selenium.

    Somit erhält der Programmierer die Möglichkeit, nur die schwerwiegendsten Fehler zu erkennen. Leider bleiben „dumme“ und „unbeabsichtigte“ Benutzeraktionen sowie raffinierte Manöver in der Geschäftslogik in 99 % der Fälle im Verborgenen.

    Auch die Anwesenheit einer separaten Person in der Person eines Testers löst das Problem teilweise und bis zu einem gewissen Zeitpunkt. Selbst wenn wir die Liebe zum Detail seines Pioniers ignorieren, wird die Qualität seiner Tests mit zunehmender Anwendung auf Null sinken. Lassen Sie mich Ihnen ein Beispiel aus der Praxis geben.

    Eines Tages wurde ich beauftragt, ein kleines Programm zu entwickeln. Von der Funktionalität her ähnelte das Projekt einem einfachen CRM, das ich in kürzester Zeit implementiert habe. Nachdem ich die fällige Vergütung erhalten hatte, übergab ich alle Quellen an den Kunden und vergaß das Projekt acht Monate lang. Dann begann der Spaß. Der Kunde beschloss, die Funktionalität des Programms ernsthaft zu erweitern und rief mich um Hilfe. Natürlich nahm ich es und begann, eine neue Funktion nach der anderen zu formen. Anfangs war es nicht schwierig, aber als es um die Gesamtintegration der Funktionalität ging, stürmte ein schwirrender Schwarm von Bugs auf mich zu. Teile des Codes begannen in Konflikt zu geraten, und wir mussten viel Zeit damit verbringen, Konflikte zu lösen. „Wie kommt es, dass Sie nicht gesehen haben, dass es bei Ihrer Bewerbung Probleme gab?“ - werden aufmerksame Leser fragen. Ich habe es gestartet, aber aufgrund der Tatsache, dass die Anwendung gewachsen ist, hatte ich einfach nicht genug Zeit und Nerven, um alle Funktionen massenhaft zu testen. Ich habe mich darauf beschränkt, nur einzelne Funktionen zu testen und dafür ordentlich bezahlt. Die Moral der Geschichte lautet: „Stellen Sie sich Tests als integralen Bestandteil der Entwicklung vor.“

    Unit-Tests sind wie eine Wunderwaffe

    Unit-Tests sind der beste Weg, um Ihre Nerven zu schonen und die Garantien für die Leistung einzelner Teile der Anwendung zu erhöhen. Wenn Ihnen dieses schreckliche Wort noch nie begegnet ist, werde ich es kurz erklären. Mithilfe von Unit-Tests können Sie den Testprozess automatisieren und alle Funktionen Ihrer Anwendung testen.

    Nachdem die Entwicklung abgeschlossen ist neue Funktion(Es ist möglich, Tests vor Beginn der Entwicklung zu schreiben.) Der Entwickler schreibt speziellen Code, um seinen Code zu testen. In Ihrem Testcode müssen Sie verschiedene Situationen simulieren und Werte zurückgeben. Wir haben zum Beispiel eine Funktion geschrieben, um Leerzeichen zu kürzen (trim). Um seine Leistung zu testen, müssen wir mehrere Tests vorbereiten, die es uns ermöglichen, Folgendes festzustellen:

  • Wenn wir den String „string“ übergeben, erhalten wir „string“ als Ausgabe;
  • Bei der Übertragung der Begriffe „Zeile 9“ erhalten wir am Ausgang „Zeile 9“;
  • Wir können auch Tests für andere Eingabeparameter hinzufügen (z. B. das Ersetzen des Leerzeichens durch ein Tabulatorzeichen). Generell gilt: Je besser wir den Code mit Tests abdecken und mögliche negative Optionen vorsehen, desto größer ist die Chance, dass im entscheidenden Moment noch ein paar Haare auf dem Kopf bleiben.

    In der JS-Welt werden Tests normalerweise mit speziellen Frameworks geschrieben. Sie verfügen über alles, was Sie zum Beschreiben von Tests benötigen, sowie zumindest über einige Tools zur Systematisierung von Testfortschrittsberichten.

    Tests!= zusätzlicher Code

    Entwickler, die keine Unit-Tests verwenden, argumentieren gerne, dass Unit-Tests das Schreiben und Pflegen von zusätzlichem Code erfordern. Sie sagen, dass die Fristen in realen Projekten oft knapp sind und es einfach nicht möglich ist, zusätzlichen Code zu schreiben.

    Ich stimme den knappen Fristen zu, bin aber bereit, über den zusätzlichen Code zu streiten. Einerseits erfordern Tests ja zusätzlichen Code und damit Zeit, ihn zu schreiben. Andererseits spielt dieser Code die Rolle von Airbags in einem Auto und wird sich mit zunehmender Anwendung definitiv amortisieren.

    Wenn Sie keine Zeit haben und den Wunsch verspüren, das Schreiben von Tests aufzugeben, denken Sie dreimal darüber nach. In diesem Fall ist es möglicherweise sinnvoller, nur die schwierigsten Abschnitte des Codes mit Tests abzudecken, anstatt das Testen vollständig aufzugeben. Denken Sie immer mit Blick auf die Zukunft, als ob Ihr Programm in einem Monat zu beispiellosen Ausmaßen wachsen könnte.

    Nicht jeder Code wird getestet

    Warum sage ich, dass Sie über das Testen nachdenken müssen, bevor Sie den Hauptcode schreiben? Ja, denn der Code, der zunächst durch Unit-Tests abgedeckt werden soll, ist in einem etwas anderen Stil geschrieben. Nicht jeder Code kann getestet werden. Code, der Logik und Darstellungen vermischt und zudem in Bereiche gedrängt ist, in denen ein ordnungsgemäßes Testen unmöglich ist. Hier rate ich Ihnen immer, ein paar einfache Regeln zu beachten:

  • Es müssen keine großen Funktionen geschrieben werden. Jede Funktion sollte ein Problem lösen, nicht 100.500 mögliche Situationen. Es ist beispielsweise nicht erforderlich, den Code zum Senden von Daten an den Server in die für die Vorbereitung zuständige Funktion einzufügen;
  • Eine Funktion, die aus mehr als 10 Codezeilen besteht, ist höchstwahrscheinlich eine fehlerhafte Funktion;
  • Logik und Präsentation sollten niemals zusammenpassen;
  • QUnit – ein Klassiker von den Machern von jQuery

    Besonders beliebt ist QUnit bei JavaScript-Entwicklern. Erstens ist es gut dokumentiert und einfach zu verwenden, und zweitens wurde es von den Autoren von jQuery erstellt. Die Bibliothek eignet sich zum Testen sowohl von jQuery-basiertem als auch nativem JavaScript-Code.

    Herunterladen neueste Version Sie können QUnit über die offizielle Website verwenden: http://qunitjs.com/. Die Bibliothek kommt als einzelnes JS und CSS-Datei. Nehmen wir an, dass Sie herausgefunden haben, wie Sie die erforderlichen Komponenten laden. Wenn ja, ist es an der Zeit, einen Probetest zu schreiben. Lassen Sie uns nicht zu weit gehen und versuchen, die oben erwähnte Funktion trim() zu testen.

    Um die Tests zu demonstrieren, habe ich ein einfaches Projekt mit dem folgenden Konstruktor erstellt:

    Index.html – die Hauptdatei, die Testergebnisse anzeigt; - qunit-1.12.0.js – qunit-Bibliotheksdatei; - example.js – Datei mit Code zum Testen (in unserem Fall eine Beschreibung der Funktion trim()); - test.js – Datei mit Tests; - qunit-1.12.0.css – Stile zum Entwerfen eines Berichts mit Tests;

    Der Inhalt der Dateien index.html und test.js wird in den Auflistungen 1 und 2 dargestellt. Am meisten interessiert uns die zweite Auflistung, die die Deklaration der zu testenden Funktion (trim()) und den Testcode zu deren Überprüfung enthält Funktionalität. Bitte beachten Sie, dass sich die trim()-Funktion selbst an einer beliebigen Stelle befinden kann; ich habe sie nur aus Platzgründen im Magazin in die zweite Auflistung eingefügt.

    Schauen wir uns nun die Tests selbst an. Um die Funktionalität unseres Codes zu überprüfen, bietet uns die Qunit.js-Bibliothek eine Reihe von Methoden:

  • test() – Wrapper zur Beschreibung des Tests;
  • ok() – die Behauptung ermöglicht es Ihnen, die Wahrheit des ersten Parameters zu überprüfen. In unserem Beispiel übergebe ich einen Aufruf an die von uns definierte Funktion trim() und vergleiche sie mit dem Wert, den ich erwarte. Wenn die Bedingung wahr ist, ist der Test bestanden;
  • equal() – Mit dieser Methode können Sie die Gleichheit des ersten und zweiten Parameters überprüfen. Bitte beachten Sie dies sofort diese Methode führt eine schwache Prüfung durch und ist daher nur für skalare Größen geeignet;
  • notEqual() ist das Gegenteil von equal(). Wird ausgeführt, wenn der erste Wert nicht mit dem zweiten übereinstimmt.
  • strictEqual() ähnelt equal() mit einem Unterschied: Es verwendet eine strikte Prüfung (d. h. es prüft auch den Datentyp);
  • notStrictEqual() – die Methode ist das Gegenteil von strictEqual();
  • deepEqual() – Methode für rekursive Behauptungen, verwendet für Grundelemente, Arrays, Objekte;
  • notDeepEqual() – die Methode ist das Gegenteil von deepEqual();
  • raises() – eine Anweisung zum Testen von Rückruffunktionen, die eine Ausnahme auslösen;
  • In der zweiten Auflistung habe ich anschaulich gezeigt, wie man diese Methoden in der Praxis anwenden kann. Wenn Sie das Testbeispiel in dieser Form ausführen, werden alle Tests erfolgreich bestanden (siehe entsprechende Abbildung). Um den Unterschied zwischen bestandenen und fehlgeschlagenen Tests zu erkennen, habe ich den Code für einen Test leicht geändert. Ich habe mit strictEqual() absichtlich ein fehlerhaftes Ergebnis zur Testzeile hinzugefügt (siehe entsprechende Abbildung).

    Listing 1. Inhalt der Datei index.html Testen mit QUnit Listing 2. Testdateien und die Funktion trim() trim(string) ( return (string || "").replace(/^\s+|\s+$/g , ""); ) test("Testen Sie die Funktion trim()", function() ( ok(trim(" test ") == "test", "trimmen Sie die äußeren Leerzeichen"); ok(trim(" 1 " ) == "1", "viele Leerzeichen an den Seiten"); ok(trim(" 24 ") == "24", "Leerzeichen und Tabulatoren an den Seiten"); ", "Leere Zeile" "); strictEqual(trim(" ][aker") ));

    Wir scheinen es geschafft zu haben, einfache Funktionen zu testen. Ich habe jedenfalls nichts mehr hinzuzufügen. Als nächstes müssen Sie echten Code nehmen und versuchen, selbst Tests zu schreiben. Schauen wir uns eine weitere häufig auftretende Aufgabe für JavaScript-Entwickler an – das Testen asynchroner Funktionen. Eine mit JavaScript-Code vollgestopfte Anwendung interagiert über Ajax zu 99 % mit der Serverseite. Sie können diesen Code auch nicht deaktiviert lassen, aber das Schreiben von Tests sieht etwas anders aus. Schauen wir uns ein Beispiel an:

    AsyncTest("myAsyncFunc()", function() ( setTimeout(function() ( ok(myAsyncFunc() == true, "Daten erfolgreich übertragen"); start(); , 500); ));

    Der Hauptunterschied zwischen diesem Beispiel und dem vorherigen besteht darin, dass anstelle des test()-Wrappers asyncTest() verwendet wird, wodurch direkt zum Ausdruck gebracht wird, dass ich an asynchronen Tests interessiert bin. Als nächstes beginne ich die Wartezeit bei 500 ml. Sek. Während dieser Zeit sollte die Funktion myAsyncFunc() Daten an den Testserver übertragen und, wenn alles in Ordnung ist, „true“ zurückgeben. Hier kommt der interessanteste Moment. Wenn asyncTest() aufgerufen wird, stoppt der Ausführungsthread und wenn der Test abgeschlossen ist, muss er unabhängig gestartet werden. Um den Ausführungsfluss zu steuern, verfügt QUnit über die Methoden start() und stop().

    Das Testen asynchroner Funktionen mit der QUnit-Bibliothek ist recht einfach. Das letzte Beispiel, das ich mir ansehen möchte, beinhaltet das Schreiben eines Tests, der mehrere asynchrone Prüfungen durchführt. Die Hauptfrage, die sich bei solchen Aufgaben stellt, ist der optimale Ausgangspunkt für den Ausführungsthread. Das offizielle Dokument schlägt die Verwendung von etwas vor wie:

    AsyncTest("myAsyncFunc()", function() ( Expect(3); //Hier führen wir drei Prüfungen durch ok(myAsyncFunc(), "Making the world a better place 1"); ok(myAsyncFunc(), "Making the die Welt zu einem besseren Ort 2") ; ok(myAsyncFunc(), "Die Welt zu einem besseren Ort machen 3"); setTimeout(function() ( start(); ));

    Testen Sie auf benutzerdefinierte Aktionen

    Sie sollten immer bedenken, dass viele Schnittstellenelemente in JavaScript geschrieben sind. Zum Beispiel klickt ein Benutzer auf einen Zuhälter und als Reaktion auf seinen Klick sollte etwas passieren. In Projekten gibt es eine große Menge solchen „Schnittstellen“-Codes, der auch mit Tests abgedeckt werden muss. Sehen wir uns an, wie wir den Tastendruck eines Benutzers simulieren und einen separaten Test für diese Aktion schreiben können. Stellen wir uns vor, wir hätten eine bestimmte Funktion, die die gedrückten Tasten protokolliert. Den Code habe ich im dritten Eintrag angegeben:

    Listing 3. Tastatureingaben protokollieren Funktion KeyLogger(Ziel) ( if (!(diese Instanz von KeyLogger)) ( return new KeyLogger(target); ) this.target = target; this.log = ; var self = this; this.target. off ("keydown").on("keydown", function(event) ( self.log.push(event.keyCode); ));

    Versuchen wir nun, diese Funktion zu testen. Zunächst müssen wir im Testkörper die gedrückte Taste emulieren. Der einfachste Weg, dies zu tun, ist die Verwendung der jQuery-Bibliothek, mit der Sie ein Ereignis in wenigen Codezeilen erstellen können (siehe Listing 4).

    Listing 4. Testcode für KeyLogger test("Key logging test", function() ( var event, $doc = $(document), keys = KeyLogger($doc); event = $.Event("keydown"); event .keyCode = 9; $doc.trigger(event); equal(keys.log.length, 1, „Taste aufgezeichnet“); );

    Ganz am Anfang der Testauflistung bereite ich ein Ereignis vor, um einen Tastendruck zu emulieren – „keydown“. Wir werden daran interessiert sein, die Tab-Taste (Code 9) zu drücken. Dann sende ich mit der Methode trigger() das vorbereitete Ereignis aus, woraufhin ich mit dem Testen beginnen kann. Zuerst prüfen wir das Gesamtbild – ob eine Taste gedrückt wurde, und dann deren Code.

    DOM unter dem Deckmantel von Tests

    Da Sie mit Qunit.js Benutzeraktionen testen können, sollte das Schreiben von Tests für das DOM ebenfalls kein Problem darstellen. Das ist in der Tat wahr und das folgende Beispiel wird meine Worte bestätigen. Ich werde es nicht kommentieren, schauen Sie sich einfach den Code an und alles wird klar:

    Test("Ein neues div-Element hinzufügen", function() ( var $fixture = $("#qunit-fixture"); $fixture.append("This is a new div"); equal($("div", $fixture) .length, 1, „Neues Div erfolgreich hinzugefügt!“);

    Phantom.JS – Ausführen von Tests über die Konsole

    Das Schreiben von Tests mit der Qunit.js-Bibliothek ist bequem und einfach, aber früher oder später werden Sie den Wunsch verspüren, den Teststart und die Ergebniserfassung irgendwie zu automatisieren. Ich habe zum Beispiel ein eigenes zu diesem Thema virtuelle Maschine in DigitalOcean, das ich nur über die Konsole steuern kann.

    Das Projekt phantom.js löst dieses Problem recht elegant. Dabei handelt es sich nicht um ein weiteres Framework zum Schreiben von Unit-Tests, sondern um eine vollwertige Konsolenversion der WebKit-Engine. Vereinfacht ausgedrückt emuliert diese Anwendung einen Browser. Mit Hilfe von phantom.js ist es nicht nur möglich, die Überprüfung der Testausführung zu automatisieren, sondern auch viele Probleme zu lösen, die früher oder später vor einem Entwickler auftreten: Erhalten von Seitenrendering-Ergebnissen in eine Datei (PNG, JPG), Netzwerk Überwachungsfunktionen (Ladegeschwindigkeit, Gesamtleistung usw.), Emulation von Benutzeraktionen usw. Ich empfehle Ihnen, sich die Zeit zu nehmen und die offizielle Dokumentation zu diesem Projekt zu lesen. Sie werden auf jeden Fall etwas Interessantes für sich finden.

    Phantom.js kann für verschiedene Plattformen (Nix, Mac OS X, Windows) kompiliert werden. Wenn Sie alles unter Windows entwickeln, gibt es keine Probleme – führen Sie die Binärdateien zusammen und fahren Sie fort. Kleinere Probleme beim Start können auftreten, wenn Sie zwei Videoadapter installiert haben, darunter NVidia. In diesem Fall müssen Sie den in der Seitenleiste beschriebenen Hack verwenden.

    Versuchen wir, phantom.js in der Praxis kennenzulernen. Um die im letzten Abschnitt vorbereiteten Tests über phantom.js auszuführen und die Ausführungsergebnisse in die Konsole zu übertragen, benötigen wir ein spezielles Ladeskript – run-qunit.js. Öffnen Sie die Konsole (ich arbeite unter Windows, also verwende ich cmd) und geben Sie den Befehl im folgenden Format ein:

    Phantom.exe

    In meinem Fall sah der Startbefehl so aus:

    E:\soft\phantomjs>phantomjs.exe E:\temp\testjsforx\qunit\run-qunit.js file:///E: /temp/testjsforx/qunit/index.html Das Ergebnis seiner Ausführung: Tests abgeschlossen in 2592 Millisekunden. 9 Behauptungen von 9 bestanden, 0 fehlgeschlagen.

    Alle Tests bestanden

    Es ist auf jeden Fall notwendig, Ihren Code mit Tests abzudecken, unabhängig von der Größenordnung der Anwendung, die Sie erstellen. Ich möchte Sie noch einmal daran erinnern, dass selbst die kleinsten Programme zu ungeschickten Monstern werden, die Unterstützung und zusätzliche Funktionalität benötigen. Gut getesteter Code ist der Schlüssel zu Erfolg und Qualität. Ja, es ist nicht einfach, sofort mit dem Schreiben von Code zu beginnen, der für automatisierte Tests geeignet ist, aber glauben Sie mir, all diese Qualen werden sich in Zukunft mehr als auszahlen. Das ist alles für heute, viel Glück!

    Wenn keine Zeit für Tests bleibt

    Wenn Sie keine Zeit haben, macht es keinen Sinn, Tests für einfache Funktionen zu schreiben (nehmen Sie dasselbe trim() aus den Beispielen im Artikel), es ist besser, sich auf die kritischsten Abschnitte des Codes zu konzentrieren. Die gleiche Regel sollte beim Schreiben von häufig geändertem Code befolgt werden. Die technischen Spezifikationen eines Live-Projekts ändern sich häufig und einige Funktionen müssen ständig aktualisiert werden. Solche Änderungen können zu unangenehmen Momenten führen – der geänderte Code funktioniert gut mit neuen Daten, verarbeitet alte Daten jedoch nicht organisch. Um hier also keinen Fehler zu entdecken, ist es besser, solche Funktionen sofort mit Tests abzudecken. Denken Sie an eine einfache Regel: Es bleibt keine Zeit, den gesamten Code mit Tests abzudecken, sondern den wichtigsten Teil davon abzudecken.

    Regeln für gute Tests
  • Der Test sollte so einfach wie möglich sein. Je komplexer der Test, desto wahrscheinlicher ist es, dass er Fehler macht.
  • Tests müssen in Module gruppiert werden, um es später einfacher zu machen, Fehler zu finden und bestimmte Teile der Anwendung testen zu können;
  • Jeder Test sollte unabhängig von anderen Tests sein;
  • Schreiben Sie immer einen separaten Test, wenn Sie Fehler finden.
  • phantom.js Probleme unter Windows

    Es ist einfach so passiert, aber ich habe alle Beispiele in diesem Artikel nicht unter Linux, sondern unter dem guten alten Windows 7 getestet. Es stellt sich heraus, dass phantom.js kleinere Probleme hat, wenn es auf Systemen arbeitet, die mehrere Videoadapter verwenden. Mein Laptop verfügt neben dem integrierten Videochip auch über NVidia und weigerte sich aufgrund von phantom.js kategorisch, auf den Befehl phantom.exit() zu antworten. Infolgedessen konnte der Prozess phantom.js nach der Ausführung des Skripts seine Arbeit nicht abschließen und blieb weiterhin im Speicher hängen. Das Terminalfenster reagierte auch nicht mehr auf Befehle zum Herunterfahren (Strg + C half nicht).

    Wenn Sie mit einem ähnlichen Problem konfrontiert sind und planen, phantom.js unter Windows zu verwenden, dann machen Sie sich bereit für den folgenden Hack. Öffnen Sie die Nvidia-Systemsteuerung. Suchen Sie in der Baumstruktur nach dem Element „3D-Einstellungen“. Die Option „Bevorzugter Grafikadapter“ sollte auf der rechten Seite erscheinen. Standardmäßig ist der Wert auf „Automatische Auswahl“ eingestellt. Wir müssen es in „Hochleistungs-Nvidia-Prozessor“ oder „Integrierte Grafikhardware“ ändern. Nach diesem einfachen Trick begann sich phantom.js gehorsam zu verhalten.

  • Cristian Johansens „Test-Driven JavaScript Development“ ist eines der wenigen Bücher, das JavaScript aus der Sicht des Schreibens von Tests betrachtet;
  • John Resing, Beer Bibo „Secrets of the JavaScript Ninja“ ist ein gutes Buch, das vor allem für JS-Entwickler mit einem durchschnittlichen Ausbildungsstand nützlich sein wird. Das Buch behandelt ausführlich die Probleme beim Schreiben effektiven browserübergreifenden Codes, die Nuancen der Ereignisverarbeitung und viele andere Extras.
  • Tests sind ein integraler Bestandteil des Softwareentwicklungszyklus. Neue Entwicklungsteams unterschätzen oft ihre Rolle und überprüfen die Funktionalität der Anwendung auf die altmodische Art und Weise: „Es funktioniert, okay.“ Früher oder später scheitert diese Strategie und der Bugtracker wird von einer zahllosen Armee an Aufgaben überfordert. Um nicht in eine solche Falle zu tappen, empfehle ich, sich ein für alle Mal mit den Nuancen des Testens von JavaScript-Code vertraut zu machen.

    JavaScript ist kein Kinderspiel mehr!

    Ich muss Ihnen wahrscheinlich nicht erklären, dass JavaScript heutzutage nicht nur eine Sprache ist, um das Erscheinungsbild einer Anwendung aufzupeppen. Aber ich werde es trotzdem erklären und eine kleine Einführung geben, denn dann zahlen sie mir noch mehr Geld! 🙂 Die Zeiten, in denen JavaScript für Witze oder die Erstellung von Menüs verwendet wurde, sind also unwiderruflich vorbei. Es handelt sich nun um eine eigenständige Sprache, die sowohl auf dem Client als auch auf dem Server gleichermaßen gut funktioniert. Die Rolle von JavaScript hat erheblich zugenommen, was bedeutet, dass Sie beim Schreiben von Code nicht davor zurückschrecken sollten, auf Praktiken zurückzugreifen, die sich in anderen Programmiersprachen bewährt haben.

    Was meine ich mit Praktiken und Paradigmen? Natürlich das MVC-Architekturmuster (Model View Controller) und die Code-Organisationsmuster. Wenn Sie diese einfachen Tricks befolgen, können Sie besseren Code schreiben, der nicht nur einfach zu warten ist, sondern auch automatisch getestet werden kann.

    Regeln für gute Tests
    • Der Test sollte so einfach wie möglich sein. Je komplexer der Test, desto wahrscheinlicher ist es, dass er Fehler macht.
    • Tests müssen in Module gruppiert werden, um später Fehler leichter finden und bestimmte Teile der Anwendung testen zu können.
    • Jeder Test sollte unabhängig von anderen Tests sein.
    • Schreiben Sie immer einen separaten Test, wenn Sie Fehler finden.
    Fehler der meisten Tester

    Es ist kein Geheimnis, dass die beliebteste Testmethode schon immer ein banaler Sehtest war. Sein Wesen ist bis zur Schande einfach: Sie schreiben ein paar tausend Zeilen Code, lösen das Problem und starten Ihre Kreation. Ich habe herumgespielt, geklickt – alles scheint zu funktionieren, Sie können es auf den Produktionsserver hochladen. Alles ist äußerst einfach und mit der gebotenen Aufmerksamkeit des Entwicklers (idealerweise einer Einzelperson mit dem Spitznamen „Tester“) können Sie sich auf den korrekten Betrieb der Anwendung verlassen.

    In der Praxis läuft alles etwas anders ab. In der Regel gibt es keinen separaten Tester. Der Entwickler selbst versucht, die Funktionalität des Programms zu überprüfen, indem er die in den technischen Spezifikationen festgelegte Abfolge von Aktionen durchführt. Fortgeschrittenere Codefälschungen automatisieren diese Art von Integrationstests mithilfe von Tools wie Selenium.

    Somit erhält der Programmierer die Möglichkeit, nur die schwerwiegendsten Fehler zu erkennen. Leider bleiben „dumme“ und „unbeabsichtigte“ Benutzeraktionen sowie raffinierte Manöver in der Geschäftslogik in 99 % der Fälle im Verborgenen.

    Auch das Vorhandensein eines separaten Testers löst das Problem teilweise und bis zu einem gewissen Zeitpunkt. Selbst wenn wir die Liebe zum Detail seines Pioniers ignorieren, wird die Qualität seiner Tests mit zunehmender Anwendung auf Null sinken. Lassen Sie mich Ihnen ein Beispiel aus der Praxis geben.

    Eines Tages wurde ich beauftragt, ein kleines Programm zu entwickeln. Von der Funktionalität her ähnelte das Projekt einem einfachen CRM, das ich in kürzester Zeit implementiert habe. Nachdem ich die gebührende Belohnung erhalten hatte, übergab ich alle Quellen an den Kunden und vergaß das Projekt acht Monate lang. Dann begann der Spaß. Der Kunde beschloss, die Funktionalität des Programms ernsthaft zu erweitern und rief mich um Hilfe. Natürlich nahm ich es und fing an, eine Funktion nach der anderen zu formen ... Zuerst war es nicht schwierig, aber als es um die Gesamtintegration der Funktionalität ging, stürmte ein schwirrender Schwarm von Käfern auf mich zu. Teile des Codes begannen in Konflikt zu geraten, und wir mussten viel Zeit damit verbringen, Konflikte zu lösen. „Wie kommt es, dass Sie nicht gesehen haben, dass es bei Ihrer Bewerbung Probleme gab?“ - werden die Leser fragen. Ich antworte: Ich habe es gestartet, aber aufgrund der Tatsache, dass die Anwendung gewachsen ist, hatte ich einfach nicht genug Zeit und Nerven, um alle Funktionen massenhaft zu testen. Ich habe mich darauf beschränkt, nur einzelne Funktionen zu testen und dafür ordentlich bezahlt. Moral der Geschichte: „Betrachten Sie Tests als integralen Bestandteil der Entwicklung.“

    Unit-Tests sind wie eine Wunderwaffe

    Unit-Tests sind der beste Weg, um Ihre Nerven zu schonen und die Garantien für die Leistung einzelner Teile der Anwendung zu erhöhen. Wenn Sie diesem schrecklichen Biest noch nie begegnet sind, werde ich es kurz erklären. Mithilfe von Unit-Tests können Sie den Testprozess automatisieren und alle Funktionen Ihrer Anwendung testen.

    Nach Abschluss der Entwicklung einer neuen Funktion (es ist möglich, Tests vor Beginn der Entwicklung zu schreiben) schreibt der Entwickler speziellen Code, um seinen Code zu testen. Es muss verschiedene Situationen simulieren und Werte zurückgeben. Wir haben zum Beispiel eine Funktion geschrieben, um Leerzeichen zu kürzen (trim). Um seine Leistung zu testen, müssen wir mehrere Tests vorbereiten, die es uns ermöglichen, Folgendes festzustellen:

    • Wenn wir den String „string“ übergeben, erhalten wir „string“ als Ausgabe;
    • Bei der Übertragung der Begriffe „Zeile 9“ erhalten wir am Ausgang „Zeile 9“;

    Wir können auch Tests für andere Eingabeparameter hinzufügen (z. B. das Ersetzen des Leerzeichens durch ein Tabulatorzeichen). Generell gilt: Je besser wir den Code mit Tests abdecken und je mehr mögliche Negativoptionen wir bereitstellen, desto höher ist die Wahrscheinlichkeit, dass im entscheidenden Moment noch ein paar Haare auf dem Kopf bleiben.

    In der JS-Welt werden Tests normalerweise mithilfe spezieller Frameworks beschrieben. Sie verfügen über alles, was Sie dafür benötigen, sowie über einige Tools zur Systematisierung von Berichten über den Testfortschritt.

    Tests!= zusätzlicher Code

    Entwickler, die keine Unit-Tests verwenden, argumentieren gerne, dass Unit-Tests das Schreiben und Pflegen von zusätzlichem Code erfordern. Sie sagen, dass die Fristen in realen Projekten oft knapp sind und es einfach nicht möglich ist, zusätzlichen Code zu schreiben.

    Wenn keine Zeit für Tests bleibt

    Wenn Sie keine Zeit haben, macht es keinen Sinn, Tests für einfache Funktionen zu schreiben (nehmen Sie dasselbe trim() aus dem Beispiel im Artikel); es ist besser, sich auf die kritischsten Abschnitte des Codes zu konzentrieren. Die gleiche Regel sollte beim Schreiben von häufig geändertem Code befolgt werden. Die technischen Spezifikationen eines Live-Projekts ändern sich häufig und einige Funktionen müssen ständig aktualisiert werden. Solche Änderungen können zu unangenehmen Momenten führen – der geänderte Code funktioniert gut mit neuen Daten, verarbeitet alte Daten jedoch nicht organisch. Um hier keinen Fehler zu entdecken, ist es besser, solche Funktionen sofort zu überprüfen. Denken Sie an eine einfache Regel: Es bleibt keine Zeit, den gesamten Code mit Tests abzudecken – decken Sie den wichtigsten Teil davon ab.


    Ich stimme den knappen Fristen zu, bin aber bereit, über den zusätzlichen Code zu streiten. Einerseits ja – Tests erfordern zusätzlichen Code und damit Zeit, ihn zu schreiben. Andererseits spielt dieser Code die Rolle von Airbags in einem Auto und wird sich mit zunehmender Anwendung definitiv amortisieren.
    • Cristian Johansens Test-Driven JavaScript Development (goo.gl/mE6Is) ist eines der wenigen Bücher, das JavaScript aus der Perspektive des Schreibens von Tests betrachtet.
    • John Resing, Beer Bibo „Secrets of the JavaScript Ninja“ (goo.gl/xquDkJ) ist ein gutes Buch, das vor allem für JS-Entwickler mit einem durchschnittlichen Schulungsniveau nützlich sein wird. Das Buch behandelt ausführlich die Probleme beim Schreiben effektiven browserübergreifenden Codes, die Nuancen der Ereignisverarbeitung und viele andere Extras.
    • David Flanagan JavaScript. Vollständiger Leitfaden„(goo.gl/rZjjk) – das Buch wurde sechsmal nachgedruckt und jede Veröffentlichung wird zum Bestseller. Das ist in der Tat das Meiste ausführliche Anleitung in JavaScript, das jeder JS-Entwickler mindestens einmal lesen muss.
    • PhantomJS + JSCoverage + QUnit oder Konsolen-JS-Unit-Tests mit Abdeckungsberechnung (goo.gl/FyQ38) – der Autor des Artikels demonstriert die Verwendung des Bundles aufgelistete Pakete um Statistiken zu sammeln und den Prozentsatz der Codeabdeckung durch Tests zu berechnen.
    • Nützliche Beispiele für die Verwendung von PhantomJS – die Seite präsentiert eine große Anzahl von Kampfanwendungen von PhantomJS.

    Wenn Sie keine Zeit haben und den Wunsch verspüren, das Schreiben von Tests aufzugeben, denken Sie dreimal darüber nach. Vielleicht wäre es in diesem Fall angemessener, nur die schwierigsten Abschnitte des Codes mit Tests abzudecken, anstatt das Testen ganz aufzugeben. Denken Sie immer mit Blick auf die Zukunft, als ob Ihr Programm in einem Monat ein beispielloses Ausmaß erreichen könnte. Nicht jeder Code wird getestet

    Warum sage ich, dass Sie über das Testen nachdenken müssen, bevor Sie den Hauptcode schreiben? Ja, denn der Code, der zunächst durch Unit-Tests abgedeckt werden soll, ist in einem etwas anderen Stil geschrieben. Nicht jeder Code kann getestet werden. Code, in dem Logik und Darstellungen vermischt sind und sogar wer weiß wo hineingepfercht ist, lässt sich nicht richtig testen. Hier rate ich Ihnen immer, sich an ein paar einfache Regeln zu halten:

    • Es müssen keine großen Funktionen geschrieben werden. Jede Funktion sollte ein Problem lösen, nicht 100.500 mögliche Situationen. Es ist beispielsweise nicht erforderlich, den Code zum Senden von Daten an den Server in die für die Vorbereitung zuständige Funktion einzufügen.
    • Eine Funktion, die aus mehr als zehn Codezeilen besteht, ist höchstwahrscheinlich eine fehlerhafte Funktion.
    • Logik und Präsentation sollten niemals zusammenpassen.
    QUnit – ein Klassiker von den Machern von jQuery

    Besonders beliebt ist QUnit bei JavaScript-Entwicklern. Erstens ist es gut dokumentiert und einfach zu verwenden, und zweitens wurde es von den Autoren von jQuery erstellt. Die Bibliothek eignet sich zum Testen sowohl von jQuery-basiertem als auch nativem JavaScript-Code.


    Sie können die neueste Version von QUnit von der offiziellen Website herunterladen. Die Bibliothek wird als einzelne JS- und CSS-Datei geliefert. Nehmen wir an, Sie haben herausgefunden, wie Sie die erforderlichen Komponenten laden. Wenn ja, ist es an der Zeit, einen Testtest zu schreiben. Lassen Sie uns nicht zu weit gehen und versuchen, die Funktion trim() zu testen.

    Um die Tests zu demonstrieren, habe ich ein einfaches Projekt mit folgender Struktur erstellt:

    • index.html – die Hauptdatei, die Testergebnisse anzeigt;
    • qunit-1.12.0.js – QUnit-Bibliotheksdatei;
    • example.js – eine Datei mit Code zum Testen (in unserem Fall eine Beschreibung der Funktion trim());
    • test.js – Datei mit Tests;
    • qunit-1.12.0.css – Stile zum Entwerfen eines Berichts mit Tests.

    Der Inhalt der Dateien index.html und test.js wird in den Auflistungen 1 und 2 dargestellt. Am meisten interessiert uns die zweite Auflistung, die die Deklaration der zu testenden Funktion (trim()) und den Testcode zu deren Überprüfung enthält Funktionalität. Bitte beachten Sie, dass sich die trim()-Funktion selbst an einer beliebigen Stelle befinden kann; ich habe sie nur aus Platzgründen im Magazin in die zweite Auflistung eingefügt.
    Schauen wir uns nun die Tests selbst an. Die QUnit.js-Bibliothek bietet uns eine Reihe von Methoden:

    • test() – Wrapper zur Beschreibung des Tests;
    • ok() – die Behauptung ermöglicht es Ihnen, die Wahrheit des ersten Parameters zu überprüfen. In unserem Beispiel übergebe ich einen Aufruf an die von uns definierte Funktion trim() und vergleiche sie mit dem Wert, den ich erwarte. Wenn die Bedingung wahr ist, ist der Test bestanden;
    • equal() – Mit dieser Methode können Sie die Gleichheit des ersten und zweiten Parameters überprüfen. Bitte beachten Sie gleich, dass diese Methode eine schwache Prüfung durchführt und daher nur für skalare Größen geeignet ist;
    • notEqual() ist das Gegenteil von equal(). Wird ausgeführt, wenn der erste Wert nicht mit dem zweiten übereinstimmt.
    • strictEqual() – ähnelt equal() mit einem Unterschied – es verwendet eine strikte Prüfung (d. h. es prüft auch den Datentyp);
    • notStrictEqual() – die Methode ist das Gegenteil von strictEqual();
    • deepEqual() – Methode für rekursive Behauptungen, verwendet für Grundelemente, Arrays, Objekte;
    • notDeepEqual() – die Methode ist das Gegenteil von deepEqual();
    • raises() ist eine Anweisung zum Testen von Rückruffunktionen, die eine Ausnahme auslösen.

    In der zweiten Auflistung habe ich anschaulich gezeigt, wie man diese Methoden in der Praxis anwenden kann. Wenn Sie das Testbeispiel in dieser Form ausführen, werden alle Tests erfolgreich bestanden (siehe entsprechende Abbildung). Um den Unterschied zwischen bestandenen und fehlgeschlagenen Tests zu erkennen, habe ich den Code für einen Test leicht geändert. Ich habe mit strictEqual() absichtlich ein fehlerhaftes Ergebnis zur Testzeile hinzugefügt (siehe entsprechende Abbildung).

    Listing 1. Inhalt der Datei index.html Testen mit QUnit

    Wir scheinen es geschafft zu haben, einfache Funktionen zu testen. Ich habe jedenfalls nichts mehr hinzuzufügen. Als nächstes müssen Sie echten Code nehmen und versuchen, selbst Tests zu schreiben. Schauen wir uns eine weitere häufig auftretende Aufgabe für JavaScript-Entwickler an – das Testen asynchroner Funktionen. Eine mit JavaScript-Code vollgestopfte Anwendung interagiert zu 99 % mit der Serverseite über AJAX. Sie können diesen Code auch nicht deaktiviert lassen, aber das Schreiben von Tests sieht etwas anders aus. Schauen wir uns ein Beispiel an:

    AsyncTest("myAsyncFunc()", function () ( setTimeout(function () ( ok(myAsyncFunc() == true, "Daten erfolgreich übertragen"); start(); , 500); ));

    Der Hauptunterschied zwischen diesem Beispiel und dem vorherigen besteht darin, dass anstelle des test()-Wrappers asyncTest() verwendet wird, wodurch direkt zum Ausdruck gebracht wird, dass ich an asynchronen Tests interessiert bin. Als nächstes führe ich eine Zeitüberschreitung von 500 Millisekunden durch. Während dieser Zeit sollte die Funktion myAsyncFunc() Daten an den Testserver übertragen und, wenn alles in Ordnung ist, true zurückgeben. Hier kommt der interessanteste Moment. Wenn asyncTest() aufgerufen wird, wird der Ausführungsthread gestoppt und muss nach Abschluss des Tests selbst ausgeführt werden. Um den Ausführungsfluss zu steuern, verfügt QUnit über die Methoden start() und stop().


    Das Testen asynchroner Funktionen mit der QUnit-Bibliothek ist recht einfach. Das letzte Beispiel, das ich mir ansehen möchte, beinhaltet das Schreiben eines Tests, der mehrere asynchrone Prüfungen durchführt. Die Hauptfrage, die sich bei solchen Problemen stellt, ist der optimale Ort, an dem der Ausführungsthread gestartet werden soll. Das offizielle Dokument schlägt die Verwendung von so etwas vor

    AsyncTest("myAsyncFunc()", function () ( Expect(3); // Hier führen wir drei Prüfungen durch ok(myAsyncFunc(), "Making the world a better place 1"); ok(myAsyncFunc(), "Making the Welt zu einem besseren Ort 2") ; ok(myAsyncFunc(), "Die Welt zu einem besseren Ort machen 3"); setTimeout(function () ( start (), 3000 ));

    Testen Sie auf benutzerdefinierte Aktionen

    Sie sollten immer bedenken, dass viele Schnittstellenelemente in JavaScript geschrieben sind. Zum Beispiel klickt ein Benutzer auf einen Zuhälter und als Reaktion auf seinen Klick sollte etwas passieren. In Projekten gibt es eine große Menge solchen „Schnittstellen“-Codes, der auch mit Tests abgedeckt werden muss. Sehen wir uns an, wie wir den Tastendruck eines Benutzers simulieren und einen separaten Test für diese Aktion schreiben können. Stellen wir uns vor, wir hätten eine bestimmte Funktion, die die gedrückten Tasten protokolliert. Den Code habe ich im dritten Eintrag angegeben.

    Listing 3. Tastatureingaben protokollieren Funktion KeyLogger(Ziel) ( if (!(diese Instanz von KeyLogger)) ( return new KeyLogger(target); ) this.target = target; this.log = ; var self = this; this.target. off ("keydown").on("keydown", function(event) ( self.log.push(event.keyCode); ));

    Versuchen wir nun, diese Funktion zu testen. Zunächst müssen wir im Testkörper die gedrückte Taste emulieren. Am einfachsten geht das mit der jQuery-Bibliothek, mit der Sie ein Ereignis in wenigen Codezeilen erstellen können (siehe Listing 4).

    Listing 4. Testcode für KeyLogger test("Key logging test", function () ( var event, $doc = $(document), keys = KeyLogger($doc); event = $.Event("keydown"); event .keyCode = 9; $doc.trigger(event); equal(keys.log.length, 1, "Taste aufgezeichnet");

    Ganz am Anfang der Testauflistung bereite ich ein Ereignis vor, um einen Tastendruck zu emulieren – „keydown“. Wir werden daran interessiert sein, die Tab-Taste (Code 9) zu drücken. Dann sende ich mit der Methode trigger() das vorbereitete Ereignis aus, woraufhin ich mit dem Testen beginnen kann. Zuerst prüfen wir das Gesamtbild – ob eine Taste gedrückt wurde, und dann deren Code.

    DOM unter dem Deckmantel von Tests

    Da Sie mit Qunit.js Benutzeraktionen testen können, sollte das Schreiben von Tests für das DOM ebenfalls kein Problem darstellen. Das ist in der Tat wahr, und das folgende Beispiel wird meine Worte bestätigen. Ich werde es nicht kommentieren, schauen Sie sich einfach den Code an und alles wird klar:

    Test("Ein neues div-Element hinzufügen", function () ( var $fixture = $("#qunit-fixture"); $fixture.append("This is a new div"); equal($("div", $fixture) .length, 1, „Neues Div erfolgreich hinzugefügt!“);

    PhantomJS – Ausführen von Tests über die Konsole

    Das Schreiben von Tests mit der QUnit.js-Bibliothek ist bequem und einfach, aber früher oder später werden Sie den Wunsch verspüren, den Start, das Testen und das Sammeln von Ergebnissen irgendwie zu automatisieren. Zu diesem Zweck habe ich beispielsweise eine eigene virtuelle Maschine in DigitalOcean, die ich nur über die Konsole verwalten kann.

    Mit dem PhantomJS-Projekt können Sie dieses Problem ganz elegant lösen. Dabei handelt es sich nicht nur um ein weiteres Framework zum Schreiben von Unit-Tests, sondern um eine vollwertige Konsolenversion der WebKit-Engine. Vereinfacht ausgedrückt emuliert diese Anwendung einen Browser. Mit Hilfe von PhantomJS ist es nicht nur möglich, die Überprüfung der Testausführung zu automatisieren, sondern auch viele Probleme zu lösen, die früher oder später vor einem Entwickler auftreten: Erhalten von Seitenrendering-Ergebnissen in eine Datei (PNG, JPG), Netzwerküberwachungsfunktionen (Ladegeschwindigkeit, Gesamtleistung usw.), Emulation von Benutzeraktionen usw. Ich empfehle Ihnen, sich die Zeit zu nehmen und die offizielle Dokumentation zu diesem Projekt zu lesen. Sie werden auf jeden Fall etwas Interessantes für sich finden.

    PhantomJS kann für verschiedene Plattformen (*nix, OS X, Windows) kompiliert werden. Wenn Sie alles unter Windows entwickeln, gibt es keine Probleme – führen Sie die Binärdateien zusammen und fahren Sie fort. Wenn Sie zwei Grafikkarten installiert haben, darunter eine von NVIDIA, kann es zu leichten Startschwierigkeiten kommen. In diesem Fall müssen Sie den in der Seitenleiste beschriebenen Hack verwenden.


    Versuchen wir, PhantomJS in der Praxis kennenzulernen. Um die im letzten Abschnitt vorbereiteten Tests über PhantomJS auszuführen und die Ausführungsergebnisse in die Konsole zu übertragen, benötigen wir ein spezielles Loader-Skript – run-qunit.js. Öffnen Sie die Konsole (ich arbeite unter Windows, also verwende ich cmd) und geben Sie den Befehl im Format ein

    phantom.exe

    In meinem Fall sah der Startbefehl so aus:

    E:\soft\phantomjs>phantomjs.exe E:\temp\testjsforx\qunit\run-qunit.js file:///E: /temp/testjsforx/qunit/index.html

    Das Ergebnis seiner Ausführung:

    Tests wurden in 2592 Millisekunden abgeschlossen. 9 Behauptungen von 9 bestanden, 0 fehlgeschlagen.

    Alle Tests bestanden

    Es ist auf jeden Fall notwendig, Ihren Code mit Tests abzudecken, und es spielt keine Rolle, welchen Umfang die Anwendung hat, die Sie erstellen. Ich erinnere Sie noch einmal daran: Selbst die kleinsten Programme werden zu schwerfälligen Monstern, die Unterstützung und zusätzliche Funktionalität benötigen. Gut getesteter Code ist der Schlüssel zu Erfolg und Qualität. Ja, es ist nicht einfach, sofort mit dem Schreiben von Code zu beginnen, der für automatisierte Tests geeignet ist, aber glauben Sie mir, all diese Qualen werden sich in Zukunft mehr als auszahlen. Das ist alles, was ich für heute habe, viel Glück!

    PhantomJS-Probleme unter Windows

    Es ist einfach so passiert, aber ich habe alle Beispiele in diesem Artikel nicht unter Linux, sondern unter dem alten getestet gutes Windows 7. Es stellt sich heraus, dass PhantomJS einige kleinere Probleme hat, wenn es auf Systemen läuft, die mehrere Videoadapter verwenden. Mein Laptop verfügt neben dem integrierten Videochip auch über NVIDIA, und aus diesem Grund weigerte sich PhantomJS kategorisch, auf den Befehl phantom.exit() zu antworten. Infolgedessen beendete der PhantomJS-Prozess nach der Ausführung des Skripts seine Arbeit nicht und blieb weiterhin im Speicher hängen. Das Terminalfenster reagierte auch nicht mehr auf Befehle zum Herunterfahren (hat nicht geholfen).

    Wenn Sie mit einem ähnlichen Problem konfrontiert sind und planen, PhantomJS unter Windows zu verwenden, dann machen Sie sich bereit für den folgenden Hack. Öffnen Sie die NVIDIA-Systemsteuerung. Suchen Sie in der Baumstruktur nach dem Element „3D-Einstellungen“. Auf der rechten Seite sollte die Option „Bevorzugter Grafikadapter“ angezeigt werden. Standardmäßig. sein Wert ist auf „Automatische Auswahl“ eingestellt. Wir müssen es auf „Hohe Leistung“ ändern. NVIDIA-Prozessor" oder "Integrierte Grafikhardware". Nach diesem einfachen Trick begann PhantomJS, sich gehorsam zu verhalten.

    Eines Tages äußerte ein Freund seine Verwirrung darüber, wie JavaScript zum Schreiben seriöser Unternehmensprodukte verwendet werden könnte, da es keinen Compiler hat. Tatsächlich spielt bei der Erstellung von qualitativ hochwertigem Code nicht die Tatsache, dass es einen Compiler für eine Programmiersprache gibt, eine entscheidende Rolle, sondern der richtig ausgewählte und gut abgestimmte technische Prozess zur Erstellung eines Softwaresystems.

    Dieser Prozess sollte eine Reihe von Mitteln zur Kontrolle der Qualität und Effektivität der Arbeit des Programmierers umfassen. Solche Tools können sein: Unit- und Integrationstests, kontinuierliche Integration (Continuous Integration, CI), Sammlung und Analyse verschiedener Metriken (z. B. sehr lange Methoden in nDepend), Überprüfung der Einhaltung der Anforderungen von JsLint, FxCop usw.

    In diesem Artikel möchte ich Ihnen erklären, wie Sie automatische Unit- und Integrationstests Ihres Produkts in JavaScript ordnungsgemäß durchführen. Tatsächlich unterscheidet sich die JavaScript-Sprache in dieser Hinsicht nicht grundlegend von Java oder C#.

    Agil, TDD und BDD

    Typischerweise wird empfohlen, automatisierte Unit- und Integrationstests für abgeschlossene Funktionen zu erstellen, um das Risiko von Regressionsfehlern zu verringern, wenn der Code in der Zukunft geändert wird. Im Fall von JavaScript können solche Tests das Testen der Systemfunktionalität in verschiedenen Browsern erheblich vereinfachen, indem sie die Schritte zur Sicherstellung eines solchen Tests automatisieren. Darüber hinaus kann es eine gute Idee sein, für jeden geschlossenen Fehler im Produkt einen Unit- oder Integrationstest zu schreiben.

    Es gibt auch Programmiertechniken, bei denen Sie mit der Codierung der Logik beginnen müssen, indem Sie einen Komponententest schreiben: Test-Driven Development (TDD) und Behavior-Driven Development (BDD). Sie werden häufig im agilen Prozess eingesetzt. Schauen wir uns ihre Funktionen genauer an.

    Testgetriebene Entwicklung

    Testgetriebene Entwicklung ist ein iterativer Prozess zum Schreiben von Code, der die folgenden vier Schritte wiederholt:

    Schritt 1. Bevor Sie eine neue Logik hinzufügen, erstellen Sie einen Komponententest, um diese Logik zu testen.

    Schritt 2. Führen Sie den Test durch und stellen Sie sicher, dass dies der Fall ist Nicht Pässe;

    Schritt 3. Schreiben Sie den einfachsten Code, der den Test zum Erfolg führt.

    Schritt 4. Bearbeiten Sie den Code, um die Qualitätsanforderungen zu erfüllen, entfernen Sie Codeduplikate und stellen Sie sicher, dass der Test erfolgreich ist.

    Ein Unit-Test ist ein Code, der den Betrieb einer bestimmten Komponente (Modul) in einer isolierten Umgebung testet. Ein Integrationstest bezieht sich auf den Code, der testet zusammenarbeiten mehrere Komponenten. Um ein Modul in einer isolierten Umgebung zu testen, wenn es von anderen Modulen abhängt, werden Testdoubles verwendet.

    Test-Doppel

    Die Einteilung der beim Unit-Test verwendeten Hilfsobjekte in Kategorien stammt aus dem Buch xUnit Test Patterns von Gerard Meszaros. Diese Kategorien werden zusammenfassend als „Testdoppel“ bezeichnet. Es gibt folgende Arten von Zweitstudiengängen:

    • Gefälscht;
    • Dummy.

    Stub Ausgabewerte für die sie im Voraus festgelegt werden. Es wird verwendet, um die Schnittstelle einer abhängigen Komponente zu simulieren.

    Mock ist ein Hilfsobjekt Verhalten welches vorab festgelegt wird. Es dient dazu, die Schnittstelle einer abhängigen Komponente zu simulieren und zu testen, ob diese in einem Test korrekt verwendet wird.

    Spy ist ein Hilfsobjekt zum Überprüfen aufgerufener Methoden und Parameter, die ihnen während eines Tests übergeben werden.

    Fake ist ein Hilfsobjekt, das die Schnittstelle einer abhängigen Komponente in vereinfachter Form implementiert. Für Unit-Testzwecke können Sie beispielsweise eine In-Memory-Datenbank anstelle der relationalen Datenbank verwenden, die in der Produktionsversion des Produkts verwendet wird.

    Ein Dummy ist ein Hilfsobjekt, dessen Referenz oder Übergabe durch eine Methodensignatur oder einen anderen Vertrag erforderlich ist, dessen tatsächlicher Wert jedoch nie verwendet wird.

    Der Unterschied zwischen Stub und Mock besteht in der Art und Weise, wie die Testergebnisse überprüft werden. Bei Stub wird der Zustand des Objekts am Ende des Tests überprüft. Im Fall von Mock wird durch den Test überprüft, ob das Objekt genau wie bei der Registrierung beschrieben verwendet wird. Einzelheiten finden Sie in der Notiz Mocks Aren't Stubs von Martin Fowler, und ich werde hier nur ein Beispiel geben.

    Stub Verspotten
    „test connect sollte mit der Abfrage beginnen“: function () ( this.client.url = „/my/url“; sinon.stub(ajax, „poll“).returns()); .assert.claimedWith(ajax.poll, "/my/url" ) „test connect sollte mit der Abfrage beginnen“: function () ( this.client.url = „/my/url“; var mock = sinon.mock(ajax) mock.expects(“poll“) .withArgs(“/my/url ").returns(); this.client.connect(); mock.verify(); )
    Verhaltensgesteuerte Entwicklung

    Ein iterativer Ansatz zur Softwareentwicklung durch die Umsetzung funktionaler Anforderungen ist der bereits bekannte ergebnisorientierte testgetriebene Entwicklungsstil. Im BDD-Prozess werden die folgenden drei Schritte nacheinander ausgeführt:

    Schritt 1. Ermittlung funktionaler Anforderungen an das implementierte Modul in Form von Tests;

    Schritt 2. Modulkodierung;

    Schritt 3. Überprüfung, ob alle Wünsche des Kunden oder Business-Analysten () erfüllt werden, indem die Ergebnisse laufender Tests überprüft werden.

    Beim Schreiben von Tests im BDD-Stil ist es sehr praktisch, Mock-Objekte zu verwenden, da sie die funktionalen Anforderungen einer Komponente perfekt widerspiegeln. Somit können Tests im BDD-Prozess als formalisierte Darstellung des Problems (User Story) in Scrum-Begriffen dienen, was Zeit beim Schreiben technischer Spezifikationen und Dokumentation für das fertige Produkt spart.

    Was sollte ein JavaScript-Unit-Testing-Framework sein?

    Eine vollständige JavaScript-Einheit und ein Integrationstesttool sollten aus den folgenden Komponenten bestehen:

    • Assertionsbibliothek (eine Reihe von Methoden zum Überprüfen des Zustands einer Komponente am Ende jedes Tests);
    • Mock-Bibliothek (ein Tool zum Generieren von Mock-Objekten und anderen „Duplikaten“);
    • Testläufer (Tool automatischer Start Tests mit Unterstützung für die meisten Browser, einschließlich iOS-Browser und Android);
    • Verbindungsblock zu Beliebte Systeme kontinuierliche Integration (kontinuierliche Integration).
    Strategien zum Unit-Testen von JavaScript-Code

    Heutzutage gibt es drei Strategien zum Unit-Testen von JavaScript-Code (weitere Einzelheiten finden Sie im dritten Kapitel des Buches Test-Driven JavaScript Development von Christian Johansen):

    • In-Browser-Tests;
    • Headless-Testen;
    • Testen entlang des JsTestDriver-Pfads.

    Beim In-Browser-Testen werden alle Unit- und Integrationstests von einer HTML-Seite aus ausgeführt, die der Entwickler öffnet erforderliche Browser auf eigene Faust. Dieser Ansatz ist einfach und intuitiv. Der Nachteil besteht jedoch darin, dass die Möglichkeit zur Einbindung solcher Tests in die Continuous Integration nicht vorgesehen ist. Darüber hinaus kann es für einen Entwickler mühsam sein, eine HTML-Seite manuell in zehn oder mehr Browsern auszuführen und ständig „F5“ zu drücken.

    Headless-Testen bedeutet, dass der gesamte JavaScript-Code auf einem Emulator getestet wird, der in Java, Ruby, JavaScript, C++ usw. geschrieben sein kann. Der bekannteste Emulator ist heute PhantomJS, eine WebKit-Engine, die über die Befehlszeile ausgeführt wird. Zu den Vorteilen des Emulators gehört, dass er problemlos in der kontinuierlichen Integration verwendet werden kann und dass Sie damit den Start aller Tests über die Befehlszeile automatisieren können. Allerdings hat dieser Ansatz einen erheblichen Nachteil: Der Code wird nicht auf echten Browsern getestet, sodass die Gefahr besteht, dass Browserfehler übersehen werden, die nicht auf dem Emulator reproduziert werden. Vor dem Aufkommen von JsTestDriver konnte man häufig beobachten, dass In-Browser-Tests mit Headless-Tests kombiniert wurden, da sie sich perfekt ergänzen.



     


    Lesen:



    Position der Köpfe auf der Antenne

    Position der Köpfe auf der Antenne

    Der Artikel enthüllt die wichtigsten Methoden zur Bestimmung des Azimuts mit einem Magnetkompass und die Orte seines möglichen Einsatzes. Verwendung...

    So laden Sie einen intelligenten Assistenten für ein Android-Gerät herunter und konfigurieren ihn

    So laden Sie einen intelligenten Assistenten für ein Android-Gerät herunter und konfigurieren ihn

    Aktualisierungsdatum: 05.08.2017 09:22:20 Neueste Version: Kompatibilität: von Android 4.0.3-4.0.4 bis Android 6.0 Anwendungsrechte: Modi ändern...

    Optionen „Überall zu Hause“ und „Überall zu Hause in Russland“ MTS - Beschreibung, Kosten, Verbindung

    Optionen „Überall zu Hause“ und „Überall zu Hause in Russland“ MTS - Beschreibung, Kosten, Verbindung

    Russland nimmt ein riesiges Gebiet unseres Planeten ein. Viele Russen sind mit häufigen Reisen durch ihr Heimatland konfrontiert: Geschäftsreisen, Reisen ...

    So stellen Sie ein Windows-Benutzerkennwort wieder her oder setzen es zurück

    So stellen Sie ein Windows-Benutzerkennwort wieder her oder setzen es zurück

    Wenn Sie plötzlich das Passwort für Ihr Windows-Konto vergessen haben, bleibt Ihnen nichts anderes übrig, als nach einer Möglichkeit zu suchen, es zurückzusetzen oder festzulegen ...

    Feed-Bild RSS