Basics of Exception Handling Mechanism in JavaScript Testing

Exclusive offer: get 50% off this eBook here
JavaScript Testing Beginner's Guide

JavaScript Testing Beginner's Guide — Save 50%

Test and debug JavaScript the easy way.

$26.99    $13.50
by Yuxian Eugene Liang | August 2010 | Beginner's Guides Open Source

In this article, by Liang Yuxian Eugene, author of JavaScript Testing Beginner's Guide, we will learn more about JavaScript testing. More specifically, we'll learn how to test more complex code, where there will be more interactions between entities.

More specifically, we'll cover the following:

  • Issues with combining scripts
  • Using JavaScript libraries
  • Deliberately throwing your own JavaScript errors

(For more resources on JavaScript, see here.)

Issues with combining scripts

Consider the real-life situation where we typically use external JavaScript; what happens if we use more than one JavaScript file? What kind of issues can we expect if we use more than one external JavaScript file? We'll cover all of this in the subsections below. We'll start with the first issue—combining event handlers.

JavaScript helps to bring life to our web page by adding interactivity. Event handlers are the heartbeat of interactivity. For example, we click on a button and a pop-up window appears, or we move our cursor over an HTML div element and the element changes color to provide visual feedback.

To see how we can combine event handlers, consider the following example, which is found in the source code folder in the files combine-event-handlers.html and combine-event-handlers.js as shown in the following code:

In combine-event-handlers.html, we have:

<html>
<head>
<title>Event handlers</title>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="combine-event-
handlers.js"></script>
</head>
<body>
<div id="one" onclick="changeOne(this);"><p>Testing One</p></div>
<div id="two" onclick="changeTwo(this);"><p>Testing Two</p></div>
<div id="three" onclick="changeThree(this);"><p>Testing
Three</p></div>
</body>
</html>

Notice that each of the div elements is handled by different functions, namely, changeOne(), changeTwo(), and changeThree() respectively. The event handlers are found in combine-event-handlers.js:

function changeOne(element) {
var id = element.id;
var obj = document.getElementById(id);
obj.innerHTML = "";
obj.innerHTML = "<h1>One is changed!</h1>";
return true;
}
function changeTwo(element) {
var id = element.id;
var obj = document.getElementById(id);
obj.innerHTML = "";
obj.innerHTML = "<h1>Two is changed!</h1>";
return true;
}
function changeThree(element) {
var id = element.id;
var obj = document.getElementById(id);
obj.innerHTML = "";
obj.innerHTML = "<h1>Three is changed!</h1>";
return true;
}

You might want to go ahead and test the program. As you click on the text, the content changes based on what is defined in the functions.

However, we can rewrite the code such that all of the events are handled by one function. We can rewrite combine-event-handlers.js as follows:


function combine(element) {
var id = element.id;
var obj = document.getElementById(id);
if(id == "one"){
obj.innerHTML = "";
obj.innerHTML = "<h1>One is changed!</h1>";
return true;
}
else if(id == "two"){
obj.innerHTML = "";
obj.innerHTML = "<h1>Two is changed!</h1>";
return true;
}
else if(id == "three"){
obj.innerHTML = "";
obj.innerHTML = "<h1>Three is changed!</h1>";
return true;
}
else{
; // do nothing
}
}

When we use if else statements to check the id of the div elements that we are working on, and change the HTML contents accordingly, we will save quite a few lines of code. Take note that we have renamed the function to combine().

Because we have made some changes to the JavaScript code, we'll need to make the corresponding changes to our HTML. So combine-event-handlers.html will be rewritten as follows:

<html>
<head>
<title>Event handlers</title>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="combine-event-
handlers.js"></script>
</head>
<body>
<div id="one" onclick="combine(this);"><p>Testing One</p></div>
<div id="two" onclick="combine(this);"><p>Testing Two</p></div>
<div id="three" onclick="combine(this);"><p>Testing
Three</p></div>
</body>
</html>

