JQuery Kochbuch (German Edition)
führen, dass der Test fehlschlägt, weil der Test Runner den Fehler abfängt und den Test als nicht erfolgreich klassifiziert.
Asynchrone Callbacks testen
Problem
Während
expect()
nützlich ist, um synchrone Callbacks zu testen (siehe Synchrone Callbacks testen ), ist es nicht sinnvoll einzusetzen, wenn man asynchrone Callbacks testet. Solche Callbacks passen nicht zur Art und Weise, wie der Test Runner die Tests ausführt. Wenn der zu testende Code einen Timeout, ein Intervall oder eine Ajax-Anfrage startet, führt der Test Runner den Rest des Tests und alle folgenden Tests aus, statt auf das Ergebnis einer asynchronen Operation zu warten.
Lösung
Es gibt zwei Funktionen, um den Test Runner manuell mit der asynchronen Operation zu synchronisieren. Rufen Sie
stop()
vor jeder asynchronen Operation auf und
start()
, nachdem alle Assertions ausgeführt wurden. Dann kann der Test Runner mit den anderen Tests fortfahren:
test("Ein Test", function() { stop();
$.getJSON("/someurl", function(result) { equal(result.value,
"someExpectedValue"); start(); }); });
Diskussion
Ein Nachteil der manuellen Synchronisation ist das Risiko, dass
start()
niemals aufgerufen wird, wenn der zu testende Code an anderer Stelle fehlerhaft ist. In diesem Fall kann der Test Runner seine Arbeit niemals abschließen und damit auch die Endergebnisse nicht anzeigen. Selbst die Ergebnisse des aktuellen Tests sind nicht mehr verfügbar, so dass nur das Ergebnis des vorigen Tests zu sehen ist.
Wenn das geschieht, müssen Sie zuerst den Test ermitteln, der sich nicht abschließen lässt. Dazu schauen Sie sich den vorigen Test an und finden danach im Code den nächsten, fehlerhaften Test. Ist das geschehen, können Sie das Debuggen vereinfachen, indem Sie dem Aufruf von
stop()
ein Timeout-Argument mitgeben:
test("Ein Test", function() {
stop(500); $.getJSON("/someurl", function(result) { equal(result.value,
"someExpectedValue"); start(); }); });
In diesem Beispiel würde der Test Runner (mit Hilfe von
setTimeout
) 500 ms darauf warten, bis der Test abgeschlossen ist und ansonsten den Test als nicht erfolgreich deklarieren und mit der Ausführung fortfahren. Durch Analyse der Ergebnisse von anderen Tests kann es dann viel einfacher sein, das eigentliche Problem herauszufinden und zu beheben.
Das Timeout-Argument sollte aber nicht für normale Tests genutzt werden. Haben Sie es zu Debugging-Zwecken hinzugefügt, entfernen Sie es, wenn der Test wieder funktioniert.
Warum das? Der Nachteil des Timeouts ist, dass die Tests nichtdeterministisch werden. Lässt man den Test auf einem langsamen Rechner oder unter starker Last laufen, kann der Timeout zu langsam sein und einen ansonsten perfekten Test als nicht erfolgreich klassifizieren lassen. Die Suche nach einem Fehler, der gar nicht existiert, ist sehr zeitaufwändig und frustrierend – vermeiden Sie es also möglichst.
Benutzeraktionen testen
Problem
Code, der auf von Benutzern ausgelösten Aktionen aufbaut, kann nicht einfach durch den Aufruf einer Funktion getestet werden. Normalerweise ist eine anonyme Funktion an das Event eines Elements gebunden, zum Beispiel einen Klick, der simuliert werden muss.
Lösung
Sie können das Event mit der jQuery-Methode
trigger()
auslösenund prüfen, ob das erwartete Verhalten auftritt. Wollen Sie nicht, dass die Browser-eigenen Events ausgelöst werden, können Sie
triggerHandler()
verwenden, um nur die gebundenen Eventhandler auszuführen. Das ist nützlich, wenn Sie ein Click-Event für einen Link testen, bei dem
trigger()
dafür sorgen würde, dass der Browser die Seite wechselt – was für einen Test selten das gewünschte Verhalten ist.
Lassen Sie uns annehmen, dass wir einen einfachen Keylogger testen wollen:
var keylogger = { log: null, init:
function() { keylogger.log = [];
$(document).unbind("keydown").keydown(function(event) {
keylogger.log.push(event.keyCode); }); } };
Wir können ein Keypress-Event manuell auslösen, um herauszufinden, ob der Logger funktioniert:
test("basic keylogger behavior",
function() { // Initialisieren keylogger.init(); // Event auslösen var
event = $.Event("keydown"); event.keyCode = 9;
$(document).trigger(event); // erwartetes Verhalten überprüfen
deepEqual(keylogger.log.length, 1, "Eine Taste wurde protokolliert");
deepEqual(keylogger.log[0], 9, "Die richtige Taste wurde
protokolliert"); });
Diskussion
Ist Ihr Eventhandler nicht von bestimmten Eigenschaften des Events abhängig,
Weitere Kostenlose Bücher