JSUnit
These days I've been doing more and more JScript, thanks to JQuery and ExtJs. I've been moving more and more of the application logic to the client side. That has some advantages and some disadvantages, which are clearly out of the scope of this post. The main disadvantage for me has always been that it's hard to unit test JavaScript. Until yesterday I thought it was impossible, but not anymore. Enter JSUnit.
Introduction
JSUnit allows you to easily unit test your JavaScript code. There are a few catches, though.
1) You should do Object-Oriented JavaScript in order to do that.
2) Your test classes have to be html pages with some fixed stuff.
Let's check each of them.
Object-Oriented JavaScript
What do I mean by that? I'll show it. It's easier to demonstrate by example.
Let's say I have this code:
1: <script>
2: if (myVar > 0){ 3: document.greaterThanZero = true;
4: }
5: else{ 6: document.greaterThanZero = false;
7: }
8: </script>
This code is very hard to unit test, since we don't have anything to call on in our test. Now let's say I rewrite that to be:
1: <script>
2: myClass = function(){ 3: this.checkGreaterThanZero = function (myVar){ 4: if (myVar > 0){ 5: document.greaterThanZero = true;
6: }
7: else{ 8: document.greaterThanZero = false;
9: }
10: };
11: }
12: </script>
Now that is easy to test. That's what I call Object-Oriented Javascript. You encapsulate your javascript code in classes and methods, in a way that makes them easier to test (and to use). Now let's get back to JSUnit.
Test Classes
Your test classes have to follow some conventions. From the JSUnit website:
A test page must "include" the jsunit/app/jsUnitCore.js JavaScript file; this file is the JsUnit engine. (This corresponds to extending the TestCase class in JUnit.)
That is, the document's <head> must contain the statement
<script language="JavaScript" src="jsUnitCore.js"></script>
Of course, you may need to change this to point at jsUnitCore.js if you are in a different directory. For example, since the JsUnit self tests live in jsunit/tests, they point at "../app/jsUnitCore.js".
You also need to name all your tests starting with "test", so JsUnit can automatically add them. For more information check the JsUnit documentation.
What this means is that if we wanted to test the above code, we would have a test file like this:
1: <html>
2: <head>
3: <title>Test Page for myClass.checkGreaterThanZero(value)</title>
4: <script language="javascript" src="jsUnitCore.js"></script>
5:
6: <!-- This is the file that contains our class! -->
7: <script language="javascript" src="myJsScripts.js"></script>
8: </head>
9: <body>
10: <script language="javascript">
11: function testWithGreaterThanZero() { 12: myClass.checkGreaterThanZero(4);
13: assertEquals("4 is greater than zero", true, document.greaterThanZero); 14: }
15: function testWithZero() { 16: myClass.checkGreaterThanZero(0);
17: assertEquals("0 is not greater than zero", false, document.greaterThanZero); 18: }
19: function testWithLowerThanZero() { 20: myClass.checkGreaterThanZero(-10);
21: assertEquals("0 is not greater than zero", false, document.greaterThanZero); 22: }
23: </script>
24: </body>
25: </html>
26:
That page unit tests the code that checks if a number is greater than zero for the three possible scenarios (greater than zero, zero and lower than zero).
Now that our test page is done, you just have to run it in the provided testRunner.html page that comes with JSUnit. It is pretty straightforward.
Conclusion
I can go back to have some of my application's logic live in Javascript, as long as I can unit test it. I hope this is helpful. In my next article I'll show how to make your JSUnit tests part of your NUnit run using Stormwind.Accuracy.
#145