Jasmine + JSTestDriver + Coverage + RequireJS
Asked Answered
C

4

7

Wow, what a mess. This is the scenario.

  • Backbone driven JS app.
  • RequireJS for AMD functionality, initialized like this:

    <script data-main="js/main" src="js/require.js" type="text/javascript"></script>
    

    then inside main.js the following config code:

    require.config(
    {
        paths:
        {
            ... : ...
        }
    });
    

    Each Backbone View/Model/Router is a "define(...)" module, and "require("theOneRouter", ...)" is called once in main.js.

  • r.js used as optimizer with Uglify/Closure. One 'compiled' main.js is created in a ./release subfolder which I pick dynamically within my .net framework.

  • Took quite a while to get the Backbone + Require.JS to work, but works great now!

  • Then slapping Jasmine on top of that also took a little custom work, but it worked just fine. I had to load require.js from my SpecRunner.html, define each test module as an AMD using require's define(...) call, and I instantiate & run Jasmine once from a call to require's require(...) call once in the SpecRunner.html:

    require(
    [
    //"test/specs/testSpec1",
    "test/specs/views"
    ],
    function ()
    {
        jasmine.getEnv().updateInterval = 1000;
        var reporter = new jasmine.TrivialReporter();
        jasmine.getEnv().addReporter(reporter);
        ....
        ....
    });
    

    this too works great. Tests load & run, no issues. Require takes care of everything.

Now, I would like a framework like JSTestDriver to act as my runner. I've chosen JSTD for it's simplicity, ability to test on remote browsers, code coverage support, but am still open for other suggestions.

JSTestDriver per se works fine, the only problem I have is running the combination JSTD + Jasmine + ReuireJS together. The biggest issue being, if I tell JSTD in the config file about a Jasmine/Require test module in order to load it, I get the following error:

http://requirejs.org/docs/errors.html#mismatch

If I use r.js to optmize all my code into one main.js, the combination works, including Coverage, but coverage is collected on one gigantic file and hard to analyze. Not to mention it takes very long to instrument a 50k-lines-of-code js file and to run it via JSTD.

I tried creating a fixture-like js file that loads all my Jasmine test modules & code modules, but I keep returning to the above "mismatch" error, AND, if I don't tell JSTD about each module individually (by loading an html/js fixture that does the real loading) they won't get instrumented for code coverage.

Has anyone gotten this specific combination to work? Maybe I'm asking for too much...

Carrefour answered 24/5, 2012 at 20:54 Comment(0)
C
4

The solution is exactly as devadvocate mentioned. Because JsTestDriver and Require.js are competing to be the ones to manage the loading of files/dependencies, JsTestDriver throws a fit when you try to do it 100% the Require.js way (with anonymous modules and defines). Instead you have to name your modules and use require([...], function(...) {... instead of define([...]. I wrote a post that shows how to integrate QUnit, Requirejs, and code coverage with JSTD: js-test-driver+qunit+coverage+requirejs. I use QUnit in my example, but you can easily substitute QUnit for Jasmine. In trying to figure this out I considered just using PhantomJS, but for our user base it is essential that we have cross-browser testing, IE7,IE8,IE9, etc., so a single WebKit wouldn't cut it. JsTestDriver is very useful, but I'm afraid poor documentation turns developers away. Soon I'll get the code for my example up on GitHub. Hope this helps.

Contumelious answered 30/6, 2012 at 1:10 Comment(2)
Thanks for the input, good comment. Yes you're right about your points and I've tried manually naming my modules and using require calls instead of define()s, but that's not a feasible solution: even if automated, it would require substantial extra work to be performed prior to every test run, which I'd like to avoid for the sake of running tests fast during development.Carrefour
So I now have a patched version of jsTestDriver.jar that allows exlcusions of files via regular expressions. It also allows JavaScript files to be loaded from the ‘serve’ section. Serving JavaScript source files means they won't be automatically executed when the browsers' pages load. Instead, when the browser executes require.js, require is able to pull the files over from the serve section. This way the modules can be anonymous without any problem. See Backbone-TestingContumelious
L
2

I was not able to get this to work and ended up using PhantomJS to run my jasmine tests. http://phantomjs.org/

Lendlease answered 26/5, 2012 at 12:0 Comment(3)
I've considered PhantomJS, but the point of JSTD is to run cross-platform unit tests, which PhantomJS doesn't support being a headless web-kit. I guess that leads to the question whether cross-platform unit tests are necessary: should I run unit tests in a headless environment, and only focus on running integration / acceptance tests in a Selenium-like cross-browser environment?Carrefour
I built my own solution for running unit tests cross browser. I don't automate the process, but you could easily expand the solution to do so. Here is a link to my blog post --> linkLendlease
After a few weeks of experimenting around, I'm still convinced that unit tests should be run in a browser environment, not headlessly. For that reason I've been experimenting with Selenium and the hosted SauceLabs solution and so far most everything works. My only setback is code coverage: JSTD has nice smoothly integrated coverage tool & reporting and I can't seem to find a comparably smart instrumenter out there for a custom spun environment.Carrefour
W
2

Have you tried naming your modules under test and using require instead of define in your tests?

https://github.com/podefr/jasmine-reqjs-jstd

Edit:

I just released an open source toolkit which will hopefully help others as much as it helps me. It is a composition of many open source tools which gives you a working requirejs backbone app out of the box.

It provides single commands to run: dev web server, jasmine single browser test runner, jasmine js-test-driver multi browser test runner, and concatenization/minification for JavaScript and CSS. It also outputs an unminified version of your app for production debugging, precompiles your handlebar templates, and supports internationalization. No setup is required. It just works.

It also supports unnamed modules under test.

http://github.com/davidjnelson/agilejs

Waterfall answered 27/6, 2012 at 22:46 Comment(2)
Yup, I've seen that project and I've had success with it, but it's too cumbersome. In a large project with many modules require'ing many other modules, I would have to have a system in place to name all modules under test automatically. Big painpoint, imho. I've found a cleaner solution going with Selenium & Node Coverage...Carrefour
I've solved this problem with my new agilejs toolkit: github.com/davidjnelson/agilejsWaterfall
R
0

Check out this repo (Bredele appolo), it's an environment that runs Jasmine BDD specs over anonymous modules loaded with require.js and JsTestDriver.

If your are developing none-anonymous modules, I also advise to use the podefr solution.

Olivier

Ridgley answered 20/1, 2013 at 18:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.