maandelijkse archieven: Januari 2014

Arme Man de Caching in JavaScript

[TL;DR versie: gebruik van cookies voor het opslaan van de resultaten van asynchrone oproepen; de resultaten van afgelopen async oproepen onmiddellijk renderen en vervolgens valideren ze na het laden van de pagina.]

Ik heb gewerkt op SharePoint intranet-site voor een client die functies, onder andere, een gestileerde secundaire navigatie waarvan menu-opties worden beheerd via een regelmatige oude aangepaste lijst.  Het idee is dat de client krijgt om "hun" site systeemmenu zonder te tasten of wordt beïnvloed door de wereldwijde navigatie stak door het.

(Er is iets ongelooflijk subversieve over het toevoegen van een CEWP die verwijst naar een HTML-bestand dat ladingen sommige CSS en JS fundamenteel veranderen bijna alles over van een site probleem... maar dat is voor een andere post)

De code voor dit vrij eenvoudig:

De zere plek hier is dat elke keer als iemand hits een pagina van de site, webbrowser van die gebruiker is het bereiken uit om items uit de lijst.  Zodra dev voltooid is en dingen te testen heeft bewezen stabiel en voltooien, deze oproep is onnodig meer dan 99% van de tijd sinds het menu zelden verandert.  Heeft ook een raar UI invloed die gebruikelijk is in deze heerlijke nieuwe wereld van hyper-ajaxy websites-de pagina maakt en alleen dan heeft het menu maken.  Het is zenuwachtig en afleidend in mijn mening.  En zenuwachtig. Dus, opslaan in de cache. 

Ik heb gewijzigd de logica thusly:

  • Zoek naar een cookie in de browser die het menu bevat als ik laatst lezen
    • Als gevonden, maken het onmiddellijk.  Wacht niet op de pagina te laden voltooien.  (U moet ervoor zorgen dat uw HTML-code wordt strategisch geplaatst hier, maar het is niet moeilijk om te doen).
  • Wachten op de pagina te laden voltooien en maak een async oproepen voor vracht opwaarts menu-items uit een lijst met behulp van REST of lists.asmx of wat dan ook
  • Vergelijken wat ik heb tegen de cookie
    • Als het overeenkomt met, STOP
    • Anders, met behulp van jQuery, dynamisch vullen een bos als <Li>de in een <UL>
  • Gebruik CSS te doen alle opmaak
  • Winst!

Sommigen van u zullen zeggen, "hey! Er is geen echte in het voorgeheugen onderbrengende gaat hier omdat je het lezen van het menu hoe dan ook elke keer.”  En je hebt gelijk-ik ben niet het geven van de server elke soort pauze.  Maar omdat de oproep async is en gebeurt na de pagina's eerste HTML-nettolading volledig maakt, het voelt"" ontvankelijker voor de gebruiker.  Het menu maakt vrij veel als de pagina vestigt.  Als het menu aan de verandering gebeurt, de gebruiker is onderworpen aan een zenuwachtig opnieuw te tekenen van het menu, maar slechts die één keer.

Er zijn een aantal manieren aan deze cache doeltreffender maken en helpen de server op hetzelfde moment:

  • Zet in een regel dat de cache"cookie" geldig voor een minimum van is 24 uren of sommige andere tijdsbestek. Zolang er geen verlopen cookie is, gebruik van de cookie menu momentopname en nooit hit de server.

Nou... dat is alles wat die te binnen schieten nu :). 

Als iemand slimme ideeën hier heeft zou ik graag willen weten ze.

En tot slot – deze techniek kan worden gebruikt voor andere dingen.  Deze client pagina heeft een aantal data-gedreven dingen op verschillende pagina 's, velen van hen veranderen relatief zelden (zoals een keer per week of eenmaal per maand).  Als u zich richten op specifieke gebieden van functionaliteit, u kunt een meer responsieve UI geven door trekken inhoud uit de lokale cookie store en meteen renderen.  Het voelt sneller aan de gebruiker, zelfs als u niet de server elke cycli opslaat.  U kan Sla de server cycli door te besluiten op een aantal voorwaarden en triggers om deze lokale cookie cache ongeldig te maken.  Dat is allemaal situationele en kunstzinnige spullen en echt de leukste :). 

</einde>

undefinedAbonneren op mijn blog.

Volg mij op Twitter op http://www.twitter.com/pagalvin

Procedures: Unit Test en Test dekking met QUnit.js en Blanket.js voor een Office configureren 365 SharePoint App

Intro

Ik heb het verkennen van eenheid die test en test dekking voor JavaScript als ik werk op een nieuwe SharePoint-app voor SharePoint online in het kantoor 365 Suite.  De paden voor de hand liggende onderzoek leidde me om te Qunit.js en direct na dat, Aan Blanket.js.

QUnit laat me eenheid tests instellen en groeperen in modules.  Een module is gewoon een eenvoudige manier om te organiseren gerelateerde tests. (Ik ben niet zeker dat ik gebruik het als bedoeld, maar het werkt voor mij tot nu toe met de kleine set van tests die ik tot nu toe hebt gedefinieerd).

