Activate your free membership today | Log-in

Friday, April 25th, 2008

Cuzillion: Performance best practices tool

Category: JavaScript, Showcase, Examples, Browsers, Testing, Performance

Steve Souders has released a nice little tool called Cuzillion which has the tag line of ‘cuz there are zillion pages to check, although it could also be that there are a zillion ways to do Web development!

The tool lets you test out different techniques for optimizing performance in browsers, and these tests can be saved and shared by the community.

Steve explains how the tool came about:

I’m constantly thinking of or being asked about how browsers handle different sets of resources loaded in various ways. Before I would open an editor and build some test pages. Firing up a packet sniffer I would load these pages in different browsers to diagnose what was going on. I was starting my research on advanced techniques for loading scripts without blocking and realized the number of test pages needed to cover all the permutations was in the hundreds. That was the birth of Cuzillion.

Here Steve talks about some examples:

A great example of how Cuzillion is useful is looking at the impact inline scripts have when they follow a stylesheet in Internet Explorer. Typically, a stylesheet followed by any other resource results in both resources being downloaded in parallel in Internet Explorer. (In Firefox stylesheets block parallel downloads, so this performance optimization is only applicable to IE.) Here’s a Cuzillion page that shows this: stylesheet and image downloading in parallel. Both the stylesheet and image are configured to take 2 seconds to download. Since they download in parallel the page takes about 2 seconds to load as shown by the “page load time”.

But look what happens if we put an innocent inline script between the stylesheet and image: stylesheet, inline script, and image. Now, in Internet Explorer the stylesheet and image are downloaded sequentially, which means the page load time goes from 2 seconds to 4 seconds. If the inline script is simply moved above the stylesheet the two resources are downloaded in parallel again, and the page load goes back down to 2 seconds: inline script, stylesheet, and image.

This was a great discovery. But immediately my officemate asked if inline style blocks had the same effect. No problem. With Cuzillion I just do some clicks and drag-and-drop, and can test it out: stylesheet, inline style block, image. It turns out inline style blocks don’t cause stylesheets to block downloads.

The findings from a tool like Cuzillion are really valuable. The lessons learned from poking at inline scripts and stylesheets can save hundreds of milliseconds on page load times. And it’s a common problem. eBay, MSN.com, MySpace, and Wikipedia all suffer from this problem.

Much thanks to Google for letting me release this code under Open Source. It’s not currently on Google Code but if you want to contribute let me know and I’ll do that. Try it out and send me your feedback. And share your insights with others. We all want the Internet to be faster!

Steve is talking at Web 2.0 Expo today at 1:30pm in room 2002. If you are in town, check it out and see Cuzillion in action!

Posted by Dion Almaer at 1:37 pm
3 Comments

+++--
3.6 rating from 15 votes

JavaScriptMVC Test Plugin

Category: JavaScript, Testing


Justin Meyer and the JavaScriptMVC team have created a new Test plugin. We all voted testing as the number two pain point in Web dev and this is an attempt to make the world a bit better.

Test lets you simulate every major DOM event, as well as some combination events like Write and Drag, simulate Ajax, and use assertions. It runs functional and unit tests in a separate console window. Another nice feature is that if you use it with the Controller plugin, helper methods are automatically created that simulate each controller action's event, such as TodoClick.

Here's an example test function:

JAVASCRIPT:
  1.  
  2. test_drag: function(){
  3.     // click the second todo
  4.     this.TodoClick(2);
  5.     // call done_dragging after Drag is complete
  6.     this.Drag($('draggable'),{from: 'pointA', to: 'pointB', callback: this.next_callback()})
  7. },
  8. done_dragging : function(){
  9.     // did the drag complete successfully
  10.     this.assert_equal(1, $('pointB').next().childNodes.length);
  11. }
  12.  

Check out the demo

Posted by Dion Almaer at 6:18 am
3 Comments

++++-
4.5 rating from 8 votes

Wednesday, April 16th, 2008

DOH, let me test my code!

Category: Dojo, Testing

Dustin Machi has posted on DOH, the Dojo Objective Harness which is a testing framework for JavaScript.

It can be used with your own Dojo applications, and even without any Dojo at all.

To do this you need to follow a couple of patterns, and Dustin documents them so you can get going.

You end up putting the correct refresh code in your HTML:

