Posts Tagged ‘javascript’

JavaScript Unit Testing

Monday, May 16th, 2011

As recently blogged on GORGES, unit testing is important to the success of projects. Unit testing reduces bugs, improves a project’s robustness to requirement changes, and sustains a high rate of programming productivity. It is well-accepted that most if not all, non-trivial web applications should include unit tests as part of the project specification.

Web developers typically write unit tests on server side code and rarely on client side code, which is where JavaScript resides. This approach is reasonable given that the majority of the application logic of web applications run on the server side. However, as the web become increasingly more dynamic, so does the number of lines of JavaScript code needed to support a rich user experience. The need for unit testing in JavaScript should be apparent, yet JavaScript unit testing have been largely ignore.

One reason why developers don’t write JavaScript unit tests is that JavaScript testing is front end testing. Front end tests are hard to write and we are better off leaving it to manual testers. Keep in mind, however, that application logic tend grow exponentially in complexity. So unless the project has the resources to hire manual testers at an exponential rate, it is far more cost effective to devote the time to write tests.

Another reason for not writing JavaScript unit tests is the belief that client side programming logic should be minimized and pushed into the server side wherever possible. The rationale is that JavaScript unit testing is not needed if the code base is small. In other words, not writing JavaScript means not having to write unit tests. However, as mentioned, JavaScript is needed to support a rich web experience. Not writing JavaScript is not an option if a modern web experience is desired.

There are many free and open source testing frameworks available for JavaScript. Three such frameworks are: Selenium, JS Test Driver, and QUnit.

SELENIUM, http://seleniumhq.com

Selenium is not a JavaScript testing framework. Rather, it is an end-to-end testing framework for web applications. So Selenium implicitly tests the JavaScript portions of a web application. Selenium works as follows:

  1. Write your Selenium scripts. The scripts can be written in many languages including PHP, Ruby, C#, and Java. If you don’t know how to program, you can use Selenium IDE which is a Firefox plugin that records your mouse clicks and typing web browsing behavior to create test scripts
  2. Your unit test runner (e.g., JUnit) sends the scripts to the Selenium server
  3. The Selenium server launches browsers and runs the tests. The Selenium server can be configured to launch different browsers on different computer platforms (e.g., PC, Mac, Linux).

Note that Selenium runs your tests using real browsers so you get comprehensive tests of your web application against various browsers. The downside is that the comprehensiveness also leads to complexity of setting up the Selenium server and stand-by machines waiting for Selenium tests. Selenium is best suitable for large web projects with the resources needed to configure various servers.

JS TEST DRIVER, http://code.google.com/p/js-test-driver/

JS Test Driver can be thought of as Selenium-lite but specifically designed for unit testing your JavaScript code (as opposed to end-to-end integration testing as is the case with Selenium). The test runner for JS Test Driver runs your unit tests in the same manner as Selenium. JS Test Driver launches your browsers and executes your tests inside the browser. JS Test Driver can also be integrated into the Eclipse or IntelliJ IDE as a plugin which provides a one click interface to running your JavaScript tests.

QUnit, http://docs.jquery.com/Qunit

QUnit is the simplest of the three framework. You write your tests in JavaScript and embed it in an HTML page with qunit.js and qunit.css include. To run your tests, you simply refresh the page in your browser. There is almost no learning curve for developers familiar with any of the xUnit framework. Because of its simplicity, there is no out-of-the-box support for running your tests on multiples browsers simultaneously, unlike Selenium and JS Test Driver.

Which framework?

These three frameworks all serve different testing needs and are by no means mutually exclusive. If you are only interested in end-to-end integration test, then Selenium is a good choice if you have the resources to set up your testing environment. If you see the value of unit testing JavaScript in your web application, then QUnit is the easiest way to start but look into JS Test Driver as your testing need evolves.

Why You Should Use CoffeeScript

Monday, May 16th, 2011

JavaScript (JS) is the programming language that allows web developers to make web pages interactive. Each browser has a slightly different implementation, which developers iron out by using cross-browser frameworks such as JQuery. It doesn’t matter if the server side component is written in PHP or Ruby – the front end is always JavaScript. Thanks to Google’s V8 JavaScript engine and Node.js, JS is also becoming the goto language for realtime interactive web applications such as chat, live blogs. JS is the language behind most everything the end user perceives as cool in the UI.

JS has been around since the late 1990s. Like a house with several owners with different tastes, it’s been added on to over the years. It’s really easy to write ugly JS, chock full of bugs, that no other developer will ever want to or be able to read. You can accidentally open memory leaks that crash the browser. You can accidentally put a variable in the global namespace and cause the rest of the program to come to a crashing halt, or behave mysteriously.