Blanket.js integreert met Qunit en het zal mij de feitelijke lijnen van JavaScript die waren- en nog belangrijker-werden niet daadwerkelijk uitgevoerd tijdens het uitvoeren van de tests.  Dit is "dekking"-lijnen die uitgevoerd worden gedekt door de test, terwijl anderen niet zijn.

Tussen goede testcases instellen en weergeven van de dekking, We kunnen het risico dat onze code heeft verborgen gebreken.  Goede tijden.

Qunit

Veronderstellend hebt u uw Visual Studio project instellen, Begin door te downloaden van het pakket JavaScript uit http://qunitjs.com.  De JavaScript en bijbehorende CSS toevoegen aan uw oplossing.  Mine ziet er als volgt:

image

Figuur 1

Zoals u kunt zien, Ik was met behulp van 1.13.0 op het moment schreef ik deze blogpost. Vergeet niet om te downloaden en het CSS-bestand toevoegen.

Dat uit de weg, volgende stap is het maken van een soort van testuitrusting en verwijst naar de Qunit bits.  Ik ben het testen van een heleboel functies in een scriptbestand genaamd "QuizUtil.js" dus ik heb een HTML-pagina met de naam "QuizUtil_test.html gemaakt" zoals:

image Figuur 2

Hier is de code:

