Monatliche Archive: Januar 2014

Armer Mann ist in JavaScript Zwischenspeichern.

[TL;DR-version: Verwenden Sie Cookies zum Speichern der Ergebnisse der asynchrone Aufrufe; die Ergebnisse der letzten asynchrone Aufrufe sofort gerendert, und überprüfen sie dann nach dem Laden der Seite.]

Ich habe auf SharePoint-Intranet-Site für einen Client, dass die Funktionen gearbeitet, unter anderem, eine stilisierte Sekundärnavigation dessen Menüoptionen über eine normale alte benutzerdefinierte Liste verwaltet werden.  Die Idee besteht darin, dass der Client "ihre" Site-Menü steuern, ohne zu beeinflussen oder durch die globale Navigation löschte dadurch beeinträchtigt wird.

(Es ist etwas unglaublich subversiven zum Hinzufügen eines CEWP, der auf einer HTML-Datei verweist, das lädt einige CSS und JS grundlegend verändern fast alles über eine Website Verhalten... aber das ist für einen anderen Beitrag)

Der Code für diese ziemlich einfach:

Die Wunde Punkt hier ist das jedes Mal, wenn jemand eine der Seiten hits, Web-Browser des Benutzers greift Elemente aus der Liste abgerufen.  Sobald Dev vollständig und Tests sind bewährt Dinge zu stabil und vollständig sein, Dieser Aufruf ist unnötig mehr als 99% die Zeit, da das Menü nur selten ändert.  Es hat auch einen seltsamen UI Affekt, der in dieser schönen neuen Welt von hyper-Ajaxy Websites üblich ist – die Seite macht und erst dann rendert das Menü.  Es ist nervös und störend aus meiner Sicht.  Und nervös. Also, Zwischenspeichern. 

Ich änderte die Logik Wasserverbrauch:

  • Suchen Sie ein Cookie im Browser, der Menü enthält, wie ich es zuletzt gelesen
    • Wenn gefunden, machen Sie es sofort.  Warten Sie nicht auf die Seite geladen.  (Sie müssen sicherstellen, dass Ihre HTML hier strategisch ist, aber es ist nicht schwer zu tun).
  • Warten Sie, bis die Seite fertig geladen und machen ein Async aufrufen, um Menüelemente aus einer Liste mit REST oder lists.asmx oder was auch immer zu laden
  • Vergleichen Sie, was ich mit dem cookie
    • Wenn es passt, STOP
    • Ansonsten, mithilfe von jQuery, ein paar dynamisch zu füllen, wenn <Li>ist in einem <UL>
  • Verwenden Sie CSS, um die Formatierung zu tun
  • Gewinn!

Einige von Ihnen werden sagen, "hey! Es gibt kein richtiger Zwischenspeichern hier da du sowieso das Menü liest jedes Mal.”  Und du hast Recht-ich gebe nicht dem Server jede Art von Bruch.  Aber weil der Aufruf asynchron und geschieht, nachdem die Seite erste ist rendert HTML-Nutzlast voll, es "fühlt"sich stärker auf den Benutzer.  Das Menü macht ziemlich viel wie die Seite zieht.  Wenn das Menü zur Änderung geschieht, der Benutzer wird eine unruhige neu zu ziehen des Menüs unterzogen, aber nur dieses eine Mal.

Es gibt einige Möglichkeiten, um diese Zwischenspeicherung effizienter und helfen den Server zur gleichen Zeit:

  • Setzen Sie in der Regel, dass der "Cookiecache" gültig für einen Mindestaufenthalt von ist 24 Stunden oder einige andere Zeitrahmen. Solange es keine abgelaufene cookie, Verwenden Sie das Cookie Menü Snapshot und nie schlagen Sie den server.

Nun... das ist alles, die was gerade in den Sinn kommen :). 

Wenn jemand hier eine clevere Idee hat würde ich gerne kennenlernen.

