So testen Sie Javascript-Code mit QUnit. JavaScript-Tests Tests zur Kenntnis von HTML-Javascript

Einmal drückte ein Freund von mir seine Verwunderung darüber aus, wie JavaScript zum Schreiben ernsthafter Unternehmensprodukte verwendet werden kann, da es keinen Compiler hat. Tatsächlich spielt nicht die Tatsache, dass für eine Programmiersprache ein Compiler zur Verfügung steht, die entscheidende Rolle bei der Erstellung von hochwertigem Code, sondern ein richtig gewählter und abgestimmter technischer Prozess zur Erstellung eines Softwaresystems.

Dieser Prozess sollte eine Reihe von Qualitätskontrollen und Leistungskontrollen des Programmierers umfassen. Diese Tools können sein: Unit- und Integrationstests, Continuous Integration (Continuous Integration, CI), Erfassung und Analyse verschiedener Metriken (z.B. sehr lange Methoden in nDepend), Prüfung auf Konformität mit JsLint, FxCop, etc.

In diesem Artikel möchte ich Ihnen zeigen, wie Sie automatisierte 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

Generell wird empfohlen, für abgeschlossene Funktionalität automatisierte Unit- und Integrationstests zu erstellen, um das Risiko von Regressionsfehlern bei zukünftigen Codeänderungen zu reduzieren. Im Fall von JavaScript können solche Tests den System-Health-Check in deutlich vereinfachen verschiedene Browser durch Automatisierung von Aktionen, um eine solche Überprüfung sicherzustellen. Darüber hinaus kann das Schreiben eines Unit- oder Integrationstests für jeden geschlossenen Fehler im Produkt gute Arbeit leisten.

Es gibt auch Programmiertechniken, bei denen Sie mit der Programmierung Ihrer 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 verwendet. Betrachten wir ihre Funktionen genauer.

Testgetriebene Entwicklung

Test Driven Development ist ein iterativer Codierungsprozess, der die folgenden vier Schritte wiederholt:

Schritt 1... Erstellen Sie vor dem Hinzufügen einer neuen Logik einen Komponententest, um diese Logik zu testen.

Schritt 2... Führen Sie den Test durch und stellen Sie sicher, dass er nicht geht vorbei;

Schritt 3... Schreiben Sie den einfachsten Code, um den Test erfolgreich durchzuführen.

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

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

Testdoppel

Die Kategorisierung der beim Unit-Test verwendeten Utility-Objekte geht auf das Buch xUnit Test Patterns von Gerard Meszaros zurück. Diese Kategorien werden zusammenfassend als "Test-Doubles" bezeichnet. Subs sind von den folgenden Typen:

  • Fälschung;
  • Attrappe.

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

Spotten Ist ein Hilfsobjekt, Verhalten die im Voraus eingestellt ist. Es wird verwendet, um die Schnittstelle einer abhängigen Komponente zu simulieren und während des Tests zu überprüfen, ob diese korrekt verwendet wird.

Spion Ist ein Hilfsobjekt zum Untersuchen aufgerufener Methoden und Parameter, die ihnen während eines Tests übergeben werden.

Fälschung Ist ein Hilfsobjekt, das die Schnittstelle der abhängigen Komponente vereinfacht implementiert. Beispielsweise können Sie für Komponententests eine In-Memory-Datenbank anstelle der relationalen Datenbank erstellen, die in der Produktionsversion des Produkts verwendet wird.

Schnuller Ist ein Hilfsobjekt, das von einer Methodensignatur oder einem anderen Vertrag angegeben oder übergeben werden muss, aber der echte Wert wird nie verwendet.

Der Unterschied zwischen Stub und Mock besteht darin, wie die Testergebnisse überprüft werden. Bei Stub wird der Zustand des Objekts am Ende des Tests überprüft. Im Fall von Mock überprüft der Test, dass das Objekt genau wie bei der Registrierung beschrieben verwendet wird. Für weitere Details siehe Martin Fowlers Mocks Aren "t Stubs, und ich gebe Ihnen hier nur ein Beispiel.

Stub Spotten
"test connect sollte die Abfrage starten": function () (this.client.url = "/ my / url"; sinon.stub (ajax, "poll"). return (()); this.client.connect (); sinon.assert.calltWith (ajax.poll, "/my/url");) "test connect sollte die Abfrage starten": function () (this.client.url = "/ my / url"; var mock = sinon.mock (ajax) mock.expects ("poll") .withArgs ("/ my / url ") .returns (()); this.client.connect (); mock.verify ();)

Verhaltensorientierte Entwicklung

Ein iterativer Ansatz der Softwareentwicklung durch die Umsetzung funktionaler Anforderungen ist der bereits bekannte Stil der testgetriebenen Entwicklung, ergebnisorientiert. Im BDD-Prozess werden die folgenden drei Schritte nacheinander ausgeführt:

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

Schritt 2... Modulcodierung;

Schritt 3... Überprüfung, ob alle Wünsche des Kunden oder Business Analyst () erfüllt sind, durch Überprüfung der Ergebnisse laufender Tests.

Beim Schreiben von Tests im BDD-Stil ist es sehr praktisch, Mock-Objekte zu verwenden, da sie die funktionalen Anforderungen an eine Komponente perfekt widerspiegeln. Somit können Tests im BDD-Prozess als formalisierte Darstellung des Problems dienen ( Benutzer Geschichte) in Begriffen Gedränge, wodurch Sie Zeit beim Schreiben von technischen Spezifikationen und Dokumentationen für das fertige Produkt sparen können.

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

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

  • Assertionsbibliothek (eine Reihe von Methoden zum Überprüfen des Zustands der Komponente am Ende jedes Tests);
  • Mock-Bibliothek (ein Tool zum Generieren von Mock-Objekten und anderen "Backups");
  • Testläufer (Werkzeug automatischer Start Tests mit Unterstützung für die meisten Browser, einschließlich iOS- und Android-Browser);
  • Blockierung der Verbindung zu gängigen Systemen der kontinuierlichen Integration (Continuous Integration).

Teststrategien für JavaScript-Einheiten

Heute gibt es drei Strategien zum Unit-Testen von JavaScript-Code (weitere Details finden Sie in Kapitel 3 des Buches Test-Driven JavaScript Development von Christian Johansen):

  • Im Browser testen;
  • Kopflos testen;
  • Unterwegs testen JsTestTreiber.

Beim In-Browser-Testing werden alle Unit- und Integrationstests von einer HTML-Seite ausgeführt, die der Entwickler selbst in den erforderlichen Browsern öffnet. Dieser Ansatz ist einfach und intuitiv. Nachteilig ist jedoch, dass die Möglichkeit, solche Tests in Continuous Integration einzubinden, nicht vorgesehen ist. Darüber hinaus kann es für einen Entwickler mühsam sein, eine HTML-Seite in zehn oder mehr Browsern manuell zu starten und ständig "F5" zu drücken.

Headless Testing bedeutet, dass der gesamte JavaScript-Code auf einem Emulator getestet wird, der in Java, Ruby, JavaScript, C++ usw. geschrieben werden kann. Der bekannteste Emulator ist heute PhantomJS, der a WebKit gestartet von Befehlszeile... Zu den Vorteilen des Emulators ist anzumerken, dass er problemlos in Continuous Integration verwendet werden kann und dass Sie den Start aller Tests über die Befehlszeile automatisieren können. Dieser Ansatz hat jedoch einen erheblichen Nachteil – der Code wird nicht auf echten Browsern getestet, daher besteht die Gefahr, dass Browserfehler fehlen, die auf dem Emulator nicht reproduziert werden können. Vor dem Aufkommen von JsTestDriver konnte man oft feststellen, dass In-Browser-Tests mit Headless-Tests kombiniert werden, da sie sich perfekt ergänzen.

Das Erstellen effektiver Testfälle kann bei großen Projekten äußerst wichtig sein, wenn sich das Verhalten von Teilen der Anwendung aus verschiedenen Gründen ändern kann. Das vielleicht häufigste Problem ist, wenn große Gruppe Entwickler arbeiten an den gleichen oder verwandten Modulen. Dies kann zu ungeplanten Verhaltensänderungen von Funktionen führen, die von anderen Programmierern geschrieben wurden. Oder die Arbeit an einem engen Zeitplan führt zu unbeabsichtigten Änderungen an kritischen Teilen der Anwendung.

