6

in a jQuery plugin i have created helper functions, like this

(function($) {

  var someHelperFunction = function(s, d) {
    return s*d;
  }
  var someOtherHelperFunction = function(s) {
    return s*2;
  }

// here goes the normal plugin code

})(jQuery);

now I want to call someHelperFunction from the outside, to be able to unit test it, is that possible somehow?

JohnSmith
  • 4,538
  • 9
  • 25
  • 25

5 Answers5

2

Per this related question, I'd say just test the external interface.

But if you must test these methods in isolation, you'll have to test "copies" of them outside of the context of their deployment as internal methods. In other words, create an object in which they are not inaccessible to client code, and then cobble those versions together with your outer script in a pre-process. Sounds like a lot of work, but hey, that's the point of hiding methods, right? (To make them unreachable.)

Community
  • 1
  • 1
harpo
  • 41,820
  • 13
  • 96
  • 131
1

You may also like to consider JavaScript doctests. There are two implementations of which I'm aware: Ian Bicking's doctest.js, and my own doctest.

davidchambers
  • 23,918
  • 16
  • 76
  • 105
  • I'm trying to weight in the pros and cons of each library but they seem pretty similar. As the author of doctest - could you give a short run down? My use-case is to add unit tests to [white-space](https://github.com/dotnetCarpenter/white-space/issues/6) which doesn't have a public api and need to test HTML fixtures and document.readyState. – dotnetCarpenter Nov 27 '13 at 13:28
  • First, doctests allow usage examples to be tested, ensuring that they remain up to date. Doctests are really for testing the *documentation*, not the code. Secondly, doctests work well for [pure functions](http://en.wikipedia.org/wiki/Pure_function), but not for callback-based code. I suggest using a dedicated testing framework. – davidchambers Nov 27 '13 at 17:06
  • What I really like about doctest, is that I don't have to artificially create a public API just for testing. As far as I understand, I can write method/function documentation inside closures and still allow access for unit tests.I guess that it's the limitation of pure functions that is a deal breaker for me, since what I'm really testing, is browser behavior. – dotnetCarpenter Nov 28 '13 at 13:37
1

If the internal functions need testing that's a good indicator that they should maybe be in a separate module somewhere and injected as dependencies and used within your objects public interface implementation. That's the more "testable" way to do it.

var myActualImplementationTestTheHellOutOfMe = function(s, d) {

    return s*d;

}

(function($, helper) {

  var someHelperFunction = function(s, d) {
    return helper(s, d);
  }
  var someOtherHelperFunction = function(s) {
    return s*2;
  }

// here goes the normal plugin code

})(jQuery, myActualImplementationTestTheHellOutOfMe);
Derek Reynolds
  • 3,473
  • 3
  • 25
  • 34
0

the helpers are scoped inside the plugin, which is an anonymous function , and you cannot access the variables declared inside it.
If you want to test it, drop the var keyword in front of the functions. That will declare the functions as global (will attach them to the window object), giving them the ability to be visible from the window scope ( by calling someHelperFunction or window.someHelperFunction).
so, for testing :

(function($) {
    someHelperFunction = function(s, d) {
        return s*d;
    }
    someOtherHelperFunction = function(s) {
        return s*2;
    }
     // here goes the normal plugin code
})(jQuery);

after the testing is over, add the var keyword again.

Update
I think that a better approach would be to group your testable functions in an object - and construct an api. Then, on the same principle, you could make that api visible in the global scope or not:

(function($, global) {
    someHelperFunction = function(s, d) {
        return s*d;
    }
    someOtherHelperFunction = function(s) {
        return s*2;
    }

    var api = {
        someHelperFunction: someHelperFunction,
        someOtherHelperFunction: someOtherHelperFunction
    };

    // decide whether you want to expose your api or not 
    if(makeGlobal) {
        global.api = api;
    }
})(jQuery, this);
gion_13
  • 41,171
  • 10
  • 96
  • 108
  • 3
    Don't use global variables just to test your private functions. This isn't a good answer because it endorses bad practices. – drublic Nov 12 '13 at 08:18
-3

take a look at qunit, a JavaScript unit test lib

cander
  • 822
  • 1
  • 7
  • 10