At the same time, the core of JS is a beautiful language that, if you stick to the “good parts,” can support the richest of rich client apps with grace and aplomb. That is where CoffeeScript comes in.

CoffeeScript (CS) is a language that compiles into JavaScript. It makes it easier and less tedious to do good things with JS, and harder to do bad things. Because CS only turns into JS when the i’s are dotted and the t’s are crossed, it is harder to write buggy JS.

Line Noise Reduction

Programming languages based on C or Java, such as JS and PHP, are filled with parentheses and semicolons to tell the computer where each block of code starts and ends. Keywords such as “var” and “function” tell the computer which are variables and which are functions. The programmer’s eye gets used to them, and may even come to rely on them to interpret code on the screen.

Oftentimes before I write a paper I begin with an outline. Top level items are on the left, and each layer of sub-item gets one level of indentation. My word processor responds when I press the TAB key, and has an indent button. There is no facility to write an outline like the following, nor is there a word processing facility for doing so outside of a code editor:

I. The Industrial Revolution {
    A. Origins {
        i. deforestation in 17th century England
        ii. proximity of coal and iron deposits
        iii. accumulation of capital from overseas trade
    }
}

Therefore if you want to make code more human readable, replace the braces with indentation, and let the compiler put them back in for you to make the computer happy. CS does this, calling it “syntactic white-space”:

class App
  ...
  initUI: ->
    if $('#controls').size() is 0
      $('#title').append render('searchControls')
      JKT.earth.addControls() if (JKT.earth)
    ...

becomes:

App = (function() {
  function App() {
    ...
  }
  App.prototype.initUI = function() {
    if ($('#controls').size() === 0) {
      $('#title').append(render('searchControls'));
      if (JKT.earth) {
        JKT.earth.addControls();
      }
    }
  }
  return App;
});

I personally find the CS more meaningful, and the compiled code to be cleaner than the code I would have written to do the same thing (although it’s not fashionable to admit that your code isn’t always the cleanest and most awesome code anyone has ever written).

Notice that the -> stands for “function”, and function name colon: means “add this function to the object prototype.” Please read the CS documentation a few times before you try CS – this is just the beginning of the stuff you can do.

The bottom line is that “line noise reduction” removes as much computer-oriented meaning as possible from the code, while leaving the human-oriented meaning. The principle is that while programmers write code for computers to run, unless it’s one-time only throwaway code, they’re also writing code for other programmers (including themselves when they come back to it three months later to add a new feature). The less time it takes a programmer to figure out what is going on, the higher the business value.

Meaningful Code is Cleaner Code

The code snippet above isn’t necessarily fair, because it doesn’t show JS “before I started writing CS.” I see that it has benefited from the other thing I most like about CS: to make it easier to debug, you have to break it down into smaller parts. Smaller parts that do one thing only are cleaner parts.

That’s right. In the old regime, I might have a JS file with several hundred lines. When a error pops up, Firebug will tell me what line it’s on, and I can jump to it in the code editor and fix it. Maybe right there I will add some more code, and pretty soon I’ll have a large JS file that is hard to edit without Firebug, with lots of interconnected parts and mixed behaviors.

Since CS makes working with the JS object model so easy, I find myself using it. I would take that 500 line JS file and break it into a half dozen or more constituent parts. I have development mode set to deliver these to the browser individually, so if an error crops up, it’s easier for me to find it in the CS. Production mode combines and minifies the JS into one file for speed of delivery to the user.

If you’re coming from Ruby or Python, you’ll recognize the philosophy of human oriented code. You’ll also recognize that CS is 2/3 Python and 1/3 Ruby. Therefore CS will be easier for you if you know one of those; likewise if you hate Ruby, stay away from CS. (And if you don’t know JS yet, don’t try CS…)

Gotchas

I must admit that CS came with some pounding of my head on the table, especially when I started. Here’s where I got stuck, and what I did to get unstuck:

  1. I started by opening a JS file and “saving as” a coffee file. DON’T DO THAT! Create a new coffee file, copy the JS from the JS file, and paste it into the coffee file. The paste action will get the indentation right.
  2. Your code may look indented to you, but it may not be so for coffee. You may have SPACES mixed in with your TABS.

