6

Ich habe festgestellt, dass qUnit keine Benachrichtigung gibt, wenn in einem späteren Teil des Tests eine Ausnahme auftritt. Zum Beispiel wird diese in einem Test läuft():Warum erhält Ausnahme innerhalb des Rahmens keine Benachrichtigung in qUnit?

stop(); 
function myfun(ed) { 
    console.log('resumed'); 
    start(); //Resume qunit 
    ok(1,'entered qunit again'); 
    ok(ed.getContent()== 'expected content') // < causes exception, no getContent() yet. 
} 
R.tinymce.onAddEditor.add(myfun) 

in einem inneren iframe auf der Seite wird eine Ausnahme verursachen (Typeerror: ed.getContent ist keine Funktion), aber nichts in QUnit Statusbereich erzählt diese . Ich sehe 0 Fehler.

(R ist der innere Iframe, mit Technik hier: http://www.mattevanoff.com/2011/01/unit-testing-jquery-w-qunit/) Wäre ich in der Annahme richtig, dass dies nicht der beste Weg ist, Sequenzen der UI-Interaktion zu testen, die bestimmte Ergebnisse verursachen? Ist es immer besser, etwas Selen zu verwenden, sogar für einige meist Javascript-orientierte Front-End-Web-App-Tests?

Als eine Randnotiz zeigt die Firefox-Konsole die console.log unter der Ausnahme hier, obwohl es zuerst passiert ist ... warum?

Antwort

3

Wenn Sie sich den qUnit-Quellcode ansehen, gibt es zwei Mechanismen, die Ausnahmen behandeln. Einer wird von config.notrycatch Einstellung gesteuert und wird Test Setup, Ausführung und Teardown in try..catch Blöcke umbrechen. Diese Herangehensweise wird mit Ausnahmen, die von asynchronen Tests ausgelöst werden, nicht viel helfen, aber qUnit ist dort nicht der Aufrufer. Aus diesem Grund gibt es einen zusätzlichen window.onerror Handler, der von der Test.ignoreGlobalErrors Einstellung gesteuert wird. Beide Einstellungen sind standardmäßig false, so dass beide Arten von Ausnahmen abgefangen werden. In der Tat, der folgende Code (wie bei Ihnen im Wesentlichen gleich, aber ohne TinyMCE spezifische Teile) erzeugt die erwarteten Ergebnisse für mich:

test("foo", function() 
{ 
    stop(); 
    function myfun(ed) 
    { 
    start(); 
    ok(1, 'entered qunit again'); 
    throw "bar"; 
    } 
    setTimeout(myfun, 1000); 
}); 

ich zum ersten Mal eines bestandenen Tests mit der Meldung „eingegeben QUnit wieder“ und dann einem failed eins mit der Nachricht: "uncaught exception: bar." Wie, warum Sie dies nicht funktioniert, kann ich folgende Optionen:

  1. Ihre QUnit Kopie mehr als zwei Jahre alt ist, bevor qUnit issue 134 wurde behoben und ein globaler Exception-Handler hinzugefügt.
  2. Ihr Code ändert sich Test.ignoreGlobalErrors Einstellung (unwahrscheinlich).
  3. Es gibt einen vorhandenen window.onerror-Handler, der true zurückgibt und somit qUnit mitteilt, dass der Fehler behoben wurde. Ich habe überprüft, ob TinyMCE standardmäßig einen hinzufügt, aber es sieht nicht so aus.
  4. TinyMCE fängt Fehler in Ereignishandlern auf, wenn sie aufgerufen werden. Dies ist die logische Sache zu tun, wenn Sie mit mehreren Rückrufe zu tun, ist der übliche Ansatz etwas wie folgt aus:
for (var i = 0; i < callbacks.length; i++) 
{ 
    try 
    { 
    callbacks[i](); 
    } 
    catch (e) 
    { 
    console.error(e); 
    } 
} 

Durch alle Ausnahmen zu console.error Umleitung dies stellt sicher, dass Ausnahmen sind nach wie vor berichtet, während alle Callbacks selbst dann aufgerufen werden, wenn einer von ihnen eine Ausnahme auslöst. Da die Ausnahme jedoch behandelt wird, kann jQuery sie nicht mehr abfangen. Auch hier habe ich überprüft, ob TinyMCE dieses Muster implementiert - es sieht nicht so aus.

Update: Es gibt eine fünfte Option, an die ich nicht gedacht habe: Die Ausnahme wird innerhalb eines Rahmens ausgelöst und qUnit hat seinen globalen Fehlerhandler dort nicht eingerichtet (bereits, weil Tracking-Frame-Erstellung nicht ist -trivial, ein neuer Rahmen kann jederzeit erstellt werden).Dies sollte durch Hinzufügen des folgenden Code an dem Rahmen leicht behoben werden:

window.onerror = function() 
{ 
    if (parent.onerror) 
    { 
    // Forward the call to the parent frame 
    return parent.onerror.apply(parent, arguments); 
    } 
    else 
    return false; 
} 

Bezüglich Ihrer Neben Anmerkung: die console Objekt nicht garantieren Ihnen eine bestimmte Reihenfolge, in der Nachrichten angezeigt werden. Tatsächlich zeigt der Code console.log("foo");throw "bar"; auch zuerst die Ausnahme, gefolgt von der Protokollnachricht. Dies weist darauf hin, dass Protokollmeldungen in die Warteschlange gestellt und möglicherweise aus Leistungsgründen verzögert verarbeitet werden. Aber Sie müssen in Firefox die Implementierung des console Objekts überprüfen, um sicher zu sein - das ist ein Implementierungsdetail.

+0

Danke für eine ausführliche Antwort. Während "window.onerror" eine Funktion ist, sind 'window.frames [0] .onerror' und' window.frames [0] .frames [0] .onerror' null, wo Tests stattfinden. Es scheint, dass qUnit wurde nicht entworfen, um mit iframes zu laufen? Ich nehme an, ich könnte die Frames als Onerror der Frames festlegen oder sie irgendwie nennen, ich bin mir nicht sicher, ob es einen weniger hacky Weg gibt? Denkst du, qUnit wäre der empfohlene Ansatz dafür, nicht etwas wie Selenium oder andere? – NoBugs

+0

@NoBugs: Siehe mein Update. Was die Verwendung von qUnit betrifft - warum nicht? Es ist natürlich eine Frage der Vorlieben, aber Selen ist im Allgemeinen komplizierter anzuwenden. –