![]() |
Web Development »
Client side scripting »
General
Beginner
License: The Code Project Open License (CPOL)
Unit Test for JavaScriptBy Roberto 'Obi-Wan' Colnaghi JuniorHow to strengthen your client-side code and improve reliability |
Javascript, Dev, QA
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
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.)
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.
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.
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".
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?
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.
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.
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!
Some great resources on the Web:
debugHelper is required now. | You must Sign In to use this message board. | |||||||||||||||
|
|||||||||||||||
|
|||||||||||||||
|
|||||||||||||||
|
|||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads.
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 14 Dec 2007 Editor: Deeksha Shenoy |
Copyright 2007 by Roberto 'Obi-Wan' Colnaghi Junior Everything else Copyright © CodeProject, 1999-2010 Web10 | Advertise on the Code Project |