<!DOCTYPE HTML>
<HTML xmlns= 'http://www.w3.org/ 1999/xhtml">
<hoofd>
    <titel>QuizUtil test met Qunit</titel>
    <koppeling rel= "stylesheet" href="../CSS/qunit-1.13.0.CSS" />
    <script type= text/javascript"" src="QuizUtil.js" gegevens-cover></script>
    <script type ="text/javascript" src ="qunit-1.13.0.js"></script>
    <script type ="text/javascript" src ="blanket.min.js"></script>

    <script>
        module("getIDFromLookup");
        test("QuizUtil getIDFromLookupField", functie () {
            var goodValue = "1;#Paul Galvin";

            gelijke(getIDFromLookupField(goodValue) + 1, 2), "ID van [" + goodValue + "] + 1 2 moeten worden";
            gelijke(getIDFromLookupField(undefined), undefined, "Niet-gedefinieerde invoer argument moet ongedefinieerde resultaat te retourneren.");
            gelijke(getIDFromLookupField(""), undefined, "Lege invoer argument moet een niet-gedefinieerde waarde retourneren.");
            gelijke(getIDFromLookupField("gobbledigood3-thq;dkvn ada;skfja sdjfbvubvqrubqer0873407t534piutheqw;VN"), undefined,"Moeten altijd terug een resultaat Cabrio naar een geheel getal");
            gelijke(getIDFromLookupField("2;#enige andere persoon"), "2", "Checking [2;#enige andere persoon].");
            gelijke(getIDFromLookupField("9834524;#Long-waarde"), "9834524", "Grote waarde test.");
            notEqual(getIDFromLookupField("5;#iedereen", 6), 6, "Het testen van een notEqual (5 is niet gelijk aan 6 voor dit voorbeeld: [5;#iedereen]");

        });

        module("htmlEscape");
        test("QuizUtil htmlEscape()", functie () {
            gelijke(htmlEscape("<"), "&lt;", "Ontsnappen een minder dan, operator ('<')");
            gelijke(htmlEscape("<div class =  "someclass">Sommige tekst</div>"), "&lt;div class =&quot;someclass&quot;&gt;Sommige tekst&lt;/div&gt;", "Meer complexe test string.");
        });

        module("getDateAsCaml");
        test("QuizUtil getDateAsCaml()", functie () {
            gelijke(getDateAsCaml(Nieuw Datum("12/31/2013")), "2013-12-31T:00:00:00", "Testing hard gecodeerde datum: [12/31/2013]");
            gelijke(getDateAsCaml(Nieuw Datum("01/05/2014")), "2014-01-05T:00:00:00", "Testing hard gecodeerde datum: [01/05/2014]");
            gelijke(getDateAsCaml(Nieuw Datum("01/31/2014")), "2014-01-31T:00:00:00", "Testing hard gecodeerde datum: [01/31/2014]");
            gelijke(getTodayAsCaml(), getDateAsCaml(Nieuw Datum()), "getTodayAsCaml() moet gelijk zijn aan getDateAsCaml(nieuwe datum())");
            gelijke(getDateAsCaml("onzin waarde"), undefined, "Proberen om de datum van de waarde van een onzin.");
            gelijke(getDateAsCaml(undefined), undefined, "Probeer om de datum van de [undefined] datum.");
        });

        module("getParameterByName");
        test("QuizUtil getParameterByName (uit de querytekenreeks)", functie () {
            gelijke(getParameterByName(undefined), undefined, "Proberen om te krijgen niet-gedefinieerde parameter ongedefinieerde moet retourneren.");
            gelijke(getParameterByName("does not exist"), undefined, "Proberen om de waarde van de parameter wanneer we weten dat de parameter niet bestaat.");

        });

        module("Cookies");
        test("QuizUtil verschillende cookie functies.", functie () {
            gelijke(setCookie("test", "1", -1), getCookieValue("test"), "Get een cookie ik ingesteld zou moeten werken.");
            gelijke(setCookie("anycookie", "1", -1), True, "Instellen van een geldig koken moet retourneren 'true'.");
            gelijke(setCookie("gekke cookienaam !@#$%"%\^&*(()?/><.,", "1", -1), True, "Instellen van een slechte cookienaam moet retourneren 'valse'.");
            gelijke(setCookie(undefined, "1", -1), undefined, "Passing ongedefinieerde als de cookienaam.");
            gelijke(getCookieValue("does not exist"), "", "Cookie does not exist test.");
        });

    </script>
</hoofd>
<lichaam>
    <div id"qunit ="></div>
    <div id= "qunit-armatuur"></div>

</lichaam>
</HTML>

Er zijn verschillende dingen gebeuren hier:

  1. Verwijzen naar mijn code (QuizUtil.js)
  2. Verwijzen naar Qunity.js
  3. Sommige modules definiëren (getIDFromLookup, Cookies, en anderen)
  4. Plaatsen van een <div> waarvan de ID is "qunit".

Vervolgens, Ik trek alleen deze pagina en krijg je zoiets als dit:

image

Figuur 3

Als je aan de bovenkant kijkt, u hebt een paar opties, waarvan er twee zijn interessant:

  • Verbergen voorbij tests: Vrij duidelijk.  Kan helpen uw oog gewoon zien de probleemgebieden en niet een heleboel rommel.
  • Module: (drop-down): Dit zal de tests tot alleen die groepen van tests die u wilt filteren.

Wat betreft de tests zelf-een paar opmerkingen:

  • Het spreekt vanzelf dat you need to Schrijf uw code zodanig zijn dat het in de eerste plaats testbare is.  Met behulp van het hulpprogramma kunt afdwingen die discipline. Bijvoorbeeld, Ik had een functie genaamd "getTodayAsCaml()”.  Dit is niet zeer testbare aangezien het geen invoer argument neemt en testen voor gelijkheid, We zouden moeten voortdurend actualiseren van de test-code om te reflecteren op de huidige datum.  Ik refactored het door een invoerparameter gegevens toevoegen dan langs de huidige datum wanneer ik wil de datum van vandaag in CAML formaat.
  • Het Qunit kader documenten zijn eigen proeven en het lijkt vrij robuust.  Het kan doen eenvoudige dingen zoals testen voor gelijkheid en heeft ook ondersteuning voor ajax stijl oproepen (zowel de "echte" of de mocked met behulp van uw favoriete mocker).
  • Gaan door het proces ook dwingt je om na te denken door middel van randgevallen – wat er gebeurt met "undefined" of null wordt doorgegeven aan een functie.  Het maakt het doodsimpel om te testen deze scenario's uit.  Goed spul.

Dekking met Blanket.js

Blanket.js is een aanvulling op Qunit door het bijhouden van de werkelijke lijnen van code die in de loop van het runnen van uw tests worden uitgevoerd.  Het integreert dus zelfs al is het een hele aparte app recht in Qunit, het speelt mooi-het echt lijkt alsof het is een naadloze app.

Dit is blanket.js in actie:

image Figuur 4

image

Figuur 5

(Je eigenlijk hebben om te klikken op het selectievakje "Enable dekking" aan de bovenkant [Zie figuur 3] om dit mogelijk te maken.)

De gemarkeerde regels in figuur 5 niet zijn uitgevoerd door een van mijn tests, dus ik moet ontwikkelen een test die leidt hen om uit te voeren tot als ik wil volledige dekking.

Krijgen blanket.js werken door deze stappen te volgen:

  1. Het downloaden van http://blanketjs.org/.
  2. Toe te voegen aan uw project
  3. Bijwerken van uw testpagina harnas (QuizUtil_test.html in mijn geval) als volgt:
    1. Verwijst naar de code
    2. Versier uw <script> verwijst naar uitzien:
    <script type= text/javascript"" src="QuizUtil.js" gegevens-cover></script>

Blanket.js pikt het kenmerk "gegevens-cover" en doet zijn magie.  Het haken in Qunit, bijgewerkt de UI als u wilt toevoegen de optie "Enable dekking" en voila!

Samenvatting (TL; DR)

Gebruik Qunit om te schrijven uw testcases.

  • Downloaden
  • Toe te voegen aan uw project
  • Schrijf een testpagina harnas
  • Maak uw tests
    • Sommige van uw code testbare refactoring
    • Wees creatief!  Denk aan gek, onmogelijk scenario's en test hen toch.

Gebruik blanket.js om dekking

  • Zorg ervoor dat Qunit werkt
  • Blanket.js downloaden en toevoegen aan uw project
  • Toe te voegen aan uw harnas testpagina:
    • Voeg een verwijzing toe naar blanket.js
    • Voeg een "gegevens-cover" kenmerk toe aan uw <script> Label
  • Uw Qunit tests uitvoeren.

Ik nooit heb een van deze vóór en had sommige rudimentaire dingen werken in een handvol uur. 

Gelukkig testen!

</einde>

undefinedAbonneren op mijn blog.

Volg mij op Twitter op http://www.twitter.com/pagalvin