HTML:
  1.  
  2. <meta http-equiv="REFRESH" content="0;
  3.     url=../../../util/doh/runner.html?testModule=company.tests.foo
  4.           &registerModulePath=company,../../company">
  5.  

You register tests like this:

JAVASCRIPT:
  1.  
  2. doh.register("project.tests.TestGroupA",
  3.        [
  4.                {
  5.                        name: "My Function Test [_myfunc()]",
  6.                        timeout: 4000,
  7.                        runTest: function(){
  8.                               var result = _myFunc("a", "b");
  9.                               doh.assertEqual("Foo", result);
  10.                             }
  11.                  }
  12.    ]
  13. );
  14.  

Posted by Dion Almaer at 9:26 am
2 Comments

+++--
3 rating from 16 votes

Tuesday, March 18th, 2008

jqunit: extending jquerys testrunner to all

Category: JavaScript, Testing, Framework, jQuery

Michael Grosser has created jQuerys testrunner in a way that makes it work with jsUnit, and also useful for libraries other than jQuery.

Here is a full example:

JAVASCRIPT:
  1.  
  2. var temp = function($) {
  3.   jqUnit.module('Without local interface');
  4.   jqUnit.test('test a', function(){
  5.     jqUnit.ok(true);
  6.     this.ok(true);
  7.   });
  8.        
  9. with(jqUnit) {
  10.   module('With local interface');
  11.   test('test b', function(){
  12.     ok(true);
  13. });
  14.  
  15.  
  16.   module('Example tests');
  17.   test('Real Click vs False Click',function(){
  18.     var clicked = false;
  19.     $('#test-form').click(function(){clicked=true;});
  20.    
  21.     //false click
  22.     $('#test-form input').click();
  23.     ok(!clicked);
  24.    
  25.     //real click
  26.     triggerEvent($('#test-form input').get(0),'click');
  27.     ok(clicked);
  28.   });
  29.  
  30.   test('Waiting',function(){
  31.     $('#ajax').load('fixtures/1.html');
  32.     expect(1);//expect 1 assertion, here: fails if ajaxStop is never called
  33.     stop();//pause: so we can wait with setTimeout,setInterval,...
  34.    
  35.     $().ajaxStop(function(){setTimeout(function(){
  36.       //field is not filled directly after ajaxStop
  37.       //since DOM traversal comes after stopping to load
  38.       equals($('#ajax').html(),1);//!reverted jsUnit order
  39.       start();//resume: make sure its called or tests will halt!
  40.     })});
  41.   });
  42. }}(jQuery);
  43.  

that produces:

Posted by Dion Almaer at 11:01 am
3 Comments

+++--
3 rating from 24 votes

Saturday, March 15th, 2008

Progressive Enhancement with CSS support

Category: CSS, Testing

Via John Resig we just got to learn about a clever technique applied by the Filament group in Boston called Progressive Enhancement with CSS support.

The study rightfully claims that object detection to determine whether a user agent is capable of supporting a certain interface is not enough. You also need to make sure that the browser supports the right look and feel - in other words that the CSS you will apply can be rendered as intended.

I've done similar things in the past, reading out the offsetWidth of an element to determine if the browser is in standards or Quirksmode but Filamentgroup's test script goes a lot further than this. It tests for the following CSS support:

  • Box model: make sure the width and padding of a div add up properly using offsetWidth
  • Positioning: position a div and check its positioning using offsetTop and offsetLeft
  • Float: float 2 divs next to each other and evaluate their offsetTop values for equality
  • Clear: test to make sure a list item will clear beneath a preceding floated list item
  • Overflow: wrap a tall div with a shorter div with overflow set to 'auto', and test its offsetHeight
  • Line-height (including unitless): test for proper handling of line-height using offsetHeight, primarily to rule out Firefox 1.0

For example the right box model support is tested with this script:

JAVASCRIPT:
  1. var newDiv = document.createElement('div');
  2. document.body.appendChild(newDiv);
  3. newDiv.style.visibility = 'hidden';
  4. newDiv.style.width = '20px';
  5. newDiv.style.padding = '10px';
  6. var divWidth = newDiv.offsetWidth;
  7. if(divWidth != 40) {document.body.removeChild(newDiv); return false;}

When the browser passes, the script adds an "enhanced" class to the body that you can use in your style sheet.

Neat idea and very defensive programming.

Posted by Chris Heilmann at 4:16 am
8 Comments