Das Testen einer Webanwendung besteht in der Regel aus einer visuellen Bewertung von Seitenelementen und einer empirischen Bewertung der Funktionalität der Funktionalität. Mit anderen Worten, das Navigieren durch Abschnitte und das Ausführen von Aktionen an dynamischen Elementen.

Im Laufe der Zeit wird das Projekt mit neuen gefüllt Funktionalität, was den Prozess der Überprüfung seiner Arbeit verlängert und erschwert. Unit-Tests werden zur Automatisierung verwendet.

Es gibt 2 Ansätze zum Erstellen von Testskripten:

  • Weiße KisteTesten- Das Schreiben von Tests basiert auf der Implementierung von Funktionalität. Jene. denn wir prüfen mit denselben Algorithmen, auf denen die Arbeit der Module unseres Systems basiert. Dieser Ansatz garantiert nicht den korrekten Betrieb des Systems als Ganzes.
  • FlugschreiberTesten- Scripting basiert auf Spezifikationen und Systemanforderungen. Auf diese Weise können Sie die Richtigkeit der Ergebnisse der gesamten Anwendung überprüfen, aber dieser Ansatz ermöglicht es Ihnen nicht, kleine und seltene Fehler zu erkennen.

Was zu testen

Es mag den Anschein haben, als ob es sich lohnt, jede Funktion zu testen, die Sie implementiert haben. Dies ist nicht ganz richtig. Das Schreiben von Tests kostet Entwickler Zeit. Um den Prozess der Erstellung einer Anwendung zu optimieren, lohnt es sich daher, Tests nur für komplexe, kritische oder solche Funktionen vorzubereiten, die von den Ergebnissen der Arbeit anderer Systemmodule abhängen. Mit Tests auf mehrdeutige Logik abdecken, die möglicherweise zu Fehlern führen kann. Es lohnt sich auch, Tests für diejenigen Codeteile zu erstellen, die Sie in Zukunft optimieren möchten, damit Sie nach dem Optimierungsprozess sicherstellen können, dass diese korrekt ausgeführt werden.

Generell ist es äußerst wichtig, die Testkosten in Relation zur Enge des Entwicklungszeitrahmens abzuschätzen. Wenn Sie zeitlich nicht begrenzt sind, können Sie natürlich Tests für jede Funktion zulassen. Aber in der Regel wird die Entwicklung in einem harten Zeitnotstand durchgeführt, so dass die Aufgabe eines Analysten oder eines erfahrenen Entwicklers darin besteht, zu verstehen, wo Test erforderlich ist. Darüber hinaus erhöht das Schreiben von Tests die Kosten des Projekts.

Somit können wir 3 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 üblichen Suche nach ihnen.

2) Reduzieren Sie die Debugging-Zeit

3) Ermöglicht es Ihnen, häufig geänderten Code zu testen.

Von den 3 Hauptkomponenten des Frontends (HTML, CSS, JavaScript) muss vielleicht nur JavaScript-Code getestet werden. CSS wird durch eine rein visuelle Methode überprüft, wenn der Entwickler / Tester / Kunde die GUI in verschiedenen Browsern betrachtet. HTML-Markup wird mit derselben Methode validiert.

So testen Sie

Beim Erstellen von Testszenarien sollten Sie sich an den folgenden Grundsätzen orientieren:

  • Halten Sie Ihre Tests so einfach wie möglich. Dann ist es wahrscheinlicher, dass genau der Fehler, den Sie wiederholen möchten, die Ergebnisse seiner Implementierung beeinflusst.
  • Zerlegen Sie große Unit-Tests. Finden Sie den genauen Ort des Fehlers.
  • Machen Sie Ihre Tests unabhängig. Das Ergebnis eines Tests sollte in keiner Weise von den Ergebnissen eines anderen abhängen.
  • Testergebnisse müssen vollständig wiederholbar und zu erwarten sein. Jedes Mal, wenn Sie den Test erneut ausführen, sollte das Ergebnis das gleiche sein wie beim letzten Mal.
  • Für jeden Fehler bei der Ausführung der Anwendung muss ein Testskript erstellt werden. Auf diese Weise können Sie sicher sein, dass der Fehler tatsächlich behoben ist und den Benutzern nicht angezeigt wird.

Was zu testen

Es gibt mehrere Bibliotheken für Komponententests von js-Code. Am gebräuchlichsten ist vielleicht QUnit. Um Komponententests mit dieser Bibliothek durchzuführen, müssen wir eine "Sandbox" erstellen - eine einfache HTML-Seite, die die zu testende Bibliothek, den zu testenden Code und die Tests selbst enthält.

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

Auflistung der Tests:

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

Wie Sie sehen, unterstützt QUnit 3 Funktionen, um die Ergebnisse der Codeausführung mit den erwarteten zu vergleichen:

  • OK ()- betrachtet den Test als erfolgreich, wenn das zurückgegebene Ergebnis = wahr ist
  • gleich ()- vergleicht das Ergebnis mit dem erwarteten
  • tiefGleich ()- vergleicht das Ergebnis mit dem erwarteten und überprüft seinen Typ

Ausführungsergebnis:

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

Es gibt eine Reihe anderer Bibliotheken für Komponententests. Das Konzept, Testszenarien darin zu erstellen, ist jedoch das gleiche, so dass es Ihnen nicht schwer fallen wird, zu einem anderen zu wechseln, nachdem Sie sich mit einem befasst haben.

Wichtig zu merken

Ein Merkmal des modernen js-Codes ist seine asynchrone Ausführung. Testbibliotheken haben normalerweise die Möglichkeit, asynchrone Tests durchzuführen. Wenn Sie jedoch beispielsweise versuchen, eine Funktion zu testen, die beispielsweise eine Get-Anforderung an das Backend sendet und eine Antwort davon zurückgibt, müssen Sie den Thread mit der Funktion stop() stoppen, um die Tests auszuführen die zu testende Funktion und starten Sie dann den Thread mit der Methode start() neu, indem Sie ihn in setTimeout() "einpacken". Jene. Sie müssen einen bestimmten Zeitraum einstellen, in dem die Ausführung der Funktion abgeschlossen sein soll. Es ist notwendig, die Dauer dieses Segments sorgfältig zu wählen, .k. Einerseits kann die lange Arbeit der Methode entweder ein Merkmal oder sogar eine Notwendigkeit für eine bestimmte Implementierung der Anwendungsfunktionalität oder ein falsches Verhalten sein.

Backbone-Anwendungstests

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

Unit-Tests können Folgendes überprüfen:

  • Korrektes Erstellen von Modellen und Controllern
  • Richtigkeit der Daten in Modellen
  • Ausführung von Controller-Methoden (dazu müssen sie ein Ergebnis zurückgeben)
  • Aufrufe erfolgreich geladen

Testcode:

Test ("Backbone.js", Funktion () (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 (Daten); Daten zurückgeben;))), "Template-Ladeprüfung"); setTimeout (Funktion () (start (;), 1000);));

Ergebnis der Arbeit mit Testfehlern:

Testlaufautomatisierung

Typischerweise ist die Bereitstellung einer Anwendung eine Aufgabe, die in intensiver Entwicklung oft genug durchgeführt werden muss. Daher ist dieser Vorgang normalerweise automatisiert. Bei unserer Arbeit verwenden wir Jenkins, ein Continuous-Integration-Tool. Die Idee ist, die Jenkins-Bereitstellung mit automatisierten Tests zu kombinieren.

QUnit-Tests werden im Browser ausgeführt. Phantomjs, eine Software, die den Betrieb eines Browsers emuliert, hilft uns, diese Funktion zu umgehen. Die phantomjs-Entwickler haben bereits ein Skript zum Ausführen von QUnit-Tests bereitgestellt, jedoch für richtige Arbeit Ich musste es ein wenig modifizieren.

