prettify

baseline

Javascript Unit Testing TDD

A simple HTML Page that runs all your unit tests (Only Is.Equal is implemented but more are coming).
The web app should be build as MVC or at least have a distinct Model (set of .js files).
Create a Folder "UnitTest".
Put the following files inside.

External dependencies

  • ins/ins.js
  • ins/Stopwatch.js
Scripts.Add all the scripts that contain the Model to be tested.
Add all the tests.

Tests.js

"use strict";
Scripts.Add("../Samples/Sample.js");
Tests["BaumeInd convert @20"] = [
   
function () {
       
var oSample = new Sample();
        oSample
.nSamBaumeInd = 12;
        oSample
.nSamBaumeTemp = 20;
       
Expect(oSample.BaumeInd20(), Is.EqualTo(12), "12@20 ⇒ 12");
        oSample
.nSamBaumeTemp = 18;    
       
Expect(oSample.BaumeInd20(), Is.EqualTo(11.9), "12@18 ⇒ 11.9");
        oSample
.nSamBaumeTemp = 22;
       
Expect(oSample.BaumeInd20(), Is.EqualTo(12.1), "12@22 ⇒ 12.11");
   
}
];
Tests["Baume ⇒ Sugar"] = [
   
function () {
       
var oSample = new Sample();
        oSample
.nSamBaume = 16.8;
       
Expect(oSample.Baume2Sugar(), Is.EqualTo(320.8), "Baume: 6.8 ⇒ Sugar");
   
}
];
Include, but DO NOT MAKE ANY CHANGES:

UnitTest.htm

<!DOCTYPE html>
<html>
<head>
   
<title>Unit Tests</title>
<link rel="stylesheet" href="UnitTest.css" />
</head>
<body>
<button id="btnRun">Run</button>
<table id="tabResults"><thead><tr>
<th></th><th>Actual</th><th>Expected</th><th>Description</th>
</tr></thead><tbody></tbody></table>

<script src="../ins/ins.js"></script>
<script src="../ins/StopWatch.js"></script>
<script src="UnitTest.js"></script>
<script src="Tests.js"></script>
</body>
</html>

UnitTest.css

#tabResults {
   
border-collapse:collapse;
}
#tabResults td,
#tabResults th {
   
border:1px solid #999;
}
#tabResults th {
   
text-align:left;
   
font-weight:normal;
}
#tabResults td:first-child {
   
text-shadow:
       
-1px -1px 0 #999,
       
1px -1px 0 #999,
       
-1px 1px 0 #999,
       
1px 1px 0 #999;
   
font-size:1.2em;
   
font-weight:bold;
}
#tabResults .Titlos {
   
background-color:#def;
   
text-shadow:none !important;
}
#tabResults td fieldset {
   
padding:2px;
   
margin:0;
   
font-weight:normal !important;
   
background-color:#fdd;
}
#tabResults td fieldset legend {
   
background-color:#fed;
   
border-width:1px 1px 0 1px;
   
border-style:solid;
}

UnitTest.js

"use strict";
var Scripts = {};
var Tests = {};
//============================================================================================
var oC = {}
oC
.oSW = new ins.Stopwatch();
oC
.Startup=function() {
   
var oScr, nPos;
   
for (nPos = 0; nPos < Scripts.length; nPos++) {
        oScr
= document.createElement("script");
        oScr
.src = Scripts[nPos];
        document
.getElementsByTagName("body")[0].appendChild(oScr);
   
}
    $
("btnRun").onclick = oC.Run;
}
oC
.Run = function () {
   
var oTbody = $("tabResults").querySelector("tbody");
   
var nPos;
    oTbody
.Clear();
   
var oTest, oTd;
   
for (var sKey in Tests) {
       
if (!Tests.hasOwnProperty(sKey)) continue;
        oTd
= oV.Test(sKey);
        oTest
= Tests[sKey];
       
this.oSW.Start();
       
try {
           
for (nPos = 0; nPos < oTest.length; nPos++) {
                oTest
[nPos]();
           
}
       
} catch (ex) {
            oV
.TestError(oTd, ex);
       
} finally {
           
this.oSW.Stop();
       
}
        oV
.TestTitle(oTd, sKey + " (" + this.oSW.toString() + ")");

   
}
};
oC
.nScripts = 0;
oC
.ScriptLoaded = function () {
    oC
.nScripts--;
   
if (oC.nScripts <= 0) oC.Run();
};
Scripts.Add = function (sScript) {
    oC
.nScripts++;
   
var oScr = document.createElement("script");
    oScr
.onload = oC.ScriptLoaded; //ie9
    oScr
.src = sScript;

    document
.body.appendChild(oScr);
};
document
.addEventListener("DOMContentLoaded", oC.Startup, false);
//============================================================================================
var oV = {}
oV
.Expect = function (oResult) {
   
var oTbody = $("tabResults").querySelector("tbody");
   
var oTr,oTd;
    oTr
=oTbody.a$("tr").
        a$
("td", { t: (oResult.bResult ? "✔" : "✘"), "style": "fontWeight:bold;color:#" + (oResult.bResult ? "0f0" : "f00") }).parentNode.
        a$
("td", { t: oResult.Expected.toString(),"style":"textAlign:"+(typeof oResult.Expected === "number"?"right":"left") }).parentNode.
        a$
("td", { t: oResult.Actual.toString(), "style": "textAlign:" + (typeof oResult.Actual === "number" ? "right" : "left") }).parentNode.
        a$
("td", { t: oResult.sMsg });
};
oV
.Test = function () {
   
var oTbody = $("tabResults").querySelector("tbody");
   
return oTbody.a$("tr").a$("td", {"class":"Titlos", colSpan:4});
};
oV
.TestTitle = function (oTd, sTitle) {
    oTd
.a$({ t: sTitle });
};
oV
.TestError = function (oTd, oEr) {
    oTd
.a$("fieldset", {"class":"Error"}).a$("legend", { t: "Error" }).parentNode.
    a$
({ style: "", t:
   
"Name: " + oEr.name+
   
"\nMessage: " + oEr.message +
   
(oEr.number? "\nNumber: " + (oEr.number & 0xFFFF).toString():"")+
   
(oEr.fileName ? "\nfileName: " + oEr.fileName : "")+
   
(oEr.lineNumber ? "\nlineNumber: " + oEr.lineNumber : "")+
   
(oEr.stack ? "\nstack: " + oEr.stack : "")+
   
(oEr.toSource ? "\nSource: " + oEr.toSource() : "")
   
});
};
//============================================================================================
var Expect = function (Val, Obj, sMsg) {
   
if (Obj.operator === "===") {
        oV
.Expect({
            bResult
: (Val === Obj.value),
           
Expected: Val,
           
Actual: Obj.value,
            sMsg
: sMsg
       
});
   
}
};
var Is = {};
Is.EqualTo = function (obj) {
   
var oRet = {};
   
if (typeof obj === "number") {
        oRet
.type = "number";
        oRet
.value = obj;
        oRet
.operator = "===";
   
}
   
return oRet;
};

No comments:

Post a Comment