Can Blanket.js work with Jasmine tests if the test

2019-04-15 13:07发布

问题:

We've been using Jasmine and RequireJS successfully together for unit testing, and are now looking to add code coverage, and I've been investigating Blanket.js for that purpose. I know that it nominally supports Jasmine and RequireJS, and I'm able to successfully use the "jasmine-requirejs" runner on GitHub, but this runner is using a slightly different approach than our model -- namely, it loads the test specs using a script tag in runner.html, whereas our approach has been to load the specs through RequireJS, like the following (which is the callback for a requirejs call in our runner):

    var jasmineEnv = jasmine.getEnv();
    jasmineEnv.updateInterval = 1000;

    var htmlReporter = new jasmine.TrivialReporter();
    var jUnitReporter = new jasmine.JUnitXmlReporter('../JasmineTests/');

    jasmineEnv.addReporter(htmlReporter);
    jasmineEnv.addReporter(jUnitReporter);

    jasmineEnv.specFilter = function (spec) {
        return htmlReporter.specFilter(spec);
    };

    var specs = [];

    specs.push('spec/models/MyModel');
    specs.push('spec/views/MyModelView');

    $(function () {
        require(specs, function () {
            jasmineEnv.execute();
        });
    });

This approach works fine for simply doing unit testing, if I don't have blanket or jasmine-blanket as dependencies for the function above. If I add them (with require.config paths and shim), I can verify that they're successfully fetched, but all that appears to happen is that I get jasmine-blanket's overload of jasmine.getEnv().execute, which simply prints "waiting for blanket..." to the console. Nothing is triggering the tests themselves to be run anymore.

I do know that in our approach there's no way to provide the usual data-cover attributes, since RequireJS is doing the script loading rather than script tags, but I would have expected in this case that Blanket would at least calculate coverage for everything, not nothing. Is there a non-attribute-based way to specify the coverage pattern, and is there something else I need to do to trigger the actual test execution once jasmine-blanket is in the mix? Can Blanket be made to work with RequireJS loading the test specs?

回答1:

I have gotten this working by requiring blanket-jasmine then setting the options

require.config({
    paths: {
        'jasmine': '...',
        'jasmine-html': '...',
        'blanket-jasmine': '...',
    },
    shim: {
        'jasmine': {
            exports: 'jasmine'
        },
        'jasmine-html': {
            exports: 'jasmine',
            deps: ['jasmine']
        },
        'blanket-jasmine': {
            exports: 'blanket',
            deps: ['jasmine']
        }
    }
});

require([
    'blanket-jasmine',
    'jasmine-html',
], function (blanket, jasmine) {
    blanket.options('filter', '...'); // data-cover-only
    blanket.options('branchTracking', true); // one of the data-cover-flags

    require(['myspec'], function() {
        var jasmineEnv = jasmine.getEnv();
        jasmineEnv.updateInterval = 250;
        var htmlReporter = new jasmine.HtmlReporter();

        jasmineEnv.addReporter(htmlReporter);
        jasmineEnv.specFilter = function (spec) {
            return htmlReporter.specFilter(spec);
        };
        jasmineEnv.addReporter(new jasmine.BlanketReporter());
        jasmineEnv.currentRunner().execute();
    });
});

The key lines are the addition of the BlanketReporter and the currentRunner execute. Blanket jasmine adapter overrides jasmine.execute with a no-op that just logs a line, because it needs to halt the execution until it is ready to begin after it has instrumented the code.

Typically the BlanketReport and currentRunner execute would be done by the blanket jasmine adapter but if you load blanket-jasmine itself in require, the event for starting blanket test runner will not get fired as subscribes to the window.load event (which by the point blanket-jasmine is loaded has already fired) therefore we need to add the report and execute the "currentRunner" as it would usually execute itself.

This should probably be raised as a bug, but for now this workaround works well.