Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logging with grunt and qunit

I am running javascript unittests with grunt/qunit. Sometimes the tests fails because of e.g syntax errors in the source files (works fine with file info if syntax errors are introduced in the test files). When that happens grunt simply prints the line number and not the file where the problem is.

Running "qunit:all" (qunit) task
Warning: Line 99: Unexpected identifier Use --force to continue.

Aborted due to warnings.

This does not help much since I have 100 of js files. I have looked into:

https://github.com/gruntjs/grunt-contrib-qunit

and tried to add the following to my Gruntfile.js (grunt.event.on):

module.exports = function(grunt) {
    "use:strict";
    var reportDir = "output/reports/"+(new Date()).getTime().toString();
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        qunit: {
            options: {
                '--web-security': 'no',
                coverage: {
                    src: ['../src/**/*.js'],
                    instrumentedFiles: 'output/instrument/',
                    htmlReport: 'output/coverage',
                    coberturaReport: 'output/',
                    linesTresholdPct: 85
                }
            },
            all: ["testsSuites.html"]
        }
    });


    // Has no effect
    grunt.event.on('qunit.error.onError', function (msg, stack) {
        grunt.util._.each(stack, function (entry) {
            grunt.log.writeln(entry.file + ':' + entry.line);
        });
        grunt.warn(msg);
    });     

    grunt.loadNpmTasks('grunt-contrib-qunit');
    grunt.loadNpmTasks('grunt-qunit-istanbul');
    grunt.registerTask('test', ['qunit']);

Where testsSuites.html contains:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="qunit/qunit.css">
    <script src="qunit/qunit.js"></script>
    <script src="sinonjs/sinon-1.7.3.js"></script>
    <script src="sinonjs/sinon-qunit-1.0.0.js"></script>

    <!-- Sources -->
    <script src="../src/sample.js"></script>

    <!-- Test-->
    <script src="test/sample-test.js"></script>

  </head>
  <body>
    <div id="qunit"></div>
    <div id="qunit-fixture"></div>
    <script>
    </script>
  </body>
</html>

But the source file where the problem is located is still not printed. Is is out of Grunts hands to verify source code/show line number/file where e.g a syntax error is located?

I have also tried running:

grunt test --debug 9

It prints some debug info but not any information regarding syntax errors in the javascript sources.

I have tried to install JSHint and call it on all my javascript source files:

for i in $(find ../src -iname "*.js"); do jshint $i; done

Now I get tons of errors but Grunt is still happy. If I introduce a simple syntax error e.g:

(function(){
   var sampleVar 32;

}

to provoke an error in Grunt:

Running "qunit:all" (qunit) task
Warning: Line 2: Unexpected number Use --force to continue.

Aborted due to warnings.

it simply disappears in the stream of errors generated by JSHint. How do I filter JSHint "warnings" from critical errors that will actually make Grunt fail?

Or is it qunit that should be configured for more verbose output?

like image 653
u123 Avatar asked Oct 20 '22 14:10

u123


1 Answers

grunt-contrib-qunit will display filenames when encountering a syntax error. Take this simplified version of your Gruntfile.js:

module.exports = function(grunt) {
    "use:strict";
    grunt.initConfig({
        qunit: {
            options: { '--web-security': 'no' },
            all: ["testsSuites.html"]
        }
    });

    grunt.loadNpmTasks('grunt-contrib-qunit');
};

Running it gives the error you're looking for:

$ grunt qunit
Running "qunit:all" (qunit) task
Testing testsSuites.html F.
>> global failure
>> Message: SyntaxError: Parse error
>> file:///tmp/src/sample.js:2

Warning: 1/2 assertions failed (17ms) Use --force to continue.

Aborted due to warnings.

The issue you're having looks to be a bug(?) in grunt-qunit-istanbul. The warning you're getting:

Warning: Line 99: Unexpected identifier Use --force to continue.

is Grunt handling an uncaught exception. The exception is being raised by the grunt-qunit-istanbul task. You can prove it by modifying this line in your original Gruntfile.js from:

src: ['../src/**/*.js'],

to:

src: ['../src/**/*.js.nomatch'],

This will prevent grunt-qunit-istanbul from finding and parsing any Javascript files before Qunit is run. If you let Qunit run, its error handler prints out the filenames with syntax errors like you want.

The only fix is the workaround I've described, or to patch grunt-qunit-istanbul to add an error handler for parse errors like Qunit does.

Patching grunt-qunit-istanbul

The function that is throwing the exception is Instrumenter.instrumentSync, which it is supposed to do:

instrumentSync ( code, filename )

Defined in lib/instrumenter.js:380

synchronous instrumentation method. Throws when illegal code is passed to it

You can fix it by wrapping the function call:

diff -r 14008db115ff node_modules/grunt-qunit-istanbul/tasks/qunit.js
--- a/node_modules/grunt-qunit-istanbul/tasks/qunit.js  Tue Feb 25 12:14:48 2014 -0500
+++ b/node_modules/grunt-qunit-istanbul/tasks/qunit.js  Tue Feb 25 12:19:58 2014 -0500
@@ -209,7 +209,11 @@

       // instrument the files that should be processed by istanbul
       if (options.coverage && options.coverage.instrumentedFiles) {
-        instrumentedFiles[fileStorage] = instrumenter.instrumentSync(String(fs.readFileSync(filepath)), filepath);
+        try {
+          instrumentedFiles[fileStorage] = instrumenter.instrumentSync(String(fs.readFileSync(filepath)), filepath);
+        } catch (e) {
+          grunt.log.error(filepath + ': ' + e);
+        }
       }

       cb();

Then the test will keep running (and inform you of the syntax error):

$ grunt qunit
Running "qunit:all" (qunit) task
>> /tmp/src/sample.js: Error: Line 2: Unexpected number
Testing testsSuites.html F.
>> global failure
>> Message: SyntaxError: Parse error
>> file:///tmp/src/sample.js:2

Warning: 1/2 assertions failed (19ms) Use --force to continue.

Aborted due to warnings.
like image 65
Michael Kropat Avatar answered Oct 23 '22 03:10

Michael Kropat