Got to hang out at Google for dayofjs

I got to go to the dayofjs conference (thanks MJG!) Not only was the conference really interesting, but I also got to hang out at Google which was cool. So, I snapped a few pics, as one does.

This is where I found out that I parked about as far as I could have from where I wanted to be.

Google lunch.

Can’t really complain about the day

Ahh, the free beverage fridge

This doesn’t have anything to do with Google or Dayofjs, but I got In-and-Out on my way home after being stuck in traffic for 2 hours, because it has been a long time since I have had it.


The mobile talks of the day were about:

Sencha Touch: http://www.sencha.com/products/touch/

Appcelerator’s Titanium: http://www.appcelerator.com/

jQuery Mobile: http://jquerymobile.com/

There was also a fair amount of talk about PhoneGap: http://www.phonegap.com/

Yehuda Katz also gave a talk about Sproutcore that was really good.  It was not really a mobile talk, but it was still very informative and interesting.

Unit testing jQuery w/ QUnit

So, like most developers I love having unit test, but I hate writing them. Really figuring out the best way to write them and have them work well, is a pain in the ass, and that is what I hate. I have spent some time recently playing with QUnit and despite the number fact that I have found a number of posts online about it, none of them have provided (in my mind) a good way to test a site. The ideas used work well for testing a library, or specific functions, but I don’t write libraries or one off functions, I develop websites. So, I have come up with a method that I like that allows me to test my sites in a way that I like.

The Problems:

The unit testing information I have found mainly deals with testing libraries – this is no good for me.
Testing involves putting QUnit on your page, along with its specific markup – although you can have a “debug” mode for this, it just seems like a bad idea, for a number of reasons, including it not really being an accurate representation of your page, and it does not work across page requests.
Using headless testing – it is cool, but not cross browser or even really O/S ready.
Using something like Selenium – also cool, but involves building tests using a new tool that uses java.

My solution:

I have come up with my own solution, which, I admit is not perfect, but it does a darn good job of testing what I need tested. Basically it involves having a very simply html page next to your site, that loads your site in an iframe and runs the tests on it. It is cross-browser and cross-O/S safe, it works for pretty much any site, and uses the same javascript/jQuery I already write every day.

There are a couple of problems still with my solution, but they are pretty easy to overcome, and writing tests becomes very simple. The basic page we need to get started with the testing is this:



 



 

QUnit Tests

    test markup, will be hidden
     

    Note: We can (and probably should) actually move our tests into different .js files making it much easier to deal with as our number of tests grow.

    We are doing a couple of interesting things here, first we are testing multiple pages at one time. Every time a new page loads up, we grab the jQuery refrence from inside of it, then run the tests that are specified for that page.

    Another cool thing is how we get the jQuery reference for each page.

    We start by loading jQuery using noConflict(true)

    This is because we need to grab the jQuery instance from inside the actual website. When jQuery attaches events to DOM elements, it actually saves those events inside of itself, so although we can trigger events inside of the page itself using our external jQuery, triggering events inside of the iframe will not actually fire any events that were created inside the page. So, instead we grab the jQuery that is actually on the page and trigger the events using it. This has the added bonus that because it is the reference from inside the page we are loading, we can reference DOM nodes as though we were working that that page directly.

    Here we grab the jQuery reference from inside the iframe with:

    
    $ = window.frames[0].jQuery;
    

    Note: For ANY of this to work we must adhere to SOP, this is why we load this up on a server, side by side with our site. This is why I am loading up the iframe using location.protocol + ‘//’ + location.hostname rather than typing out the URL. This will allow it to work as we move between servers and such.

    One of the cool things we are doing here is tying the starting of the tests to a button, so we can get the page to any state necessary before starting the tests – such as logging in, waiting for ajax requests to finish, or navigating to somewhere specific (not that we couldn’t do these in the tests, it just gives us options.)
    Also, before we run our tests we are running the 2 following commands:

    
    $.ajax({async: false});
    $.fx.off = true;
    

    This will make our ajax requests and animations synchronous. Although you would never do this (especially the ajax one) on a site, for our tests it is necessary to ensure that the page is ready before we perform each test.

    Now that we have done this we can run our test just like we were on the page directly.

    We can select elements and trigger events on them, like so:

    
    $(elem).click(); or $(elem).trigger(‘click’);
    $(elem).mousedown(); or $(elem).trigger(‘mousedown);
    Test things, such as visibility:
    $(elem).is(‘:visible’);
    

    Basically anything you would normally do. Simple and easy.

    This is not a perfect way to test your events, it is however pretty good, and will let us know when we break things.

    Here are some examples of tests in action. I hope this helps you get started with unit testing.

    Tests in action!