Använd TDD vid JavaScript-utveckling

Med tiden som webbläsare utvecklas och kan tolka JavaScript snabbare så ökar möjligheten att skriva tunga webbaserade applikationer baserade på just JavaScript. När JavaScript-funktionerna blir mer avancerade så blir även logiken bakom det mer komplicerad. Det händer allt oftare att man har en stor mängd affärslogik i JavaScript.

För den affärslogiken som är baserad på server-kod som till exempel C# så är det lätt att utveckla den enligt TDD (Test Driven Development) vilket ökar säkerheten i koden och minskar antalet buggar genom att man skriver tester och sedan själva logiken.

Vad gäller JavaScript så brukar det ofta bli så att man utvecklar JavaScripten allt eftersom (gärna med ett bibliotek som jQuery, MooTools, YUI, Prototype eller liknande bakom). Dessvärre så har bristen på testverktyg (eller åtminstonde uppmärksamheten bland dessa) lett till att det lätt kan bli fel. En anledning till detta är att det är svårt att testa alla funktioner i alla webbläsare, då olika webbläsare tenderar att tolka ECMAScript-standarden olika.

För att göra det lättare för sig så finns det faktiskt ett par verktyg som kan lösa det här, och ett som jag gillar är JsUnitTest. Det gör det möjligt att skapa HTML-dokument som sedan används för att testa de olika funktionerna. Det är ett verktyg som är helt baserat på JavaScript, och är taget från Prototype. Det kräver dock inte att man använder Prototype själv på sidan.

Jag kommer att gå igenom ett enkelt exempel där vi skapar en Bil-klass med olika egenskaper.

Först och främst så behöver vi ladda ned js-filen för JsUnitTest (verktyget i sig är skrivet i JavaScript). Den finns här:

http://jsunittest.com/dist/jsunittest.js

Sen behöver vi skapa upp ett enkelt HTML-dokument där vi skall ha våra tester.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <title>Test: Bil</title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <script src="../assets/jsunittest.js" type="text/javascript"></script>
    <script src="../assets/bil.js" type="text/javascript"></script>
    <link rel="stylesheet" href="../assets/unittest.css" type="text/css" />
</head>
<body>
    <div id="content">
        <div id="header">
            <h1>Test: Bil</h1>
            <p>
                This file tests <strong>bil.js</strong>.
            </p>
        </div>
        <div id="testlog" />
    </div>
 
    <script type="text/javascript">
        //Här kommer våra tester
    </script>
 
</body>
</html>

Mitt projekt i Visual Studio ser ut så här nu:

1

Bil.js låter vi än så länge vara tom, och unittest.css kan ni antingen ladda ned i ett demoprojekt från JsUnitTests hemsida, eller genom den bifogade filen i bloggposten.

Till att börja med så ska vi lägga till ett test i html-sidan som kollar om objektet ”Bil” existerar.

Vi lägger till detta i script-elementet på sidan:

var test = new Test.Unit.Runner({
 
    testBilFinns: function() {
        with (this) {
            var bil = Bil;
            assert(bil);
        }
    }
});

Alla test vi skapar måste skickas in som parameter i metoden Test.Unit.Runner. Här har vi ett test vid namn ”testBilFinns” och som helt enkelt kollar om objektet finns. Om man använder ett objekt som är null i en if-sats så returneras false, annars true. Därmed kan vi enkelt kolla om objektet existerar genom att köra en assert på objektet i sig.

När vi nu kör sidan så kommer div-elementet med id ”testlog” att fyllas på med information från testet.

Det vi får upp är detta:

2

Eftersom vi inte har skapat objektet så får vi undefined som svar, vilket betyder att det inte är skapat.

Om vi öppnar upp bil.js och lägger till detta:

var Bil = { }

Så får vi istället:

3

Eftersom vi nu har skapat upp objektet “Bil” så går testet igenom.

Nu hoppar jag fram lite för att inte behöva ta upp alla olika tester, utan tar upp ett exempel där vi har två properties, en för färgen på bilen och en som visar antalet däck.

Först och främst så ska vi ha två tester som kollar de olika funktionera. I båda testerna så skickar vi in värden till metoder som vi sedan skall få tillbaka.

Testerna:

testBilensFärgÄrBlå: function() {
    with (this) {
        var bil = Bil;
        bil.setFärg('blå');
        assert(bil.färg, 'blå');
    }
},
 
testBilenHarFyraDäck: function() {
    with (this) {
        var bil = Bil;
        bil.setDäck(4);
        assert(bil.däck == 4);
    }
}

De här testerna skall ligga i samma metod som det första testet.

När vi kör det så får vi:

4

Eftersom vi inte har skapat upp egenskaperna bil.färg och bild.däck, samt metoderna bil.setFärg och bil.setDäck så får vi fel här.

Genom att skapa upp dem:

var Bil = {
    färg: null,
    däck: 0,
    setFärg: function(färg) { this.färg = färg; },
    setDäck: function(däck) { this.däck = däck; }
}

Så får vi:

5

Är man petig så finns det många fler tester att skapa upp på vägen, men det var bara en demo over hur det fungerar, så klaga inte på det. ;-)

Det är alltså möjligt att genom att skapa upp separata html-filer, kunna testa sina JavaScript-metoder på ett väldigt enkelt sätt. Genom att öppna upp dessa HTML-filer i andra webbläsare så kan vi även se om de fungerar som väntat i dessa vilket kan spara enorma mängder tid under felsökning.

Lycka till och testa på!

Ladda ned exemplet

1 Comment

Comments have been disabled for this content.