Notice that the div elements are now handled by the same function, combine(). These rewritten examples can be found in combine-event-handlers-combined.html and combine-event-handlers-combined.js.

Naming clashes

Removing name clashes is the next issue that we need to deal with. Similar to the issue of combining event handlers, naming clashes occur when two or more variables, functions, events, or other objects have the same name. Although these variables or objects can be contained in different files, these name clashes do not allow our JavaScript program to run properly. Consider the following code snippets:

In nameclash.html, we have the following code:

<html>
<head>
<title>testing</title>
<script type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="nameclash1.js"></script>
</head>
<body>
<div id="test" onclick="change(this);"><p>Testing</p></div>
</body>
</html>

In nameclash1.js, we have the following code:

function change(element) {
var id = element.id;
var obj = document.getElementById(id);
obj.innerHTML = "";
obj.innerHTML = "<h1>This is changed!</h1>";
return true;
}

If you run this code by opening the file in your browser and clicking on the text Testing, the HTML contents will be changed as expected. However, if we add &ltscript type="text/javascript" src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="nameclash2.js"></script> after the &lttitle></title> tag, and if the content of nameclash2.js is as follows:


function change(element) {
alert("so what?!");
}

Then we will not be able to execute the code properly. We will see the alert box instead of the HTML contents being changed. If we switch the arrangement of the external JavaScript, then the HTML contents of the div elements will be changed and we will not be able to see the alert box.

With such naming clashes, our program becomes unpredictable; the solution to this is to use unique names in your functions, classes, or events. If you have a relatively large program, it would be advisable to use namespaces, which is a common strategy in several JavaScript libraries such as YUI and jQuery.

JavaScript Testing Beginner's Guide Test and debug JavaScript the easy way.
Published: August 2010
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

(For more resources on JavaScript, see here.)

Using JavaScript libraries

There are many JavaScript libraries available right now. Some of the most commonly-used ones are as follows:

JQuery (http://jquery.com) YUI (Yahoo! User Interface JavaScript library) (http://developer.yahoo.com/yui/) Dojo (http://dojotoolkit.org/) Prototype (http://www.prototypejs.org/) Mootools (http://mootools.net/) Script.aculo.us (http://script.aculo.us/)

There are many more JavaScript libraries out there. For a complete list, feel free to visit http://en.wikipedia.org/wiki/List_of_JavaScript_libraries.

If you have considered using JavaScript libraries, you may be aware of the benefits of using a JavaScript library. Issues such as event handling, and the much dreaded cross-browser issues make it necessary to consider using a JavaScript library. But you might want to know what you should look out for when selecting a JavaScript library as a beginner JavaScript programmer. So here is a list of things to consider:

  • The level of available support, in terms of documentation.
  • Whether tutorials are available, and whether they are free or paid for. This helps you to speed up the programing process.
  • The availability of plugins and add-ons.
  • Does the library have a built-in testing suite? This is very important, especially for our purposes here.

Do you need to test a library that someone else has written?

Firstly, while we are learning about JavaScript testing, I would say that for a beginner learning JavaScript programing, it might not be advisable to test JavaScript libraries that someone else wrote. This is because we need to understand the code in order to perform accurate tests. People who are able to conduct objective (and accurate) tests are JavaScript experts, and although you are on your way to becoming one, you are probably not there yet.

Secondly, from a practical standpoint, many such tests have already been done for us. All you need to do is search for them on the Internet.

But for learning purposes, let us have a brief look at what tests are usually run against library code.

What sort of tests to run against library code

In general, as a user of various JavaScript libraries, we would most commonly perform performance testing and profiling testing.

Performance testing

Performance testing, as the name suggests, is about testing the performance of your code. This includes testing how fast your code runs (on various browsers) in a manual way, or by using certain tools such as Firebug or others.

In general, in order to generate accurate results for performance testing, it is important for you to test your code (most preferably by using tools and test suites) against all popular platforms. For example, a common way to performance test JavaScript code id to install Firebug in Firefox and test your code using that. But to think of it from a practical standpoint, Firefox users only make up approximately a quarter (or a third at the most) of the total number of Internet users. You will have to test your code against other platforms such as Internet Explorer in order to make sure that your code is up to the mark.

Profiling testing

Profiling testing is similar to performance testing, except that it focuses on bottlenecks in your code rather than the overall performance. Bottlenecks are, in general, the main culprits for inefficient code. Fixing bottlenecks is (almost) a sure way to enhance the performance of your code.

GUI and widget add-ons to libraries and considerations on how to test them

If you have checked the list of various JavaScript libraries that I pointed you to, you may have noticed that some of the JavaScript libraries provide user interface or widget add-ons as well. These are meant to enhance your application's user interface, and most importantly will help you to save time and effort by implementing commonly-used user interface components, such as dialog boxes, color selectors, and so on.

But that's where the problem starts—how do we test such user interface and widget add-ons? There are many ways in which we can go about doing that, but the simplest way (and perhaps the most cumbersome) would be to test visually and manually. For example, if we are expecting a dialog box to appear at the top left-hand side of the screen with a certain color, width, and height, and it does not appear the way we want, then something is wrong.

Similarly, if we see something that we expect to see, then we can say that it is correct—at least in a visual sense.

However, more vigorous testing is required. Testing user interfaces can be a daunting task, and hence I would suggest that you use testing tools such as Sahi, which allows us to write automated web application UI tests in any programing language. Tools such as Sahi are out of scope for this article. If u want to check out Sahi feel free to visit their website http://sahi.co.in.

JavaScript Testing Beginner's Guide Test and debug JavaScript the easy way.
Published: August 2010
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

(For more resources on JavaScript, see here.)

Deliberately throwing your own JavaScript errors

In this section, we will learn how to throw our own JavaScript errors and exceptions. We will briefly cover the syntax of the error functions and commands. It may be a little incomprehensible at this stage to just give you the syntax, but this is necessary. Once you understand how to make use of these commands and reserved words, you will see how you can make use of them to give yourself more specific information (and hence more control) over the types of errors that you can catch and create in the next section. So let us get started with the first reserved word—throw.

The throw statements

throw is a statement that allows you to create an exception or error. It is a bit like the break statement, but throw allows you to break out of any scope. In general, this is what we usually use to literally throw an error. The syntax is as follows:

throw(exception);

We can use throw(exception) in the following ways:

throw "This is an error";

or:

throw new Error("this is an error");

Error is a built-in object that is commonly used in conjunction with the throw statement; we will cover Error later. The important thing to understand now is the syntax, and the fact that throw is also often used with try, catch, and finally, which will help you to control the program flow and create accurate error messages. Now let us move on to catch.

The try, catch, and finally statement

The try, catch, and finally statement are JavaScript's exception handling mechanism, which, as mentioned previously, helps you control the program flow, while catching your errors. The syntax of the try, catch, and finally statements is as follows:

try {
// exceptions are handled here
}
catch (e) {
// code within the catch block is executed if any

exceptions are caught in the try block
}
finally {
// code here is executed no matter what happens in the try block
}

Notice that try is followed by catch, and then finally can be used optionally. In general, the catch statement catches the exceptions that occur in the try statement. An exception is an error. The finally statement is executed as long as the try or catch statement terminates.

Now that we have covered the basic commands and reserved words for deliberately throwing JavaScript errors, let us take a look at an example of how try, catch, and finally can be used together. Check out the following code:

<html>
<head>
<script>
function factorial(x) {
if(x == 0) {
return 1;
}
else {
return x * factorial(x-1);
}
}
try {
var a = prompt("Enter a positive integer", "");
var f = factorial(a);
alert(a + "! = " + f);
}
catch (error) {
// alert user of the error
alert(error);
alert(error.message);
}
finally {
alert("ok, all is done!");
}
</script>
</head>
<body>
</body>
</html>

You can copy and paste the code above into your favorite text editor, save it, and run it in your browser. Or you can run the sample file try-catch-finally-correct-version.html.

You will see a prompt window asking you to enter a positive integer. Go ahead and enter a positive integer, say 3 for instance, and you will receive an alert window telling you 3! = 6. After that, you should receive another alert window, which contains the message ok, all is done!, as the finally block will be executed after try or catch terminates.

Now, enter a negative number, say -1. If you are using Firefox, you will receive an alert window that says that you have too much recursion. If you are using Internet Explorer, you will receive an [object Error] message.

After the first pop-up window, you will receive a second pop-up window. If you are using Firefox, you will see an InternalError: Too much recursion message. If you are using Internet Explorer, you will receive an Out of stack space message.

Lastly, you should receive a final alert window, which contains the message ok, all is done!, as the finally block will be executed after try or catch terminates. While it is true that we have an error, the error message is not exactly what we need, as it does not tell us that we have entered an illegal value.

This is where throw comes in. throw can be used to control the program flow and give us the correct response for each type of error. Check out the following code, which can also be found in the source code folder, in the file try-catch-finally-throw-correct-version.html.

<html>
<head>
<script>
function factorial(x) {
if(x == 0) {
return 1;
}
else {
return x * factorial(x-1);
}
}
try {
var a = prompt("Please enter a positive integer", "");
if(a < 0){
throw "negative-error";
}
else if(isNaN(a)){
throw "not-a-number";
}
var f = factorial(a);
alert(a + "! = " + f);
}
catch (error) {
if(error == "negative-error") {
alert("value cannot be negative");
}
else if(error == "not-a-number") {
alert("value must be a number");
}
else
throw error;
}
finally {
alert("ok, all is done!");
}
</script>
</head>
<body>
</body>
</html>

Now go ahead and execute the program, and enter correct values, negative values, and non-alphanumeric values. You should receive the correct error messages depending on your input.

Notice the previous lines of code where we used the throw statement to control the types of error messages, which will be shown to the user in the catch block. This is one way in which throw statements can be used. Note that the string that is defined after throw is used to create program logic to decide what error messages should be called.

In case you are wondering what other capabilities this exception handling mechanism has, remove the factorial function from try-catch-finally-correct-version.html. Alternatively, you can open the file try-catch-finally-wrong-version.html and run the program. Then try entering any value. You should receive an alert message telling you that the factorial function is not defined, and after that you will receive another alert box saying ok, all is done!. Notice that, in this case, there is no need for us to write any form of message; catch is powerful enough to tell us what went wrong.

One thing to note, though, is that the JavaScript runtime may catch an exception if you do not write an exception handler.

Now that we have covered the basics of the exception handling mechanism, let us move on to the specifics—built-in objects for handling errors.

Summary

In the above article, we have covered:

  • Issues with combining scripts
  • Using JavaScript libraries
  • Deliberately throwing your own JavaScript errors

Further resources on this subject:


About the Author :


Yuxian Eugene Liang

Eugene enjoys solving difficult problems creatively in the form of building web applications using Python/Django and JavaScript/JQuery. He also enjoys doing research related to the areas of recommendation algorithms, link analysis, data visualization, data mining, information retrieval, business intelligence, and intelligent user interfaces. He has recently started a personal blog at http://www.liangeugene.com

Books From Packt


JSF 2.0 Cookbook
JSF 2.0 Cookbook

jQuery 1.4 Reference Guide
jQuery 1.4 Reference Guide

YUI 2.8: Learning the Library
YUI 2.8: Learning the Library

Object-Oriented JavaScript
Object-Oriented JavaScript

Joomla! 1.5 JavaScript jQuery
Joomla! 1.5 JavaScript jQuery

Learning Ext JS 3.0
Learning Ext JS 3.0

JSF 1.2 Components
JSF 1.2 Components

Alfresco 3 Web Content Management
Alfresco 3 Web Content Management


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software