grunt-template-jasmine-istanbul icon indicating copy to clipboard operation
grunt-template-jasmine-istanbul copied to clipboard

Web Worker coverage isn't showing in the coverage report

Open dnln opened this issue 9 years ago • 4 comments

Firstly, this tool has been really helpful for integrating Istanbul into my project. Thanks for taking the time to maintain it.

I've been using this for a few months with grunt-contrib-jasmine and recently tried using it to get coverage reports on a web worker.

Given the following scenario Istanbul is showing no coverage for worker.js, however the worker is being called and the test is passing.

worker.js:

self.addEventListener('message', function(e) {

      self.postMessage(e.data + " world"); 

}, false);

testSpec.js:

describe('worker test', function() {

    it('should pass', function(done) {

        var worker = new Worker('worker.js');

        worker.addEventListener('message', function (e) {
                expect(e.data).toEqual('hello world');
                done();
        });

        worker.postMessage('hello');

    });

});

GruntFile.js:

module.exports = function(grunt) {

        grunt.initConfig({
            jasmine: {
                coverage: {
                    src: ['worker.js'],
                    options: {
                        specs: 'testSpec.js',
                        template: require('grunt-template-jasmine-istanbul'),
                        templateOptions: {
                            coverage: 'bin/coverage.json',
                            report: [
                                {
                                    type: 'html',
                                    options: {
                                        dir: 'bin/html'
                                    }
                                },
                                {
                                    type: 'cobertura',
                                    options: {
                                        dir: 'bin/cobertura'
                                    }
                                },
                                {
                                    type: 'text-summary'
                                }
                            ]
                        }
                    }
                }
            }
        });

        grunt.loadNpmTasks('grunt-contrib-jasmine');

        grunt.registerTask('default', ['jasmine'])

};

This results in the following:

screen shot 2016-02-23 at 11 13 21

screen shot 2016-02-23 at 11 11 47

Is this expected? And if so, is there any way of capturing the coverage of a Web Worker using grunt-template-jasmine-istanbul?

dnln avatar Feb 23 '16 11:02 dnln

I don't really know how workers work, but I guess they are loading a resource through new Worker('worker.js');. That's probably not the instrumented file, but the original. Could you provide an example project, so we have a simple test case? Maybe you can fork https://github.com/maenu/grunt-template-jasmine-istanbul-example

maenu avatar Feb 23 '16 19:02 maenu

Yeah I thought that might be the issue. In which case I'm assuming it might not be possible to get the unit test coverage of the worker if it's loaded using new Worker(). I'll take look into other ways of running the code within the worker without spawning a new worker.

I've forked the grunt-template-jasmine-istanbul-example solution and created a simple web worker test case on a new 'web-worker' branch - https://github.com/dnln/grunt-template-jasmine-istanbul-example/tree/153c9a909ac27637dc5ed617b0278ff4d8f8465a . This solution has the same behaviour as the issue mentions, where the test passes but the coverage isn't captured.

dnln avatar Feb 24 '16 11:02 dnln

I think I've found a workaround : )

Rather than spawning a new worker you can call the worker code by dispatching a custom event. This calls the instrumented file rather than the original and shows up on the code coverage report.

describe('worker test', function() {

    it('should pass', function(done) {

        var myEvent = new Event('message');

        myEvent.data = 'hello';

        self.postMessage = function(response) {
            expect(response).toEqual('hello world');
            done();
        }

        self.dispatchEvent(myEvent);

    });

});

I've update my fork of the grunt-template-jasmine-istanbul-example solution with this example - https://github.com/dnln/grunt-template-jasmine-istanbul-example/tree/web-worker

dnln avatar Feb 24 '16 12:02 dnln

I'm glad you found a solution. But aren't you testing something different if you do not spawn a worker? If you don't spawn the worker, you are just testing the worker's code as a unit - a unit test. If you do spawn the worker, you actually test the code in a context close to the production - an integration test. Both cases are justified, but the integration test might reveal some context-specific issues which the unit test does not. Therefore, I'd do both. As an inspiration, there is an example - initially intended for RequireJS - where requested sources are redirected to the instrumented ones by running the tests through a local server, see https://github.com/maenu/grunt-template-jasmine-istanbul-example/blob/requirejs-server/Gruntfile.js#L16. Maybe the same idea can be adapted for the worker use-case?

maenu avatar Apr 11 '16 18:04 maenu