Und schließlich – kann diese Technik für andere Sachen verwendet werden.  Dieser Client-Seite hat eine Reihe von datengesteuerten Dingen auf verschiedenen Seiten, viele von ihnen ändern relativ selten (wie einmal pro Woche oder einmal im Monat).  Wenn Sie bestimmte Bereiche der Funktionalität gezielt, Sie können eine reaktionsschnellere Benutzeroberfläche geben, ziehen Inhalte aus dem lokalen Cookie laden und Rendern sofort.  Es fühlt sich schneller an den Benutzer, auch wenn Sie nicht den Server Schleifen speichern.  Sie können sparen Sie die Serverzyklen bei Entscheidung über einige Bedingungen und Auslöser dieser lokalen Cookiecache für ungültig erklären.  Das ist alles situationsabhängig und künstlerisch Zeug und wirklich am meisten Spaß :). 

</Ende>

undefinedOnnieren Sie meinen Blog ab.

Folgen Sie mir auf Twitter bei http://www.twitter.com/pagalvin

So wird es gemacht: Konfigurieren von Komponententests und Testabdeckung mit QUnit.js und Blanket.js für ein Büro 365 SharePoint-Webanwendung

Intro

Ich habe bereits erkundet Komponententests und Testabdeckung für JavaScript, wie ich an einem neuen SharePoint-app für SharePoint online im Büro arbeite 365 Suite.  Die offensichtliche Forschungs-Pfade führte mich zu Qunit.js und danach rechts, An Blanket.js.

QUnit Lass mich richten Sie Komponententests und in Module zu gruppieren.  Ein Modul ist nur eine einfache Möglichkeit, ähnliche Tests zu organisieren. (Ich weiß nicht, ob ich es verwende, wie beabsichtigt, aber es funktioniert für mich bisher mit den kleinen Satz von Tests, die ich bisher definiert haben).

Blanket.js Qunit integriert, und es zeigt mir die tatsächlichen Zeilen JavaScript, die – und vor allem waren nicht wirklich hingerichtet wurden im Laufe der Tests ausgeführt werden.  Das ist "Deckung"-Linien, die ausgeführt werden durch den Test abgedeckt, während andere nicht sind.

Zwischen guten Testfälle einrichten und anzeigen Abdeckung, Wir können das Risiko verringern, dass unser Code Mängel versteckt hat.  Gute Zeiten.

Qunit

Vorausgesetzt, Sie haben Ihre Visual Studio Projekt einrichten, durch das Herunterladen der JavaScript-Pakets aus starten http://qunitjs.com.  Die JavaScript und entsprechende CSS zur Projektmappe hinzufügen.  Bergwerk sieht wie folgt:

image

Abbildung 1

Wie Sie sehen können, Ich benutzte 1.13.0 damals schrieb ich in diesem Blog-post. Vergessen Sie nicht, laden und fügen Sie die CSS-Datei.

Das aus dem Weg, nächste Schritt ist eine Art Testumgebung zu erstellen und verweisen die Qunit-Bits.  Ich teste eine Reihe von Funktionen in einer Skriptdatei namens "QuizUtil.js", so dass ich eine HTML-Seite namens "QuizUtil_test.html erstellt" wie gezeigt:

image Abbildung 2

Hier ist der code:

<!DOCTYPE HTML>
<HTML xmlns= "http://www.w3.org/ 1999/xhtml">
<Kopf>
    <Titel>QuizUtil Test mit Qunit</Titel>
    <Verbindung rel= "stylesheet" href="../CSS/qunit-1.13.0.CSS" />
    <Skript Typ= Text/javascript"" src="QuizUtil.js" Daten-cover></Skript>
    <Skript-Typ ="Text/javascript" Src ="Qunit-1.13.0.js"></Skript>
    <Skript-Typ ="Text/javascript" Src ="blanket.min.js"></Skript>

    <Skript>
        Modul("getIDFromLookup");
        Test("QuizUtil getIDFromLookupField", Funktion () {
            var GoodValue = "1;#Paul Galvin";

            gleich(getIDFromLookupField(goodValue) + 1, 2), "Die ID des [" + goodValue + "] + 1 sollte 2";
            gleich(getIDFromLookupField(undefiniert), undefiniert, "Undefined Eingabeargument sollte nicht definierte Ergebnis zurückgeben.");
            gleich(getIDFromLookupField(""), undefiniert, "Leere Eingabeargument sollte einen nicht definierten Wert zurückgeben.");
            gleich(getIDFromLookupField("gobbledigood3-thq;Dkvn ada;Skfja sdjfbvubvqrubqer0873407t534piutheqw;VN"), undefiniert,"Sollte immer ein Ergebnis-Cabrio in eine ganze Zahl zurück");
            gleich(getIDFromLookupField("2;#eine andere person"), "2", "Checking [2;#eine andere person].");
            gleich(getIDFromLookupField("9834524;#Long-Wert"), "9834524", "Großen Wert Test.");
            notEqual(getIDFromLookupField("5;#Jeder", 6), 6, "Eine NotEqual-Prüfung (5 ist nicht gleich 6 für dieses Beispiel: [5;#Jeder]");

        });

        Modul("htmlEscape");
        Test("QuizUtil htmlEscape()", Funktion () {
            gleich(htmlEscape("<"), "&lt;", "Eine kleiner als-Operator-escaping ('<')");
            gleich(htmlEscape("<Div Class =  "Someclass">Text</div>"), "&lt;Div-Klasse =&quot;SomeClass&quot;&gt;Text&lt;/div&gt;", "Komplexer TestString.");
        });

        Modul("getDateAsCaml");
        Test("QuizUtil getDateAsCaml()", Funktion () {
            gleich(getDateAsCaml(Neu Datum("31.12.2013")), "2013-12-31T:00:00:00", "Testen hart codierte Datum: [12/31/2013]");
            gleich(getDateAsCaml(Neu Datum("01/05/2014")), "2014-01-05T:00:00:00", "Testen hart codierte Datum: [01/05/2014]");
            gleich(getDateAsCaml(Neu Datum("01/31/2014")), "2014-01-31T:00:00:00", "Testen hart codierte Datum: [01/31/2014]");
            gleich(getTodayAsCaml(), getDateAsCaml(Neu Datum()), "getTodayAsCaml() GetDateAsCaml sollte gleich sein.(neuer Termin())");
            gleich(getDateAsCaml("Unsinn Wert"), undefiniert, "Versuchen Sie, das Datum eines Unsinn-Wertes erhalten.");
            gleich(getDateAsCaml(undefiniert), undefiniert, "Versuchen, das Datum von der [undefiniert] Datum.");
        });

        Modul("getParameterByName");
        Test("QuizUtil getParameterByName (aus der Abfragezeichenfolge)", Funktion () {
            gleich(getParameterByName(undefiniert), undefiniert, "Versucht nicht definiert Parameter sollten undefined zurück.");
            gleich(getParameterByName("does not exist"), undefiniert, "Versuchen Sie, den Wert des Parameters zu erhalten, wenn wir wissen, dass der Parameter nicht vorhanden ist.");

        });

        Modul("Cookies");
        Test("QuizUtil verschiedene Cookie-Funktionen.", Funktion () {
            gleich(setCookie("test", "1", -1), getCookieValue("test"), "Get ein Cookie eingestellte sollte funktionieren.");
            gleich(setCookie("anycookie", "1", -1), wahr, "Einstellung eines gültigen Kochen sollte zurückgeben 'true'.");
            gleich(setCookie("crazy Cookie-name !@#$%"%\^&*(()?/><.,", "1", -1), wahr, "Einen schlechten Cookienamen festlegen sollte 'false' zurückgeben.");
            gleich(setCookie(undefiniert, "1", -1), undefiniert, "Passing als Cookie-Name nicht definiert.");
            gleich(getCookieValue("does not exist"), "", "Cookie existiert nicht Test.");
        });

    </Skript>
</Kopf>
<Körper>
    <div ID= "qunit"></div>
    <div ID= "Qunit-Leuchte"></div>

</Körper>
</HTML>

Es gibt mehrere Dinge, die hier passiert:

  1. Verweisen auf meinen code (QuizUtil.js)
  2. Verweisen auf Qunity.js
  3. Einige Module definieren (getIDFromLookup, Cookies, und andere)
  4. Platzierung einer <div> dessen ID ist "Qunit".

Dann, Ich ziehe einfach auf diese Seite und Sie erhalten etwas:

image

Abbildung 3

Wenn Sie, im oberen suchen, Sie haben ein paar Optionen, zwei davon sind interessant:

  • Ausblenden bestanden: Ziemlich offensichtlich.  Hilft Ihr Auge nur die Problembereiche und keine Menge Unordnung zu sehen.
  • Modul: (Drop-down-): Dies wird die Tests bis auf genau diese Gruppen von Tests zu filtern gewünschten.

Für die Tests selbst – einige Anmerkungen:

  • Selbstverständlich müssen Sie den Code zu schreiben, so dass es in erster Linie testbar ist.  Mit dem Tool kann helfen, diese Disziplin zu erzwingen. Zum Beispiel, Ich hatte eine Funktion namens "getTodayAsCaml()”.  Das ist nicht sehr getestet werden, da es keine Eingabeargument nimmt und es auf Gleichheit zu testen, Wir müssten den Testcode entsprechend das aktuelle Datum ständig zu aktualisieren.  Ich umgestaltet es, indem ein Daten-input-Parameter hinzufügen dann das aktuelle Datum wann ich heute in CAML-Format will übergeben.
  • Qunit Rahmen dokumentiert seine eigene Tests und es scheint ziemlich robust.  Es kann einfache Dinge wie auf Gleichheit testen und hat auch Unterstützung für Ajax-Stil-Aufrufe ("echte" oder verspottet mit Ihrer bevorzugten mocker).
  • Durch den Prozess auch zwingt Sie zu durchdenken Rand Fällen – was passiert mit "nicht definiert" oder Null an eine Funktion übergeben wird.  Es macht es tot einfach zu diesen Szenarien heraus zu testen.  Gute Sachen.

Abdeckung mit Blanket.js

Blanket.js ergänzt Qunit durch die Verfolgung der tatsächlichen Codezeilen, die im Laufe der Ausführung Ihres Tests ausführen.  Es integriert in Qunit, obwohl es eine ganz separate app ist Recht, Es spielt schön – es sieht wirklich wie es eine nahtlose app ist.

Das ist blanket.js in Aktion:

image Abbildung 4

image

Abbildung 5

(Sie haben tatsächlich klicken Sie auf das Kontrollkästchen "Enable Abdeckung" an der Spitze [siehe Abbildung 3] um dies zu ermöglichen.)

Die hervorgehobenen Zeilen in Abbildung 5 haben von einem meiner Tests nicht ausgeführt wurde, Also muss ich einen Test zu entwickeln, der sie ausgeführt werden, wenn ich volle Deckung will verursacht.

Blanket.js arbeiten mit den folgenden Schritten zu erhalten:

  1. Laden Sie es von http://blanketjs.org/.
  2. Dem Projekt hinzufügen
  3. Aktualisieren Sie Ihrer Testseite Kabelbaum (QuizUtil_test.html in meinem Fall) wie folgt:
    1. Der Referenzcode
    2. Dekorieren Sie Ihre <Skript> So verweisen:
    <Skript Typ= Text/javascript"" src="QuizUtil.js" Daten-cover></Skript>

Blanket.js nimmt das Attribut "Daten-Cover" und hat seinen Zauber.  Es hängt in Qunit, Aktualisiert die Benutzeroberfläche um die Abdeckung Option "Aktivieren" hinzuzufügen und voila!

Zusammenfassung (TL; DR)

Verwenden Sie Qunit, um Ihre Testfälle zu schreiben.

  • Laden Sie es
  • Dem Projekt hinzufügen
  • Schreiben Sie eine Testseite Kabelbaum
  • Erstellen Sie Ihre tests
    • Umgestalten Sie einige der Code testbar sein
    • Seien Sie kreativ!  Denken Sie an verrückt, unmöglich Szenarien und testen sie auf jeden Fall.

Verwenden Sie blanket.js, um die Abdeckung zu gewährleisten

  • Stellen Sie sicher, dass Qunit funktioniert
  • Download blanket.js und dem Projekt hinzufügen
  • Ihre Test-Harnisch-Seite hinzufügen:
    • Fügen Sie einen Verweis auf blanket.js
    • Fügen Sie ein Attribut "Daten-Cover" zu Ihrem <Skript> Tag
  • Führen Sie die Qunit-tests.

Ich nie habe nichts davon vor und hatte einige rudimentäre Sachen arbeiten in wenigen Stunden. 

Viel Spaß beim Testen!

</Ende>

undefinedOnnieren Sie meinen Blog ab.

Folgen Sie mir auf Twitter bei http://www.twitter.com/pagalvin