Writing "unit testable" jQuery code?
Asked Answered
S

4

17

Up untill now I was used to write all my code inside the ready() function like:

$(document).ready(function() {
  // all my code
});

Now I see that with this approach, my code is not "unit testable", e.g. I cannot access the stuff inside ready() from QUnit.

What is the proper way to structure jQuery code that is compatible with using the ready() function and able to be tested?

Is there a good open source code base or project to study and learn from?

Starnes answered 16/8, 2011 at 14:38 Comment(0)
H
8

Have your code in the ready handler just calling functions outside of the ready handler:

$(document).ready(function() {
  // call some functions outside of handler
});

// most of my code

That way, you can call those functions for unit testing as well.


NB, there's a short-cut for $(document).ready:

$(function() {
  // call some functions outside of handler
});

// most of my code
Hasheem answered 16/8, 2011 at 14:44 Comment(2)
Is the "short-cut" you mention guaranteed to be executed after the DOM has loaded?Starnes
$(document).ready(function(){}); is identical to $(function(){}); in terms of functionality. They will both call the handlers either when the dom ready event is fired, or when they are evaluated if the dom ready event has already fired. From the jQuery docs: All three of the following syntaxes are equivalent: $(document).ready(handler), $().ready(handler) (this is not recommended), $(handler).Hasheem
G
7

I see two approaches.

  1. Place the QUnit code inside document ready to run after your own code.

  2. Place your code in a module.

Option #2 looks like this:

var MyModule = (function() {
    // Your code
}());

$(document).ready(function() {
    // Quit tests, referring to MyModule.xxx
});

In option #2 it is true you do not get access to private elements within the module.

Ben Cherry talked about this a while ago in http://www.adequatelygood.com/2010/7/Writing-Testable-JavaScript where he actually made a controversial comment about closure-based privacy because of its impact on unit testing.

Goldarned answered 16/8, 2011 at 14:51 Comment(1)
+1 but you dont have to wrap QUnit tests in a $(document).ready(function() { }); - QUnit already does that for you.Hooded
A
1

One of the most effective approaches is to structure your coding using JS "namespaces" and indeed you can get a great example from the jQuery core.

Alive answered 16/8, 2011 at 14:53 Comment(0)
C
0

A strange approach that I took with untestable jQuery scripts goes like this:

  • install karma
  • include all the various scripts that can't be unit tested per se within the karma include files anyway
  • an syntax error introduced in a core script, for example, will fail the karma test, even if it's not unit tested
  • additionally if the scripts do create any globals, test for the presence of those globals in karma
  • finally refactor the scripts to have more callable units and run the tests in karma

So start with a browser run to at least sanity check!

Cottager answered 28/12, 2021 at 22:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.