+----
1 rating from 2470 votes

Friday, February 15th, 2008

newjs: JavaScript Project Creation

Category: JavaScript, Utility, Testing

When you start a new JavaScript library, how do you layout the source files, the tests, the distribution files? Do you have support scripts to generate distributions from source files? Run your JavaScript unit tests? Generators to create new unit test HTML files?

This is why Dr. Nic created newjs, a Ruby script that sets you up to do the right thing by your pet project. No longer will you crack open a .js file and slice and dice your JavaScript willy nilly. Instead, you will use newjs to:

  • Setup your directory structure for src, tests, documentation, distribution
  • Start building unit tests using unittest.js
  • Generate test files
  • Run unit tests and get nice HTML output
  • Package up your src for distribution
  • Create a website for your project (wait. is this maven???? ;)

Posted by Dion Almaer at 7:36 am
1 Comment

+++--
3.7 rating from 11 votes

Tuesday, February 5th, 2008

Continous Integration for the Front End

Category: Utility, Testing

Gareth Rushgrove has posted on continous integration for the front end.

He talks about a new site, inursite.com that does one thing:

The premise is simple; enter a few of your sites and inursite will visit them once a day and run a markup validation service over the page. You then get a feed of the pass or failure status. It’s simple but brilliant. For example, I have this very site added to the service. If I put some invalid markup in this post, tomorrow morning I’ll get an item in my feedreader telling me of my mistake. I’ll get that every day until I fix the problem.

This green/red (pass/fail) type approach to simple tests is what I find most powerful about continuous integration systems like Cruise Control.

Gareth also has some ideas for improvement:

  • Has all the CSS been compressed using something like CSSTidy.
  • Has all the javascript been compressed using something like JSMin.
  • Does any Javascript pass the harsh taskmaster that is JSLint.
  • If my markup a little bloated? Maybe I could set a maximum size for the markup and get a fail is I go over that.
  • Ditto CSS file size.
  • Ditt Javascript.
  • Ditto images.
  • If pages have associated feeds, then validate them as well according to the relevant specification (probably RSS or Atom).
  • How many HTTP Requests does it take to load the whole page, including all the relevant assets.
  • How many hosts are required to load the whole page? I’d like to be able to set a maximum number and get a fail if I go over that.
  • Is the page gzipped on the server.
  • And just to keep this topical, does the page have either the IE8 meta element or the associated HTTP header set to a particular value.

This sounds like setting up YSlow to run in a continous manner.

Posted by Dion Almaer at 7:04 am
2 Comments

+++--
3.8 rating from 6 votes

Friday, January 4th, 2008

Autotesting JavaScript in Rails

Category: Articles, Testing

Dr Nic has written a tutorial on testing JavaScript in Rails using a new javascript_test plugin.

Once you ruby script/plugin install javascript_test you can ruby script/generate javascript_test maths. Then you can write a test a la:

JAVASCRIPT:
  1.  
  2. testTruth: function() { with(this) {
  3.   assert(true);
  4. }}
  5.  

You can go further though with the autotest watching over files, and Nic shows some TDD in action.

Posted by Dion Almaer at 7:56 am
1 Comment

+++--
3.6 rating from 8 votes

Monday, December 10th, 2007

OpenSocial Container Checker: IGCheck

Category: Testing, Social Networks

Didier Durand wanted to check the compliance of various OpenSocial containers, so he decided to create a tool, IGCheck, that will do the checking for him:

The purpose of IGCheck is to test and report which functions of the Google Gadget API (i.e., prefixed with _IG_ in their Javascript name) are available in which containers. IGCheck then produces a report comparing the current test with reference data.

To get current status, check this page to see the most current result that we can produce concerning igoogle, orkut, hi5 & ning.

As the number of opensocial partners that are open for tests remain limited as of now, the following conclusions can be drawn as of now :

  • Orkut uses the gmodules infrastructure of Google Gadgets to run the opensocial api (see the line "host" in the result array)
  • Hi5 does the same and as such seems to have "outsourced" the task of running its opensocial container to Google (see the line "host" in the result array)
  • Ning has followed a more independent approach by implementing a fully independent container named "proxy.ning.com" (see the line "host" in the result array)
  • The choice of Ning has currently drawbacks: IGCheck finds only 6 _IG_ functions whereas 55 are present in the others. (see the line "count" in the result array)
  • Ning seems to have created its own function(s) with _IG_Prefix: a function "G_Tabs" is present in the Ning container but nowhere else(see the line "_IG_Tabs" in the result array).

