Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Unit Test for JavaScript

14 Dec 2007 1  
How to strengthen your client-side code and improve reliability
Screenshot -

Disclaimer

The author does not accept responsibility for any effects, adverse or otherwise, that this code may have on you, your computer, your sanity, your dog, and anything else that you can think of. Use it at your own risk. (Deja Vu? I also love the Allegro disclaimer.)

Quick and Dirty Tour

So you don't like to read all articles you see on the Web, or you don't have time for it? Then, just download the source files, and open the unitjs.htm file in your favorite browser.

Background

Although the library uses advanced DOM and JavaScript functionality, you need only to have basic knowledge of HTML and JavaScript to use and extend the tool.

Introduction

Unit tests are unquestionable friends of every developer and, if you don't think that way, maybe it's because you never tried it before (see NUnit for more Unit Tests information). I'm not covering Unit Tests or Test Driven programming here, but keep in mind that it makes your code reliable, makes you confident after code changes and makes your boss cheerful (which is good, right?). Remember that this client-side unit test algorithm is a newly born idea, not a solid development with years of usage like server-side unit test software. This means both "less functionality is available" and "report any bugs you find, please".

Overview - Test Method

Since I don't like creating my own standards, I've used a syntax very similar to NUnit. Ain't that cool? You don't even need to learn how to do it if you are familiar with NUnit, just pay attention to the small differences. First, let's assert we're in the same line:

//Create a test case
function TestGuidAlgorithm()
{
    Console.Out.Write("Test guid algorithm...");
    Assert.That( "hello", new Is.EqualTo("hello") );                  
    Console.Out.Write("done!");
}

In the above code, I've created a test method, outputting to the console some information and asserting some constraint. When we run the test fixture, this test will be included. Are you thinking: "Text case? Text fixture? What are you talking about?"? I'll give you a very brief explanation. A collection of test methods is called a test fixture. And I call test methods as test cases. That was brief, uh?

What to Test - The Component

First, let me show you what we're going to test now. I've created a pseudo-guid generator for automatic field id attribution. The purpose is to create a unique ID every time you call the method.

//Component to be tested
function _GuidComponent()
{
    // Uniqueidentifier seed
    this.GUID = 0;
}
// Uniqueidentifier generator
_GuidComponent.prototype.GetNew = function()
{
    return "o_" + this.GUID++;
}
var guidComponent = new _GuidComponent();
            
...
                        
var currentUid = guidComponent.GetNew();
//Should be "o_0";
currentUid = guidComponent.GetNew();
//Should be "o_1";

Looking at this algorithm, I've came up with two test cases to certify that the code works and that the generated ID is indeed unique.

How To Test It - Text Fixture

Now, we need to create our Text Fixture. Here you are going to see some differences due to the JavaScript language nature.

//Text Fixture
function GuidTest()
{
    this.Description = "Unit tests to exercise Guid component";
    this.Category = "Helpers";
}
//JavaScript inheritance. It is similar to implementing a interface.
GuidTest.prototype = new ITextFixture();
//Java script hack to maintain the correct constructor
GuidTest.prototype.constructor = GuidTest;

It should be very straightforward to understand the code above, except for the last two commands. Basically, it means to JavaScript-like inherit from a class and get its functionalities. Explaining it more than that would be far from the scope of this article but, if you're curious, post a comment and I'll explain it to you a little bit more.

The next step is to override some of the fixture functionality, if you ever need to do that. Here, we're keeping track of the running time of each test method.

//Override the test Setup method
//Setup: Common set of functions that are performed just before 
//each test method is called
GuidTest.prototype.SetUp = function()
{ 
    this.StartTime = new Date();
}

//Override the test TearDown method
//TearDown: Common set of functions that are performed after each test method is run
GuidTest.prototype.TearDown = function()
{
    var elapsedTime = new Date().getTime() - this.StartTime.getTime();
    Console.Out.Write("Finished in " + (elapsedTime / 1000 / 60) + "ms || " + 
        (elapsedTime / 1000) + "s");
}
            
//Create the test fixture instance
var guidTestFixture = new GuidTest();

And last, but not least, the test cases themselves.

//Create a test case
function TestGuidAlgorithm()
{
    Console.Out.Write("Test guid algorithm...");

    for(var i = 0; i<3; i++)
    {
        var currentUid = guidComponent.GetNew();
        Assert.That( currentUid, new Is.EqualTo("o_" + i) );
    }
                
    Console.Out.Write("done!");
}

//Add test case to test fixture
guidTestFixture.AddTest(TestGuidAlgorithm);
            
//Create another test case
function TestDifferentGuids()
{
    Console.Out.Write("Test different guids algorithm...");

    for(var i = 0; i<3; i++)
    {
        var currentUid = guidComponent.GetNew();
        //Assert.That( currentUid, new Is.NotEqualTo("o_" + i) );
        //Force guid algorithm to fail (just for illustration, 
        //you don't really want your tests to fail right?)
        Assert.That( currentUid, new Is.EqualTo("o_" + i) );
    }
                
    Console.Out.Write("done!");
}

//Add test case to test fixture
guidTestFixture.AddTest(TestDifferentGuids);

Remember to add the tests to the fixture or they won't run when you fire the fixture. If you're a C# developer, you may have noticed that this step is necessary since we don't have attributes in JavaScript. Yet!

And finally, add your fixture to the engine and run everything!

//Add test fixture to unit.js engine
UnitJs.AddTextFixture(guidTestFixture);
//Run all test fixtures
UnitJs.Run();

Currently, I've implemented few IConstraint methods: EqualTo, NotEqualTo (there's no Not class), GreaterThan, GreaterThanOrEqualTo, LessThan and LessThanOrEqualTo.

Oh, and yes, the debug window is backwards. I personally prefer to see the last events first, but I can show you how to revert the order if you want.

Conclusion

And that's all I have to offer for now! Please feel free to ask for new functionality, report bugs or to tell me how cool this stuff is. Enjoy!

References

Some great resources on the Web:

History

  • 12-13-2007
    • Original article
  • 12-15-2007
    • Removed unnecessary files and reduced dependency on external scripts. Only the debugHelper is required now.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here