Home > Uncategorized > jQuery and testing – JSUnit, QUnit, JsSpec [Part 1]

jQuery and testing – JSUnit, QUnit, JsSpec [Part 1]

November 15th, 2008 Leave a comment Go to comments

Trying JsUnit with JQuery

I have started first with JSUnit because it is tried and true (and to tell the truth I thought it would be fine and didn’t bother with a quick search for alternatives).

For the impatient, I won’t be going with JSUnit and here are some reasons:

  • the problem is that the integration of a setup (ie onload – pausing) to load the data doesn’t integrate well with jQuery. JSUnit has its own setup and document loader but I am still wondering how to do this transparently (ie I didn’t actually get the test to work – I wasn’t exhaustive but then again I don’t think that I should have needed to be to get this test going)
  • Firefox 3.0 on mac doesn’t integrate well (ie it doesn’t work), but safari does! Unfortunately, I am a little bound to firebug for development.
  • JSUnit doesn’t report tests well either

I went and had a look at how JSUnit does it. (Remember that this framework has been around a lot longer than jQuery.) Here is the extract from the code/test samples. The basic setup is to hook into an existing testManager that existing within a frame and then get the data from there. Furthermore, you need to manage your own flag that the process has been complete. JSUnit then looks through all functions that start with test in this case testDocumentGetElementsByTagName checks expected data. Here I assume that the tests are run in a particular frame (buffer()) that testManager gives us access to.

var uri = 'tests/data/data.html';

function setUpPage() {
    setUpPageStatus = 'running';
    top.testManager.documentLoader.callback = setUpPageComplete;
    top.testManager.documentLoader.load(uri);
}

function setUpPageComplete() {
    if (setUpPageStatus == 'running')
        setUpPageStatus = 'complete';
}

function testDocumentGetElementsByTagName() {
    assertEquals(setUpPageStatus, 'complete');
    var buffer = top.testManager.documentLoader.buffer();
    var elms = buffer.document.getElementsByTagName('P');
    assert('getElementsByTagName("P") returned is null', elms != null);
    assert('getElementsByTagName("P") is empty', elms.length > 0);
}

Below is the rewritten code to exercise my code. Here’s a couple of the features:

  • for setup, pass in the correct xml file via uri variable (obviously)
  • to test, I have written a test testXML2Object.

    p. There is one major design problem with the code itself that didn’t allow me to use my own data loader. You will see the line var feed = new StoryQResults(buffer);. Where did that come from? It is nothing close to the code I said that I wanted to exercise. It is infact from within the code I want to exercise. The major issue I found here is that to load and test data I had to use the testManager rather than use my own ().storyq() call.

The other problem was it wouldn’t return the result that I wanted either. I was expecting my feed variable to be an object of the results. Instead I was getting a reference to function StoryQResults – given now that it wasn’t running in Firefox and I didn’t have Firebug life was getting a little hard.

var uri = '../../xml/results-01.xml';

function setUpPage() {
    setUpPageStatus = 'running';
    top.testManager.documentLoader.callback = setUpPageComplete;
    top.testManager.documentLoader.load(uri);
}

function setUpPageComplete() {
    if (setUpPageStatus == 'running')
        setUpPageStatus = 'complete';
}

function testXML2Object() {
    assertEquals(setUpPageStatus, 'complete');
    var buffer = top.testManager.documentLoader.buffer();
    
    var feed = new StoryQResults(buffer);               

    assertEquals(feed.version, '0.1')
    assertEquals("Number of stories", $(feed).size(), 1)
    $.each(feed, function(){
      alert(this)               
    })

}

Even though I know that I getting a function returned instead of an object I am still going to see if I can invoke my own loading function within JSUnit. Here’s what the code would look like below. I wouldn’t recommend running it – just take a look at it. The code to me is a mixtures of styles that start to bloat the code. On the one hand, JSUnit has this setup phase with explicit flags and no anonymous functions. On the other hand, because I am using JQuery conventions, I encapsulate alot of that logic. For example, jQuery(function(){}) waits for the page to be loaded before executing ("#tree").story(), Then I have the callback function inline. It looks good from the outside, but it doesn’t work.

The order of calls is: loading, in test and then loaded. Indicating that my JQuery function runs after the test has been run. The order should have been loading, loaded and then in test. In this sense, while setUpPage runs within its own setup/test/teardown cycle. But my JQuery call isn’t linked into this. JQuery waits is waiting on a document flag rather than a custom flag (within testManager). At this point, I do not wish to dig into these libraries to work them out to get it to all play nicely. It wasn’t designed to work this way. Let’s find one that was.

var data = '';

function setUpPage() {
    setUpPageStatus = 'running';
    alert('loading')
    jQuery(function() {
      $("#tree").storyq({
          url: '../../xml/results-01.xml', 
          success: null, 
          load: function(feed) {
            data = feed;
            alert('loaded')
            setUpPageComplete()
            }
          });
    });
}

function setUpPageComplete() {
    if (setUpPageStatus == 'running')
        setUpPageStatus = 'complete';
}

function testXML2Object() {
    alert('in test')
    assertEquals(setUpPageStatus, 'complete');

    assertEquals(data.version, '0.1')
    assertEquals("Number of stories", $(feed).size(), 1)
}

I’m invoking the two-feet principle: I’m moving onto the next framework (after a quick search): QUnit

  1. No comments yet.
  1. No trackbacks yet.