The conclusions above are preliminary results only:

  • the current and future containers will have to converge after the current pioneering phase in order to reach the promise "Write Once, Run Anywhere" although the fact that IGCheck itself is a proof of partial achievement (IGCheck source code is unique for all containers)
  • the opensocial initiative will have to get more precise on Google Gadget API requirements: the debate on this topic is currently hot on the opensocial discussion group as nothing (at least to my knowledge...) has been clearly and officially stated in this area until now . A poll is under way. The target is to get opinions of developers and eventually to define to which extent opensocial containers have to implement the _IG_ API.

See the current results, and help Didier get this running in other containers.

Posted by Dion Almaer at 6:40 am
Comment here

+++--
3.3 rating from 11 votes

Wednesday, November 7th, 2007

TIBCO GI Performance Profiler

Category: Testing, TIBCO

TIBCO has released a new open source Ajax Performance Profiler that aims to answer the questions:

  • How long did it take that service to respond?
  • How long did it take for that component to render?
  • How long did it take that data to parse?
  • How long did it take for that function to execute?

Check out the Craigslist example which uses three Ajax libraries: TIBCO General Interface, dojo for offline capabilities, and Google Maps.

When you setup tests, you do so with a simple DSL:

JSON:
    {name:"Select Posting", fct: function(objServer) {
            gicx.getResultsTable().selectRecord(gicx.getResultsTable().getSortedIds()[0]);
            return gi.test.gipp.SLEEP_LONG;
    }},       

    {name:"Open Posting 1", fct: function(objServer) {
            gicx.openPosting(gicx.getResultsTable().getSortedIds()[0]);
            return gi.test.gipp.SLEEP;
    }},
           
    {name:"Open Posting 2", fct: function(objServer) {
            gicx.openPosting(gicx.getResultsTable().getSortedIds()[1]);
            return gi.test.gipp.SLEEP;
    }},
           
    {name:"Search craigslist 2", fct: function(objServer) {
            gicx.APP.getJSXByName("query").setValue("mattress");
            gicx.search();
            gi.test.gipp.POLL.poll = function(objServer) {
            return gicx.getResultsTable().getSortedIds().length;
            };
            return gi.test.gipp.POLL;
    }},

    {name:"Open Posting 3", fct: function(objServer) {
            gicx.openPosting(gicx.getResultsTable().getSortedIds()[0]);
            return gi.test.gipp.SLEEP_LONG;
    }},

TIBGO GI Perf

Posted by Dion Almaer at 5:03 am
Comment here

+++--
3.7 rating from 22 votes

Friday, October 12th, 2007

Testing JavaScript Objects with Function.prototype.call and Crosscheck

Category: JavaScript, Testing, Tip

Jason Harwig has written a quick tip on Testing JavaScript Objects with Function.prototype.call. The example that he uses is:

JAVASCRIPT:
  1.  
  2. /**
  3. * Call a function with the given execution context and parameters.
  4. * @param <object> instance the object to use as the "this" inside the function
  5. * @param <array of Objects> parameters the objects to pass to the function
  6. */
  7. Function.prototype.call(instance, parameters...);
  8.  
  9. var x = { message: 'Hello World' };
  10. var hello_function = function(name) {
  11.   alert(this.message + ", " + name);
  12. }
  13. hello_function.call(x, 'jason');
  14.  

In the context of Crosscheck, the JavaScript unit testing framework, you would see this work via:

JAVASCRIPT:
  1.  
  2. // function to test
  3. String.prototype.trim = function() {
  4.    return this.replace(/^\s+|\s+$/g,'');
  5. }
  6.  
  7. // crosscheck test
  8. assertTrim: function() {
  9.    assertEquals('text', String.prototype.trim.call('  text');
  10.    assertEquals('text', String.prototype.trim.call('  text  \n ');
  11. }
  12.  

What is Crosscheck?

Crosscheck is an open source testing framework for verifying your in-browser javascript. It helps you ensure that your code will run in many different browsers such as Internet Explorer and Firefox, but without needing installations of those browsers. The only thing you need is a Java Virtual Machine.

Posted by Dion Almaer at 7:55 am
5 Comments