/ ** * Warten Sie, bis die Testbedingung wahr ist oder ein Timeout auftritt. * Nützlich für das Warten * auf eine Serverantwort oder für eine UI-Änderung (Einblenden usw.). * * @param testFx Javascript-Bedingung, die zu einem booleschen Wert ausgewertet wird, * sie kann als String übergeben werden (zB: "1 == 1" oder * "$ (" # bar "). is (": visible ")" oder * als Callback-Funktion * @param onReady was zu tun ist, wenn die TestFx-Bedingung erfüllt ist, * sie kann als String übergeben werden (zB: "1 == 1" oder * "$ (" # bar "). is (": visible") "oder * als Callback-Funktion. * @param timeOutMillis die maximale Wartezeit. Wenn * nicht angegeben, werden 3 Sekunden verwendet. * / function waitFor (testFx, onReady, timeOutMillis) (var maxtimeOutMillis = timeOutMillis?timeOutMillis: 3001, //< 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 Seite = neue Webseite (); // "console.log ()"-Aufrufe aus dem Page-Kontext // zum Haupt-Phantom-Kontext weiterleiten (d. h. das aktuelle "this") 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 10000;));phantom.exit ((parseInt (failedNum, 10)> 0)? 1: 0);));)));

Um Ergebnisse in der Konsole anzuzeigen, müssen Sie dem Testskript eine Protokollierungsfunktion hinzufügen.

Testen Sie Ihren Code- ein integraler Softwareentwicklungszyklus. Anfänger-Entwicklungsteams unterschätzen oft ihre Rolle und testen die Funktionalität der Anwendung auf altmodische Weise - "es funktioniert, aber es ist okay". Früher oder später scheitert diese Strategie und der Bugtracker beginnt, eine endlose Armee von Aufgaben zu überwältigen. Um nicht in eine ähnliche Falle zu tappen, empfehle ich ein für alle Mal, sich mit den Nuancen des Testens zu befassen JavaScript Code.

JavaScript ist nicht gleich

Heute JavaScript Ist nicht nur eine Sprache, um das Aussehen einer Anwendung zum Leben zu erwecken. Die Zeiten, in denen JavaScript für Witze oder das Erstellen von Menüs verwendet wurde, sind vorbei. Es ist jetzt eine eigenständige Sprache, die sowohl auf dem Client als auch auf dem Server gleichermaßen gut funktioniert. Die Rolle von JavaScript hat deutlich zugenommen, was bedeutet, dass Sie beim Schreiben von Code nicht zögern sollten, Praktiken zu verwenden, die sich in anderen Programmiersprachen bewährt haben.

Was meine ich mit Praktiken und Paradigmen? Natürlich, architektonisches Muster MVC (Modellansichtscontroller) und Muster der Codeorganisation. 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.

Der Fehler der meisten Tester

Es ist kein Geheimnis, dass die beliebteste Testmethode immer ein banaler "Sehtest" war. Seine Essenz ist einfach zu blamieren - schrieb ein paar tausend Zeilen Code, löste das Problem und startete Ihre Kreation. Gespielt, geklickt - alles scheint zu funktionieren, du kannst es auf den Kampfserver hochladen. Alles ist extrem einfach und mit gebührender Aufmerksamkeit des Entwicklers (idealerweise ein einzelner Spitzname "Tester") können Sie sich auf die korrekte Funktionsweise der Anwendung verlassen.

In der Praxis läuft alles ein bisschen anders ab. In der Regel gibt es keinen separaten Tester. Der Entwickler selbst versucht, die Funktionsfähigkeit des Programms zu überprüfen, indem er die in der technischen Aufgabenstellung angegebene Abfolge von Aktionen durchführt. Fortgeschrittenere Codeschmieden automatisieren diese Art von Integrationstests mit Dingen wie Selenium.

Somit ist der Programmierer in der Lage, nur die gröbsten Fehler zu erkennen. Leider bleiben "dumme" und "unbeabsichtigte" Benutzeraktionen sowie knifflige Schritte in der Geschäftslogik in 99% der Fälle hinter den Kulissen.

Die Anwesenheit einer separaten Person in der Person eines Testers löst das Problem auch teilweise und bis zu einer bestimmten Zeit. Selbst wenn wir seine technische Liebe zum Detail beiseite lassen, wird die Qualität seiner Tests mit zunehmender Anwendung gegen Null gehen. Lassen Sie mich Ihnen ein Beispiel aus der Praxis geben.

Einmal wurde ich beauftragt, ein kleines Programm zu entwickeln. Von der Funktionalität her ähnelte das Projekt dem einfachsten CRM, das ich in kürzester Zeit implementiert habe. Nach Erhalt der fälligen Vergütung übergab ich dem Kunden alle Quellen und vergaß das Projekt für acht Monate. Dann begann das Interessanteste. 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 neue Funktion nach der anderen zu formen. Anfangs war es nicht schwer, aber als es um die Gesamtintegration der Funktionalität ging, stürmte ein summender Schwarm von Bugs in meine Richtung. Teile des Codes kollidierten, und Sie mussten viel Zeit damit verbringen, Konflikte zu lösen. "Nun, wie haben Sie nicht gesehen, dass es ein Problem mit Ihrer Bewerbung gibt?" - aufmerksame Leser werden fragen. Ich habe damit angefangen, aber aufgrund der Tatsache, dass die Anwendung gewachsen ist, hatte ich einfach nicht genug Zeit und Nerven, um alle Funktionen in großen Mengen zu testen. Ich habe mich darauf beschränkt, nur einzelne Funktionen zu testen und dafür ordentlich bezahlt. Die Moral dieser Fabel lautet: "Betrachten Sie das Testen als einen integralen Bestandteil der Entwicklung."

Unit-Tests wie ein Allheilmittel

Unit Testing ist 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. Mit Unit-Tests können Sie den Testprozess automatisieren und alle Funktionen Ihrer Anwendung testen.

Nach Abschluss der Entwicklung neue Funktion(es ist möglich, vor Beginn der Entwicklung Tests zu schreiben) Der Entwickler schreibt einen speziellen Code, um seinen Code zu testen. Das Testen von Code muss verschiedene Situationen und Rückgabewerte simulieren. Zum Beispiel haben wir eine Funktion zum Trimmen von Leerzeichen (trim) geschrieben. Um seine Leistung zu testen, müssen wir mehrere Tests vorbereiten, die es uns ermöglichen, Folgendes zu bestätigen:

  • wenn wir den String "string" am Ausgang übergeben, erhalten wir "string";
  • beim Durchlaufen der Timeline "Zeile 9" erhalten wir am Ausgang "Zeile 9";
  • Wir können auch Tests für andere Eingabeparameter hinzufügen (z. B. das Leerzeichen durch einen Tabulator ersetzen). Generell gilt: Je besser wir den Code mit Tests abdecken und mögliche negative Optionen vorhersehen, desto größer ist die Chance, dass im entscheidenden Moment ein wenig Haare auf dem Kopf bleiben.

    In der JS-Welt werden Tests normalerweise mit spezialisierten Frameworks geschrieben. Sie enthalten alles, was Sie zum Beschreiben von Tests benötigen, sowie die am wenigsten schlechten Tools zum Organisieren von Berichten über den Testfortschritt.

    Tests! = Typenzusatz

    Nicht-Unit-Test-Entwickler argumentieren gerne, dass für Unit-Tests zusätzlicher Code geschrieben und gewartet werden muss. Sie sagen, dass die Fristen in realen Projekten oft knapp sind und es einfach keine Möglichkeit gibt, zusätzlichen Code zu schreiben.

    Aufgrund der knappen Fristen stimme ich zu, bin aber bereit, über den Extracode zu streiten. Einerseits, ja, Tests erfordern zusätzlichen Code und daher Zeit, ihn zu schreiben. Auf der anderen Seite spielt dieser Code die Rolle von Airbags im Auto und wird sich mit zunehmender Anwendung definitiv auszahlen.

    Wenn keine Zeit ist und der Wunsch, das Schreiben von Tests abzulehnen, quält - denken Sie dreimal nach. In diesem Fall kann es sinnvoller sein, nur die kniffligsten Teile des Codes mit Tests abzudecken und nicht ganz auf das Testen zu verzichten. Denken Sie immer mit Blick in die Zukunft, als ob Ihr Programm in einem Monat eine noch nie dagewesene Größe erreichen könnte.

    Nicht jeder Code ist getestet

    Warum argumentiere ich, dass Sie über Tests nachdenken müssen, bevor Sie den Hauptcode schreiben? Denn der Code, der ursprünglich von Unit-Tests abgedeckt werden sollte, ist in einem etwas anderen Stil geschrieben. Nicht jeder Code kann getestet werden. Code, der Logik und Präsentation vermischt und sogar dort vollgestopft ist, wo es unmöglich ist, normal zu testen. Hier rate ich Ihnen immer, ein paar einfache Regeln zu beachten:

  • Sie müssen keine großen Funktionen schreiben. Jede Funktion sollte ein Problem lösen, nicht 100.500 mögliche Situationen. Beispielsweise müssen Sie den Code zum Senden von Daten an den Server nicht in der für die Vorbereitung zuständigen Funktion hängen;
  • Eine Funktion mit mehr als 10 Codezeilen ist höchstwahrscheinlich eine schlechte Funktion;
  • Logik und Repräsentation sollten nie zusammengehören;
  • QUnit ist ein Klassiker des Genres von den Machern von jQuery

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

    Herunterladen letzte Version Sie können QUnit von der offiziellen Website aus durchführen - http://qunitjs.com/. Die Bibliothek wird als eine JS- und CSS-Datei geliefert. Angenommen, Sie haben die Belastung der erforderlichen Komponenten ermittelt, und wenn ja, ist es an der Zeit, einen Testtest zu schreiben. Lassen Sie uns nicht weit gehen und versuchen, die oben erwähnte trim()-Funktion zu testen.

    Um die Tests zu demonstrieren, habe ich ein einfaches Projekt mit folgendem Aufbau erstellt:

    Index.html - die Hauptdatei, die die Testergebnisse anzeigt; - qunit-1.12.0.js - qunit-Bibliotheksdatei; - example.js - eine Datei mit dem Code zum Testen (in unserem Fall die Beschreibung der trim()-Funktion); - 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 Listing 1 und 2 gezeigt. Am meisten interessiert uns das zweite Listing, das die Deklaration der getesteten Funktion (trim()) und den Code für die zu überprüfenden Tests zeigt dass es funktioniert. Passen Sie auf, die trim()-Funktion selbst kann sich überall befinden, ich habe sie in die zweite Liste gesetzt, nur um Platz im Protokoll zu sparen.

    Schauen wir uns nun die Tests selbst an. Um Integritätsprüfungen unseres Codes durchzuführen, muss die Bibliothek Qunit.js bietet uns eine Reihe von Methoden:

  • Prüfung ()- Wrapper für die Beschreibung des Tests;
  • OK ()- Mit der Anweisung können Sie die Wahrheit des ersten Parameters überprüfen. In unserem Beispiel übergebe ich ihm einen Aufruf an die von uns definierte trim()-Funktion und vergleiche mit dem Wert, den ich erwarte. Wenn die Bedingung wahr ist, ist der Test bestanden;
  • gleich ()- Mit der Methode können Sie die Gleichheit des ersten und zweiten Parameters überprüfen. Achte sofort darauf diese Methode führt eine lose Prüfung durch, daher nur für Skalare geeignet;
  • nicht gleich () Ist das Gegenteil von gleich (). Wird ausgeführt, wenn der erste Wert ungleich dem zweiten ist;
  • strengGleich ()-Ähnlich gleich () mit einem Unterschied - es verwendet eine strenge Prüfung (dh es prüft auch den Datentyp);
  • nichtStrengGleich ()- die Methode ist das Gegenteil von strictEqual();
  • tiefGleich ()- Methode für rekursive Anweisungen, verwendet für Primitive, Arrays, Objekte;
  • notDeepEqual ()- die Methode ist das Gegenteil von deepEqual();
  • erhebt ()- eine Assertion zum Testen von Callback-Funktionen, die eine Ausnahme auslösen;
  • In der zweiten Auflistung habe ich Ihnen gezeigt, wie Sie diese Methoden in der Praxis anwenden können. Wenn Sie einen Testfall in dieser Form ausführen, werden alle Tests erfolgreich bestanden (siehe entsprechende Abbildung). Um den Unterschied zwischen Bestehen und Nichtbestehen von Tests zu sehen, habe ich den Code für einen Test leicht modifiziert. In die Testleitung mit strengGleich () Ich habe wissentlich ein fehlerhaftes Ergebnis hinzugefügt (siehe entsprechende Abbildung).

    Listing 1. Inhalt der Datei index.html

    Testen mit QUnit

    Listing 2. Testdateien und trim()-Funktion

    function trim (string) (return (string || "") .replace (/ ^ \ s + | \ s + $ / g, "");) test ("Test trim () function", function () (ok (trim ("test") == "test", "trim off nachfolgende Leerzeichen"); ok (trim ("1") == "1", "viele Leerzeichen an den Seiten"); ok (trim ( "24") = = "24", "Leerzeichen und Tabulatoren an den Seiten"); equal (trim (""), "", "Leere Zeichenfolge"); strictEqual (trim ("] [aker")));

    Mit Prüfung einfache Funktionen irgendwie herausgefunden. 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 vorher eine andere, oft anfallende Aufgabe an JavaScript-Entwickler - Testen asynchrone Funktionen... Eine mit JavaScript-Code gefüllte Anwendung, die zu 99% mit der Serverseite über Ajax interagiert. Sie können diesen Code auch nicht deaktiviert lassen, aber das Schreiben von Tests sieht etwas anders aus. Betrachten wir ein Beispiel:

    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 angegeben wird, dass ich daran interessiert bin, asynchrone Tests zu testen. Dann starte 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. Beim Aufruf von asyncTest() wird der Thread gestoppt und muss am Ende des Tests gestartet werden. So steuern Sie den Ausführungsfluss in QUnit es gibt start()- und stop()-Methoden.

    Testen asynchroner Funktionen mit einer Bibliothek QUnit ist einfach genug. Das letzte Beispiel, auf das ich eingehen möchte, bezieht sich auf das Schreiben eines Tests, der mehrere asynchrone Prüfungen durchführt. Die Hauptfrage, die sich bei solchen Aufgaben stellt, ist der optimale Ort, um den Ausführungsfluss zu beginnen. Das offizielle Dokument schlägt vor, etwas zu verwenden wie:

    AsyncTest ("myAsyncFunc ()", function () (expect (3); // Hier drei Prüfungen durchführen ok (myAsyncFunc (), "Make the world better 1"); ok (myAsyncFunc (), "Make the world better 2 ") ; ok (myAsyncFunc (), "Making the World Better 3"); setTimeout (function () (start (;), 3000);));

    Auf benutzerdefinierte Aktionen testen

    Sie sollten immer daran denken, dass eine Menge aller möglichen Interface-Dinge in JavaScript geschrieben sind. Zum Beispiel klickt ein Benutzer auf einen Zuhälter und als Reaktion auf seinen Klick sollte etwas passieren. Es gibt eine riesige Menge an solchem ​​"Schnittstellen"-Code in Projekten und er muss auch mit Tests abgedeckt werden. Sehen wir uns an, wie Sie einen benutzerdefinierten Tastendruck simulieren und einen separaten Test für diese Aktion schreiben können. Stellen wir uns vor, wir haben eine Funktion, die die gedrückten Tasten protokolliert. Ich habe seinen Code in der dritten Auflistung angegeben:

    Listing 3. Tastenanschläge protokollieren

    Funktion KeyLogger (Ziel) (if (! (diese Instanz von KeyLogger)) (neuen KeyLogger (Ziel) zurückgeben);) this.target = target; this.log =; var self = this; this.target.off ("keydown") .on ("keydown", Funktion (Ereignis) (self.log.push (event.keyCode);));)

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

    Listing 4. Testcode für KeyLogger

    test ("KeyLogger test", function () (var event, $ doc = $ (document), keys = KeyLogger ($ doc); event = $ .Event ("keydown"); event.keyCode = 9; $ doc . Trigger (Ereignis); gleich (keys.log.length, 1, "Taste aufgezeichnet"); gleich (keys.log [0], 9, "Tastendruck mit Code 9 aufgezeichnet");));

    Ganz am Anfang der Auflistung mit dem Test bereite ich ein Ereignis vor, um den 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, woraufhin wir mit dem Testen beginnen können. Zuerst überprüfen wir das Gesamtbild - ob eine Taste gedrückt wurde und dann deren Code.

    DOM unter dem Deckmantel von Tests

    Zeit Qunit.js ermöglicht es Ihnen, benutzerdefinierte Aktionen zu testen, dann sollte das Schreiben von Tests für das DOM auch kein Problem sein. Dies ist wahr und das folgende Beispiel wird meine Worte bestätigen. Ich werde es nicht kommentieren, schau dir einfach den Code an und alles wird klar:

    Test ("Neues div-Element hinzufügen", Funktion () (var $ Fixture = $ ("# qunit-fixture"); $ Fixture.append ("

    Das ist die neue div
    "); equal ($ (" div ", $ Fixture) .length, 1," Neues div erfolgreich hinzugefügt! ");));

    Phantom.JS - Tests über die Konsole ausführen

    Schreiben Sie Tests mit der Bibliothek Qunit.js bequem und einfach, aber früher oder später werden Sie von dem Wunsch heimgesucht, den Start von Tests und die Sammlung von Ergebnissen irgendwie zu automatisieren. Ich habe beispielsweise eine separate Datei für diesen Fall. virtuelle Maschine in DigitalOcean, was ich nur mit der Konsole bewerkstelligen kann.

    Das Projekt phantom.js löst dieses Problem recht elegant. Dies ist nicht nur ein weiterer Rahmen zum Schreiben Unit-Tests, und eine vollwertige Konsolenversion der Engine WebKit... Einfach ausgedrückt emuliert diese Anwendung einen Browser. Mit Hilfe von phantom.js geht es wirklich nicht nur darum, die Prüfung der Testausführung zu automatisieren, sondern auch viele Probleme zu lösen, die früher oder später vor dem Entwickler auftreten: die Ergebnisse des Renderns von Seiten in eine Datei (png, jpg) zu bringen , Netzwerküberwachungsfunktionen (Ladegeschwindigkeit, Gesamtleistung usw.) usw.), Emulation von Benutzeraktionen usw. Ich empfehle, nicht faul zu sein 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 kompiliert werden (nix, mac OS X, windows). Wenn Sie alles unter Windows entwickeln, gibt es kein Problem - führen Sie die Binärdateien zusammen und legen Sie los. Kleinere Startprobleme können auftreten, wenn Sie zwei Videoadapter installiert haben, von denen einer NVidia ist. In diesem Fall müssen Sie den in der Seitenleiste beschriebenen Hack verwenden.

    Versuchen wir, phantom.js in der Praxis kennenzulernen. Zum Überspringen phantom.js Tests, die im letzten Abschnitt vorbereitet wurden, und um die Ergebnisse der Ausführung in der Konsole zu erhalten, benötigen wir ein spezielles Ladeskript - run-qunit.js. Wir öffnen die Konsole (ich arbeite unter Windows, also verwende ich cmd) und geben den Befehl im Format ein:

    Phantom.exe<путь к run-qunit.js> <путь к странице с тестами>

    In meinem Fall stellte sich der Startbefehl wie folgt dar:

    E: \ soft \ phantomjs > phantomjs.exe E: \ temp \ testjsforx \ qunit \ run-qunit.js-Datei: /// E: /temp/testjsforx/qunit/index.html Sein Ergebnis: Tests wurden in 2592 Millisekunden abgeschlossen. .. 9 Assertions von 9 bestanden, 0 fehlgeschlagen.

    Alle Prüfungen bestanden

    Es ist auf jeden Fall notwendig, den Code mit Tests abzudecken, und es spielt keine Rolle, wie groß die von Ihnen erstellte Anwendung ist. Ich erinnere Sie noch einmal daran, dass selbst die kleinsten Programme zu ungeschickten Monstern werden, die gewartet und mit Funktionalität ausgestattet werden müssen. Gut getesteter Code ist der Schlüssel zu Erfolg und Qualität. Ja, es ist nicht einfach, sofort mit dem Schreiben von Code für automatisierte Tests zu beginnen, aber glauben Sie mir, all dieses Leiden wird sich in Zukunft mit Zinsen auszahlen. Das war's für heute, viel Glück!

    Wenn keine Zeit für Tests ist

    Aus Zeitmangel macht es keinen Sinn, Tests für einfache Funktionen zu schreiben (nehmen Sie das gleiche trim() aus den Beispielen im Artikel). Es ist besser, sich auf die kritischsten Abschnitte des Codes zu konzentrieren. Dieselbe Regel sollte befolgt werden, wenn Sie Code schreiben, der sich häufig ändert. Technische Aufgabe Live-Projektänderungen recht 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 den neuen Daten, aber der alte verdaut nicht organisch. Um hier keinen Fehler zu erwischen, ähnliche Funktionen es ist besser, 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.

    Gute Testregeln

  • Der Test sollte so einfach wie möglich sein. Je schwieriger der Test, desto wahrscheinlicher sind Fehler;
  • Tests sollten in Module gruppiert werden, um später Fehler leichter 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 ein Fehler gefunden wird;
  • Phantom.js-Probleme unter Windows

    Es ist einfach so passiert, aber ich habe alle Beispiele für diesen Artikel nicht unter Linux, sondern unter dem guten alten Windows 7 getestet. Es stellt sich heraus, dass phantom.js einige kleinere Probleme hat, wenn man auf Systemen arbeitet, die mehrere Videoadapter verwenden. Auf meinem Laptop hängt NVidia neben dem integrierten Videochip immer noch rum und weigerte sich wegen phantom.js kategorisch, auf den Befehl phantom.exit() zu reagieren. Infolgedessen beendete der phantom.js-Prozess nach der Ausführung des Skripts seine Arbeit nicht und blieb weiterhin im Speicher hängen. Das Terminalfenster reagierte auch nicht mehr auf Exit-Befehle (Strg + C hat nicht geholfen).

    Wenn Sie auf ein ähnliches Problem stoßen und die Verwendung planen phantom.js unter Windows, machen Sie sich bereit, den nächsten Hack auszuprobieren. Öffnen Sie die Nvidia-Systemsteuerung. Suchen Sie im Baum den Punkt "3D-Einstellungen". Auf der rechten Seite sollte die Option "Bevorzugte Grafikkarte" erscheinen. Standardmäßig ist sein Wert auf "Auto Select" eingestellt. Wir müssen es in "High Performance Nvidia Processor" oder "Integrated Graphics Hardware" ändern. Nach diesem einfachen Trick phantom.js begann sich gehorsam zu verhalten.

  • Cristian Johansen "Test-Driven JavaScript Development" ist eines der wenigen Bücher, das sich mit JavaScript beim Schreiben von Tests beschäftigt;
  • John Rezing, Beer Beebo "Geheimnisse von JavaScript Ninja" - gutes Buch, die vor allem für JS-Entwickler mit mittlerer Erfahrung nützlich ist. Das Buch behandelt ausführlich die Themen des Schreibens von effektivem Cross-Browser-Code, die Nuancen der Ereignisbehandlung und viele andere Vorteile.
  • Testen ist ein integraler Bestandteil des Softwareentwicklungszyklus. Anfänger-Entwicklungsteams unterschätzen oft ihre Rolle und testen die Funktionalität der Anwendung auf altmodische Weise - "es funktioniert, aber es ist okay". Früher oder später scheitert diese Strategie und der Bugtracker beginnt, eine endlose Armee von Aufgaben zu überwältigen. Um nicht in eine solche Falle zu tappen, empfehle ich Ihnen, sich ein für alle Mal mit den Feinheiten des Testens von JavaScript-Code zu befassen.

    JavaScript ist kein Kuchen mehr!

    Sie müssen wahrscheinlich nicht erklären, dass JavaScript heute mehr ist als nur eine Sprache, um das Aussehen einer Anwendung zum Leben zu erwecken. Aber ich werde es trotzdem erklären und kurz vorstellen, denn dann werde ich mehr bezahlt mehr Geld! 🙂 Die Zeiten, in denen JavaScript für Witze oder das Erstellen von Menüs verwendet wurde, sind also unwiderruflich vorbei. Es ist jetzt eine eigenständige Sprache, die sowohl auf dem Client als auch auf dem Server gleichermaßen gut funktioniert. Die Rolle von JavaScript hat deutlich zugenommen, was bedeutet, dass Sie beim Schreiben von Code nicht zögern sollten, Praktiken zu verwenden, die sich in anderen Programmiersprachen bewährt haben.

    Was meine ich mit Praktiken und Paradigmen? Natürlich die MVC (Model View Controller) Architekturmuster und Codeorganisationsmuster. 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.

    Gute Testregeln

    • Der Test sollte so einfach wie möglich sein. Je schwieriger der Test, desto wahrscheinlicher ist es, Fehler zu machen.
    • Tests sollten in Module gruppiert werden, um später Fehler leichter 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 einen Fehler finden.

    Der Fehler der meisten Tester

    Es ist kein Geheimnis, dass die beliebteste Testmethode immer ein banaler "Sehtest" war. Seine Essenz ist einfach zu blamieren - schrieb ein paar tausend Zeilen Code, löste das Problem und startete Ihre Kreation. Gespielt, geklickt - alles scheint zu funktionieren, man kann es auf den Kampfserver hochladen. Alles ist extrem einfach und mit der richtigen Aufmerksamkeit des Entwicklers (idealerweise eines einzelnen Spitznamens "Tester") können Sie sich auf den korrekten Betrieb der Anwendung verlassen.

    In der Praxis läuft alles ein bisschen anders ab. In der Regel gibt es keinen separaten Tester. Der Entwickler selbst versucht, die Funktionsfähigkeit des Programms zu überprüfen, indem er die in der technischen Aufgabenstellung angegebene Abfolge von Aktionen durchführt. Fortgeschrittenere Codeschmieden automatisieren diese Art von Integrationstests mit Tools wie Selenium.

    Somit ist der Programmierer in der Lage, nur die gröbsten Fehler zu erkennen. Leider bleiben "dumme" und "unbeabsichtigte" Benutzeraktionen sowie knifflige Schritte in der Geschäftslogik in 99% der Fälle hinter den Kulissen.

    Das Vorhandensein eines separaten Testers löst das Problem auch teilweise und bis zu einer bestimmten Zeit. Selbst wenn wir seine technische Liebe zum Detail beiseite lassen, wird die Qualität seiner Tests mit zunehmender Anwendung gegen Null gehen. Lassen Sie mich Ihnen ein Beispiel aus der Praxis geben.

    Einmal wurde ich beauftragt, ein kleines Programm zu entwickeln. Von der Funktionalität her ähnelte das Projekt dem einfachsten CRM, das ich in kürzester Zeit implementiert habe. Nach Erhalt der fälligen Vergütung übergab ich dem Kunden alle Quellen und vergaß das Projekt für acht Monate. Dann begann das Interessanteste. Der Kunde beschloss, die Funktionalität des Programms ernsthaft zu erweitern, und rief mich um Hilfe. Natürlich nahm ich es und fing an, Funktion für Funktion zu formen ... Anfangs war es nicht schwierig, aber als es um die Gesamtintegration der Funktionalität ging, stürmte ein summender Schwarm von Bugs in meine Richtung. Teile des Codes kollidierten, und Sie mussten viel Zeit damit verbringen, Konflikte zu lösen. "Nun, wie haben Sie nicht gesehen, dass es ein Problem mit Ihrer Bewerbung gibt?" - Leser werden fragen. Ich werde antworten: Ich habe es ausgeführt, aber aufgrund der Tatsache, dass die Anwendung gewachsen ist, hatte ich einfach nicht genug Zeit und Nerven, um alle Funktionen in großen Mengen zu testen. Ich habe mich darauf beschränkt, nur einzelne Funktionen zu testen und dafür ordentlich bezahlt. Die Moral dieser Fabel lautet: "Betrachten Sie das Testen als einen integralen Bestandteil der Entwicklung."

    Unit-Tests sind wie eine Wunderwaffe

    Unit Testing ist 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 Tier noch nie begegnet sind, werde ich es kurz erklären. Mit 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 zu schreiben und vor Beginn der Entwicklung) schreibt der Entwickler speziellen Code, um seinen Code zu testen. Es muss verschiedene Situationen simulieren und Werte zurückgeben. Zum Beispiel haben wir eine Funktion zum Trimmen von Leerzeichen (trim) geschrieben. Um seine Leistung zu testen, müssen wir mehrere Tests vorbereiten, die es uns ermöglichen, Folgendes zu bestätigen:

    • wenn wir den String "string" am Ausgang übergeben, erhalten wir "string";
    • beim Durchlaufen der Timeline "Zeile 9" erhalten wir am Ausgang "Zeile 9";

    Wir können auch Tests für andere Eingabeparameter hinzufügen (z. B. das Leerzeichen durch einen Tabulator ersetzen). Generell gilt: Je besser wir den Code mit Tests abdecken und je mehr wir mögliche negative Optionen vorhersehen, desto höher ist die Chance, dass im entscheidenden Moment ein wenig Haare auf dem Kopf bleiben.

    In der JS-Welt werden Tests normalerweise mit spezialisierten Frameworks geschrieben. Sie haben alles, was Sie dafür brauchen, sowie einige Tools zum Organisieren von Berichten über den Testfortschritt.

    Tests! = Typenzusatz

    Nicht-Unit-Test-Entwickler argumentieren gerne, dass für Unit-Tests zusätzlicher Code geschrieben und gewartet werden muss. Sie sagen, dass die Fristen in realen Projekten oft knapp sind und es einfach keine Möglichkeit gibt, zusätzlichen Code zu schreiben.

    Wenn keine Zeit für Tests ist

    Aus Zeitmangel macht es keinen Sinn, Tests für einfache Funktionen zu schreiben (nehmen Sie das gleiche trim() aus dem Beispiel im Artikel), es ist besser, sich auf die kritischsten Teile des Codes zu konzentrieren. Dieselbe Regel sollte befolgt werden, wenn Sie Code schreiben, der sich häufig ändert. Die Leistungsbeschreibung für ein Live-Projekt ändert sich oft 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 den neuen Daten, aber der alte verdaut nicht organisch. Um hier keinen Fehler zu erwischen, ist es besser, solche Funktionen gleich zu überprüfen. Denken Sie an eine einfache Regel: Es bleibt keine Zeit, den gesamten Code mit Tests abzudecken – decken Sie den wichtigsten Teil ab.


    Was die engen Fristen angeht, stimme ich zu, aber ich bin bereit, über den zusätzlichen Code zu streiten. Einerseits ja - Tests erfordern zusätzlichen Code, was Zeit zum Schreiben bedeutet. Auf der anderen Seite spielt dieser Code die Rolle von Airbags im Auto und wird sich mit zunehmender Anwendung definitiv auszahlen.
    • Cristian Johansen "Test-Driven JavaScript Development" (goo.gl/mE6Is) ist eines der wenigen Bücher, das sich mit JavaScript beim Schreiben von Tests beschäftigt.
    • John Rezing, Be'er Beebo "Secrets of JavaScript Ninja" (goo.gl/xquDkJ) ist ein gutes Buch, das vor allem für fortgeschrittene JS-Entwickler nützlich sein wird. Das Buch behandelt ausführlich die Themen des Schreibens von effektivem Cross-Browser-Code, die Nuancen der Ereignisbehandlung und viele andere Vorteile.
    • David Flanagan „JavaScript. The Complete Guide “(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 auf JavaScript, das jeder JS-Entwickler mindestens einmal lesen muss.
    • PhantomJS + JSCoverage + QUnit oder Konsolen-JS-Komponententests mit Abdeckungsberechnung (goo.gl/FyQ38) – der Autor des Artikels demonstriert die Verwendung einer Reihe der aufgeführten Pakete, um Statistiken zu sammeln und den Prozentsatz der Codeabdeckung durch Tests zu berechnen.
    • Nützliche PhantomJS-Beispiele - Diese Seite bietet große Menge Kampfeinsatz von PhantomJS.

    Wenn keine Zeit ist und der Wunsch, das Schreiben von Tests abzulehnen, quält - denken Sie dreimal nach. In diesem Fall ist es vielleicht angebrachter, nur die kniffligsten Teile des Codes mit Tests abzudecken, anstatt das Testen komplett aufzugeben. Denken Sie immer mit Blick in die Zukunft, als ob Ihr Programm in einem Monat eine noch nie dagewesene Größe erreichen könnte.

    Nicht jeder Code ist getestet

    Warum argumentiere ich, dass Sie über Tests nachdenken müssen, bevor Sie den Hauptcode schreiben? Denn der Code, der zunächst von Unit-Tests abgedeckt werden soll, ist in einem etwas anderen Stil geschrieben. Nicht jeder Code kann getestet werden. Der Code, der Logik und Repräsentationen vermischt und sogar vollgestopft ist, kann nicht normal getestet werden. Hier rate ich Ihnen immer, ein paar einfache Regeln zu beachten:

    • Sie müssen keine großen Funktionen schreiben. Jede Funktion sollte ein Problem lösen, nicht 100.500 mögliche Situationen. Beispielsweise müssen Sie den Code zum Senden von Daten an den Server nicht in der für die Vorbereitung zuständigen Funktion hängen.
    • Eine Funktion mit mehr als zehn Codezeilen ist höchstwahrscheinlich eine schlechte Funktion.
    • Logik und Repräsentation sollten niemals zusammengehen.

    QUnit ist ein Klassiker des Genres von den Machern von jQuery

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


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

    Um die Tests zu demonstrieren, habe ich ein einfaches Projekt mit folgendem Aufbau erstellt:

    • index.html - die Hauptdatei, die die Testergebnisse anzeigt;
    • qunit-1.12.0.js - QUnit-Bibliotheksdatei;
    • example.js - eine Datei, die den Code zum Testen enthält (in unserem Fall die Beschreibung der trim()-Funktion);
    • 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 Listing 1 und 2 gezeigt. Am meisten interessiert uns das zweite Listing, das die Deklaration der getesteten Funktion (trim()) und den Code für die zu überprüfenden Tests zeigt dass es funktioniert. Passen Sie auf, die trim()-Funktion selbst kann sich überall befinden, ich habe sie in die zweite Liste gesetzt, nur um Platz im Protokoll zu sparen.
    Schauen wir uns nun die Tests selbst an. Die Bibliothek QUnit.js bietet uns eine Reihe von Methoden:

    • test() - Wrapper für die Testbeschreibung;
    • ok () - die Assertion ermöglicht es Ihnen, die Wahrheit des ersten Parameters zu überprüfen. In unserem Beispiel übergebe ich ihm einen Aufruf an die von uns definierte trim()-Funktion und vergleiche ihn mit dem Wert, den ich erwarte. Wenn die Bedingung wahr ist, ist der Test bestanden;
    • equal () - Mit der Methode können Sie die Gleichheit des ersten und zweiten Parameters überprüfen. Bitte beachten Sie gleich, dass diese Methode eine lose Prüfung durchführt und daher nur für skalare Werte geeignet ist;
    • notEqual() ist das Gegenteil von equal(). Wird ausgeführt, wenn der erste Wert ungleich dem zweiten ist;
    • strictEqual() - ähnlich wie equal() mit einem Unterschied - es verwendet strikte Prüfung (d. h. es prüft auch den Datentyp);
    • notStrictEqual () - das Gegenteil von strictEqual ();
    • deepEqual () - Methode für rekursive Assertionen, verwendet für Primitive, Arrays, Objekte;
    • notDeepEqual () - das Gegenteil von deepEqual ();
    • raises() ist eine Assertion zum Testen von Callback-Funktionen, die eine Ausnahme auslösen.

    In der zweiten Auflistung habe ich Ihnen gezeigt, wie Sie diese Methoden in der Praxis anwenden können. Wenn Sie einen Testfall in dieser Form ausführen, werden alle Tests erfolgreich bestanden (siehe entsprechende Abbildung). Um den Unterschied zwischen erfolgreichen Tests und fehlgeschlagenen Tests zu sehen, habe ich den Code für einen Test leicht modifiziert. Ich habe beim Test mit strictEqual() bewusst ein fehlerhaftes Ergebnis in die Zeile eingefügt (siehe entsprechende Abbildung).

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

    Wir haben das Testen einfacher Funktionen irgendwie herausgefunden. Ich habe jedenfalls nichts mehr hinzuzufügen. Als nächstes müssen Sie echten Code nehmen und versuchen, selbst Tests zu schreiben. Sehen wir uns eine weitere häufige Herausforderung für JavaScript-Entwickler an – das Testen asynchroner Funktionen. Eine mit JavaScript-Code vollgestopfte Anwendung, die zu 99 % mit dem Back-End über AJAX interagiert. Sie können diesen Code auch nicht deaktiviert lassen, aber das Schreiben von Tests sieht etwas anders aus. Betrachten wir ein Beispiel:

    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 angegeben wird, dass ich an asynchronen Tests interessiert bin. Dann starte ich die Wartezeit von 500 Millisekunden. 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. Beim Aufruf von asyncTest() wird der Thread gestoppt und muss nach Abschluss des Tests von selbst gestartet werden. QUnit stellt start()- und stop()-Methoden bereit, um den Ausführungsfluss zu steuern.


    Das Testen asynchroner Funktionen mit der QUnit-Bibliothek ist unkompliziert. Das letzte Beispiel, auf das ich eingehen möchte, bezieht sich auf das Schreiben eines Tests, der mehrere asynchrone Prüfungen durchführt. Die Hauptfrage, die sich bei solchen Aufgaben stellt, ist der optimale Ort, um den Ausführungsfluss zu beginnen. Das offizielle Dokument schlägt vor, etwas zu verwenden wie

    AsyncTest ("myAsyncFunc ()", function () (expect (3); // Wir machen hier drei Prüfungen ok (myAsyncFunc (), "Make the world better 1"); ok (myAsyncFunc (), "Make the world better 2") ; ok (myAsyncFunc (), "Making the World Better 3"); setTimeout (function () (start (;), 3000);));

    Auf benutzerdefinierte Aktionen testen

    Sie sollten immer daran denken, dass eine Menge aller möglichen Interface-Dinge in JavaScript geschrieben sind. Zum Beispiel klickt ein Benutzer auf einen Zuhälter und als Reaktion auf seinen Klick sollte etwas passieren. Es gibt eine riesige Menge an solchem ​​"Schnittstellen"-Code in Projekten, und er muss auch mit Tests abgedeckt werden. Sehen wir uns an, wie Sie einen benutzerdefinierten Tastendruck simulieren und einen separaten Test für diese Aktion schreiben können. Stellen wir uns vor, wir haben eine Funktion, die die gedrückten Tasten protokolliert. Ich habe seinen Code in der dritten Auflistung angegeben.

    Listing 3. Protokollierung gedrückter Tasten function KeyLogger (target) (if (! (This instanceof KeyLogger)) (return new KeyLogger (target);) this.target = target; this.log =; var self = this; this.target . aus ("keydown"). on ("keydown", function (event) (self.log.push (event.keyCode);));)

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

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

    Ganz am Anfang der Auflistung mit dem Test bereite ich ein Ereignis vor, um den 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, woraufhin wir mit dem Testen beginnen können. Zuerst überprüfen wir das allgemeine Bild - ob eine Taste gedrückt wurde und dann deren Code.

    DOM unter dem Deckmantel von Tests

    Da Sie mit Qunit.js benutzerdefinierte Aktionen testen können, sollte auch das Schreiben von Tests für das DOM kein Problem darstellen. Dies ist in der Tat der Fall, und das folgende Beispiel wird meine Worte bestätigen. Ich werde es nicht kommentieren, schau dir einfach den Code an und alles wird klar:

    Test ("Neues div-Element hinzufügen", Funktion () (var $ Fixture = $ ("# qunit-fixture"); $ Fixture.append ("

    Das ist die neue 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 wird Sie der Wunsch haben, den Start, das Testen und die Erfassung der Ergebnisse irgendwie zu automatisieren. Für diesen Fall habe ich beispielsweise eine separate virtuelle Maschine in DigitalOcean, die ich nur über die Konsole verwalten kann.

    Das PhantomJS-Projekt löst dieses Problem recht elegant. Dies ist nicht nur ein weiteres Framework zum Schreiben von Komponententests, sondern eine vollwertige Konsolenversion der WebKit-Engine. Einfach ausgedrückt emuliert diese Anwendung einen Browser. Mit Hilfe von PhantomJS ist es wirklich nicht einfach, die Überprüfung der Testausführung zu automatisieren, aber auch viele Probleme zu lösen, die früher oder später vor dem Entwickler auftreten: Ergebnisse des Renderns von Seiten in eine Datei (PNG, JPG), Netzwerk Überwachungsfunktionen (Ladegeschwindigkeit, Gesamtleistung usw.), Emulation von Benutzeraktionen usw. Ich empfehle, nicht faul zu sein 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 kompiliert werden (* nix, OS X, Windows). Wenn Sie alles unter Windows entwickeln, gibt es kein Problem - führen Sie die Binärdateien zusammen und legen Sie los. Leichte Startschwierigkeiten können auftreten, wenn Sie zwei Videoadapter installiert haben, von denen einer NVIDIA ist. 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 Ergebnisse der Ausführung in der Konsole zu erhalten, benötigen wir ein spezielles Ladeskript - run-qunit.js. Wir öffnen die Konsole (ich arbeite unter Windows, also benutze ich cmd) und geben den Befehl im Format ein

    phantom.exe<путь к run-qunit.js> <путь к странице с тестами>

    In meinem Fall stellte sich der Startbefehl wie folgt dar:

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

    Das Ergebnis seiner Ausführung:

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

    Alle Prüfungen bestanden

    Es ist auf jeden Fall notwendig, den Code mit Tests abzudecken, und es spielt keine Rolle, wie groß die von Ihnen erstellte Anwendung ist. Lassen Sie mich noch einmal daran erinnern: Selbst kleinste Programme werden zu plumpen Monstern, die gewartet und funktionalisiert werden müssen. Gut getesteter Code ist der Schlüssel zu Erfolg und Qualität. Ja, es ist nicht einfach, sofort mit dem Schreiben von Code für automatisierte Tests zu beginnen, aber glauben Sie mir, all dieses Leiden wird sich in Zukunft mit Zinsen auszahlen. Das ist alles für mich heute, viel Glück!

    PhantomJS-Probleme unter Windows

    Es ist einfach so passiert, aber ich habe alle Beispiele für diesen Artikel nicht unter Linux, sondern unter dem guten alten Windows 7 getestet. Es stellt sich heraus, dass PhantomJS einige kleinere Probleme hat, wenn auf Systemen mit mehreren Videoadaptern gearbeitet wird. Auf meinem Laptop hängt neben dem integrierten Videochip auch NVIDIA, und aus diesem Grund weigerte sich PhantomJS kategorisch, auf den Befehl phantom.exit () zu reagieren. 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 Exit-Befehle ( hat nicht geholfen).

    Wenn Sie mit einem ähnlichen Problem konfrontiert sind und vorhaben, PhantomJS unter Windows zu verwenden, dann machen Sie sich bereit für den folgenden Hack. Öffne das Panel NVIDIA-Steuerung... Suchen Sie im Baum den Punkt "3D-Einstellungen". Die Option "Bevorzugter Grafikadapter" sollte auf der rechten Seite erscheinen. Standard. sein Wert ist auf "Auto Select" gesetzt. Wir müssen es in "High Performance NVIDIA Processor" oder "Integrated Graphics Hardware" ändern. Nach diesem einfachen Trick begann sich PhantomJS gehorsam zu verhalten.

    Jetzt steht die Seite zum Testen von Wissen zu folgenden Themen zur Verfügung: HTML-Datei, CSS, JavaScript, PHP, SQL.

    Jeder Test besteht aus 10 Fragen zu einem bestimmten Thema. Bei jeder Frage habe ich versucht, die unterschiedlichsten Anwendungsgebiete einer bestimmten Sprache anzusprechen, um Ihren Kenntnisstand möglichst genau zu überprüfen.

    Natürlich alles kostenlose Tests und jeder kann sie durchlaufen.

    Testprozedur:

    1. Folge dem Link " Test starten"bei der entsprechenden Prüfung.
    2. Beantworten Sie die gestellten Fragen, indem Sie auswählen nur Korrekte Option.
    3. Nach Abschluss des Tests sehen Sie Ihre Punktzahl, Anzahl der Fehler, und auch Analyse jeder Frage aus dem Teig.

    Beachtung! Sie können nicht zur vorherigen Frage zurückkehren, also denken Sie nach, bevor Sie antworten.

    Aktuell verfügbare Tests

    1. HTML-Datei

      • Gesamtprüfung bestanden: 75424 Personen
      • Durchschnittsnote: 2.83 von 5 Punkte.

      Grundlagentest HTML-Datei... Sie müssen die Grundlagen kennen HTML-Tags, sowie deren kompetente Anwendung. Es ist auch notwendig, die Merkmale des Standards zu verstehen XHTML 1.1.

    2. CSS

      • Gesamtprüfung bestanden: 32.828 Personen
      • Durchschnittsnote: 3.37 von 5 Punkte.

      Der Test testet Kenntnisse der Grundlagen CSS... Um den Test erfolgreich zu bestehen, müssen Sie die grundlegenden Arten von Selektoren (ihre Syntax) kennen, die grundlegenden Eigenschaften und ihre möglichen Werte kennen und auch den Zweck der gängigsten Pseudoelemente kennen.

    3. JavaScript

      • Gesamtprüfung bestanden: 24845 Personen
      • Durchschnittsnote: 3,31 von 5 Punkte.

      Dieser Test testet Ihre Kenntnisse der JavaScript-Sprache. Die Fragen aus dem Test decken verschiedene Anwendungsbereiche der gegebenen Sprache ab. Es gibt viele Fragen zum Verständnis von "kleinen" Nuancen. Im Übrigen müssen Sie grundlegende Dinge wissen: Arbeiten mit Variablen, grundlegende JavaScript-Funktionen, Prioritäten von Operationen und so weiter.

    4. PHP

      • Gesamtprüfung bestanden: 33.239 Personen
      • Durchschnittsnote: 3,03 von 5 Punkte.

      Dieser Test testet Ihre Kenntnisse der PHP-Sprache. Sie müssen grundlegende PHP-Konstrukte kennen, mit Variablen, Sitzungen, Umleitungsimplementierungen und anderen Standarddingen arbeiten.
      Ernsthafte Bitte: Der Test enthält viele Fragen des Typs: "Was wird das Skript ausgeben?" Große Anfrage, keine Notwendigkeit, es zu kopieren und zu überprüfen. Sei ehrlich zu dir selbst.

    5. SQL

      • Gesamtprüfung bestanden: 18014 Personen
      • Durchschnittsnote: 3.28 von 5 Punkte.

      Dieser Test testet Ihre Kenntnisse der SQL-Abfragesprache. Fragen betreffen nur die grundlegendsten Kenntnisse dieser Sprache, ohne Vertiefung. Sie müssen die grundlegendsten SQL-Abfragen kennen und mit Bedacht verwenden.

    Fortsetzung des Themas:
    Modems

    Haben Sie sich schon lange Tricolor-TV-Satellitenfernsehen angesehen? Ist es an der Zeit, Ihren alten Receiver zu ersetzen? Jetzt ist die beste Zeit, um Ihre Träume wahr werden zu lassen. Auschecken ...