When you make changes to coffee but nothing seems to happen in the browser:

  1. First check that you are running the compiler. I have a shell script that starts coffee’s compile-on-edit mode. Sometimes I forget to run it. By the third alert statement, I check for that.
  2. Second, check the compiler output. You may have a syntax error in CS. It won’t compile at all if there’s a problem with the CS. If you see “cannot use a pure statement in an expression”, it usually means there’s a rogue space in your tab indentation. Redo the indentation and try again.
  3. Third, if the CS compiled but weird things are happening such as it says a function doesn’t exist when you know it does, check the compiled JS. Sometimes there is an indentation issue that doesn’t break the compiler, but causes it to misinterpret where classes end and begin.

In a perfect world

CS is new. Therefore it is not integrated into most IDEs yet. Since Rails 3.1 uses CoffeeScript, it shouldn’t be long before you see CS support in Aptana. There is an IntelliJ plugin for RubyMine and PHPStorm. I use the TextMate bundle. My colleague Jim uses Eclipse and edits it with plain text, as he finds it still easier to read than JS.

Getting started

I recommend going to the CS website (http://jashkenas.github.com/coffee-script/). Read it a few times before you do anything. Bookmark it. Then install node, npm, and coffee.

When I started on CS, I had a few thousand lines of JS already written. Most of it was for a prototype, and I dreaded having to whip it into production grade and add the rest of the features to it. I started learning CS by porting some of the easier JS files. When I was comfortable, I took on the hairy part. It emerged as a piece of code I’m proud of and like to work with.

In a nutshell, CoffeeScript makes it fun for me to write clean JavaScript, and delivers business value by helping me to write maintainable JavaScript faster that it otherwise would. If you’re not using it yet, it’s time to start.

References/Additional Resources

  1. The CoffeeScript web page: http://jashkenas.github.com/coffee-script/
  2. My presentation to the Ithaca Web Group: http://www.slideshare.net/davidfurber/real-lifecoffeescript
  3. Tongue in cheek presentation of why you’ll hate CS: http://www.slideshare.net/tim.lossen.de/coffeescript-7-reasons-you-are-gonna-hate-it
  4. The PeepCode screencast, “Meet CoffeeScript”
  5. The PragProg book (written by yours truly), “CoffeeScript: Accelerated JavaScript Development”
  6. The CoffeeScript Cookbook wiki (new, but promising)
David has a passion for both web site design and development, both front end visual design and back end programming work. He loves the endless variety of projects and tasks that go into launching a successful Web site.

Dynamic resource management in JavaScript

Wednesday, April 1st, 2009

One of the most important features of modern web sites overall, is their ability to respond quickly and come back with the information requested by the user. We live in an “attention economy” on the Web 2.0, and if your site does not respond pretty much instantly, the user will find a site that does.

One way that modern sites achieve this, is by loading in smaller increments – for example, loading the detailed content for an item on a list can be deferred using AJAX.

Another way to break down the loading of a web application into smaller chunks, is by loading various other resources, specifically JavaScript and CSS files, on demand.

Doing this in a compatible and clean way, can be tricky.

The Challenge

Let’s look at some of the requirements that a good solution to this problem must fulfill.

First of all, some of the JavaScript frameworks we work with, do provide some sort of resource management. But we work with many different frameworks, and sometimes with no framework at all, so our solution needs to be stand-alone as well as compatible with most major JavaScript frameworks.

Secondly, we target all modern browsers – and therefore, our solution must be fully cross browser , targeting Internet Explorer 6 through 8, Firefox, Opera and Chrome, and hopefully any other standards compliant future browsers.

JavaScript is (or can be) object-oriented, meaning that a class in one script could potentially extend a class in another script. Therefore, since we are going to load resource asynchronously, we must ensure that scripts are loaded and executed in order .

Another concern is notification of resource readiness. Since resources are loaded asynchronously, and sometimes have already been loaded once, our script needs to provide a callback-notification when the resource is ready and available.

And finally, we don’t want to write code for every project to keep track of what’s been loaded and what has not. In other words, we need a load-once method, so that classes, widgets and stylesheets can be automatically loaded the first time they are needed.

Limitations

We’re going to accept certain limitations of this script.

For one, we’re not going to attempt to do a lot of error handling – if a resource can’t be loaded, this is a problem that needs to be solved by the developer, and not really something you can provide a “pretty” solution for anyway.

And secondly, some resource management scripts attempt to inject scripts in a way that allows scripts from foreign domains to run without security limitations. This has certain other drawbacks that I won’t get into, but we’re going to assume that you’re loading scripts from your own domain.

Our Solution

Our script comes in the form of a classless singleton object, which provides two methods for loading resources on demand:

Loader.load( url, [callback-function], [context-object], [driver-name] );
Loader.once( url, [callback-function], [context-object], [driver-name] );

The Loader.load() method will allow you to load the same resource repeatedly – for example, you will be able to execute the same JavaScript more than once. Just keep in mind that duplicate class declarations, and duplicate initialization, for example, could cause problems. Most likely, you will only want to use this method if you want to intentionally overwrite existing variables.

The Loader.once() method will ensure that the same resource is only loaded once. Note that the callback will be called when the resource is ready , not only the first time when the resource actually loads.

Arguments for the two functions are identical:

  • url : required – relative (to your page) or absolute URL to a JavaScript or CSS resource.
  • callback-function : optional callback-function – called when the resource (and any resources requested before it) has loaded.
  • context-object : optional object to use as the context (this) for the callback-function. Use null (or leave out) if calling context is unimportant.
  • driver-name : optional driver-name, e.g. “css” or “js” – this determines how the loaded resource is handled. If unspecified, the loader will try to determine the driver by file-extension, but will default to “js” if the file extension at the end of the URL does not match “.css” or “.js”.

Conclusion

When you need to load a collection of resources, remember that they will be loaded in the order you request them. For example, loading components for a widget-based framework such as ExtJS is possible – you can load a component class declaration, and then load another class that extends it, but you must request them in order.

Another thing to keep in mind, when you need to know when a collection of resources are ready, you don’t need to attach a callback to every request – just attach your callback-function to the last request, as this won’t execute until all previously requested resources are ready.

Source Code

Finally, here is the source code for you to cut and paste:

/*

Version:   1.1
Developer: Rasmus Schultz
License:   GPL v3 <http://www.gnu.org/licenses/gpl-3.0-standalone.html>

Copyright 2009, Gorges Web Sites <http://www.GORGES.us>

Removing this notice from the source code would be bad karma.

*/

var Loader = {
q: [], // the Queue for pending items to be loaded
reg: {}, // a registry to ensure items are loaded only once
load: function(url, cb, context, driver, once) {
var dd = url.split('.').pop();
if (!Loader.drivers[dd]) dd = driver || 'js';
var p = new Loader.Proxy(
{ url: url, cb: cb || function(){}, reg: once, driver: dd, context: context }
);
Loader.q.push(p);
Loader.next();
return p;
},
once: function(url, cb, context, driver) {
this.load(url, cb, context, driver, 1);
},
next: function() {
for (i=0; i<Loader.q.length; i++) {
var l = Loader.q[i];
if (l.state == 1) return; // already loading
if (l.state == 0) return l.load(); // not loading (and not yet loaded)
}
}
}

Loader.Proxy = function(opt) {
this.driver = opt.driver;
this.context = opt.context || this;
this.url = opt.url;
this.reg = opt.reg;
this.state = 0; // inactive
this.cb = opt.cb;
this.load = function() {
if (this.reg &amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp; Loader.reg[this.url]) return this.loaded(); // already loaded once
this.state = 1; // loading
var hd = document.getElementsByTagName("head")[0];
var el = Loader.drivers[this.driver](this, this.url + (this.url.indexOf('?') == -1 ? '?' : '&amp;amp;amp;amp;amp;') + new Date().getTime());
hd.appendChild(el);
}
this.loaded = function() {
this.state = 2; // loaded
if (this.reg) Loader.reg[this.url] = 1;
this.cb.call(this.context);
Loader.next();
}
}

Loader.drivers = {

js: function(proxy, url) {
var el = document.createElement('script');
el.type = 'text/javascript';
el.src = url;
var me = proxy;
if (el.attachEvent) { // IE
el.attachEvent('onreadystatechange', function() {
if (el.readyState == 'loaded' || el.readyState == 'complete') me.loaded();
});
} else { // DOM
el.onload = function() { me.loaded(); }
}
return el;
},

css: function(proxy, url) {
var el = document.createElement('link');
el.rel = 'stylesheet';
el.type = 'text/css';
el.href = url;
el.media = 'all';
new (function(link, proxy){
this.index = document.styleSheets.length;
this.link = link;
this.proxy = proxy;
var me = this;
this.check = function() {
try {
var s = document.styleSheets[me.index];
if ((s.rules || s.cssRules).length) { // DOM || FF
window.clearInterval(me.int);
me.proxy.loaded();
}
} catch (e) {};
}
this.int = window.setInterval(this.check, 100);
})(el, proxy);
return el;
}

}
Rasmus Schultz has worked for web development companies, advertising agencies and a music software company during his extensive development career. His main strengths are software development and database design. Rasmus has more than a decade of experience with many development platforms, languages and standards.
©2012 GORGES - All rights reserved
where programming meets design and lives happily ever after