From ab847f3786353185f78163b02c276760a380e80c Mon Sep 17 00:00:00 2001 From: Dan Vanderkam Date: Sat, 21 Mar 2015 18:44:31 -0400 Subject: [PATCH] Generate LCOV coverage data and post to coveralls --- .travis.yml | 4 --- auto_tests/karma.conf.js | 9 +++-- gulpfile.js | 14 ++++++-- package.json | 5 ++- scripts/transform-coverage.js | 78 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 11 deletions(-) create mode 100755 scripts/transform-coverage.js diff --git a/.travis.yml b/.travis.yml index 5a4bb52..8425aa8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,8 +2,4 @@ language: node_js node_js: - "0.10" -before_script: - - npm install -g bower - - bower install - script: "gulp travis" diff --git a/auto_tests/karma.conf.js b/auto_tests/karma.conf.js index 6b673cd..4349239 100644 --- a/auto_tests/karma.conf.js +++ b/auto_tests/karma.conf.js @@ -16,13 +16,16 @@ module.exports = function (config) { ], autoWatch: false, singleRun: true, - reporters: ['mocha'], // ['spec', 'coverage'], + reporters: ['dots', 'coverage'], // or 'mocha', 'spec' preprocessors: { 'dist/dygraph-combined.dev.js': ['coverage'] }, coverageReporter: { - type: 'html', - dir: 'dist/coverage' + dir: 'dist/coverage', + reporters: [ + { type: 'html', subdir: 'report-html' }, + { type: 'lcovonly', subdir: 'report-lcov' }, + ] }, browsers: ['PhantomJS'], plugins: [ diff --git a/gulpfile.js b/gulpfile.js index 3e38b8d..f842bf7 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -98,10 +98,11 @@ gulp.task('create-loader', function() { gulp.task('create-dev', function() { var dest = 'dist'; - return gulp.src(mergePaths(src.polyfills, src.main, src.plugins, src.devOptions, src.datahandlers)) - .pipe(plugins.sourcemaps.init()) + return gulp.src(mergePaths(src.polyfills, src.main, src.plugins, src.devOptions, src.datahandlers), {base: '.'}) + .pipe(plugins.sourcemaps.init({debug:true})) .pipe(plugins.concat('dygraph-combined.dev.js')) .pipe(plugins.header(copyright)) + .pipe(plugins.sourcemaps.write('.')) // '.' = external sourcemap .pipe(gulp.dest(dest)); }); @@ -156,6 +157,13 @@ gulp.task('test', ['concat', 'create-dev'], function(done) { }, done); }); +gulp.task('coveralls', ['test'], plugins.shell.task([ + './scripts/transform-coverage.js ' + + 'dist/dygraph-combined.dev.js.map ' + + 'dist/coverage/report-lcov/lcov.info ' + + '| ./node_modules/.bin/coveralls' +])); + gulp.task('watch', function() { gulp.watch('src/**', ['concat']); }); @@ -165,5 +173,5 @@ gulp.task('watch-test', function() { }); gulp.task('dist', ['gwt-dist', 'bower-dist']); -gulp.task('travis', ['test']); +gulp.task('travis', ['test', 'coveralls']); gulp.task('default', ['test', 'dist']); diff --git a/package.json b/package.json index 1881b1c..397a5f6 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "gulp-load-plugins": "^0.8.0", "gulp-rename": "^1.2.0", "gulp-replace": "^0.5.0", - "gulp-shell": "^0.2.11", + "gulp-shell": "^0.4.0", "gulp-sourcemaps": "^1.3.0", "gulp-uglify": "^1.0.2", "jshint": "^2.5.10", @@ -48,9 +48,12 @@ "karma-phantomjs-launcher": "^0.1.4", "karma-spec-reporter": "0.0.16", "lazypipe": "^0.2.2", + "lcov-parse": "0.0.9", "mocha": "^2.1.0", "obvious-closure-library": "^20140401.0.2", + "parse-data-uri": "^0.2.0", "phantomjs": "^1.9.7-8", + "source-map": "^0.4.2", "uglify-js": "^2" }, "scripts": { diff --git a/scripts/transform-coverage.js b/scripts/transform-coverage.js new file mode 100755 index 0000000..a492f26 --- /dev/null +++ b/scripts/transform-coverage.js @@ -0,0 +1,78 @@ +#!/usr/bin/env node +/** + * This script applies a source map to LCOV data. If you have coverage data for + * a concatenated file, plus a source map, this will output LCOV data for your + * original source files. + * + * Usage: + * + * transform-coverage.js path/to/soure.map path/to/coverage.lcov > out.lcov + */ + +// TODO: make this a command line argument +var SOURCE = 'src/'; // only report files under this directory + +var assert = require('assert'), + fs = require('fs'), + lcovParse = require('lcov-parse'), + parseDataUri = require('parse-data-uri'), + sourcemap = require('source-map'); + +var sourcemapFile = process.argv[2]; +var lcovFile = process.argv[3]; + +var sourcemapData = fs.readFileSync(sourcemapFile).toString(); +var sourcemap = new sourcemap.SourceMapConsumer(sourcemapData); + +lcovParse(lcovFile, function(err, data) { + assert(!err); + // TODO: 0 --> the correct file + var lines = data[0].lines.details; + + var fileToCov = {}; // filename -> { line num -> hits } + + lines.forEach(function(line) { + var pos = sourcemap.originalPositionFor({line: line.line, column: 0}); + if (pos == null) { + return; + } + + var filename = pos.source; + + // Test coverage of node_modules is never interesting. + if (!filename || filename.indexOf('node_modules') >= 0) { + return; + } + + // Strip paths down to the source root. + var base = filename.indexOf(SOURCE); + if (base == -1) return; + filename = filename.slice(base); + + if (!fileToCov[filename]) fileToCov[filename] = []; + fileToCov[filename][pos.line] = line.hit; + }); + + // Other LCOV fields to translate: + // FN:2454 + // FNF:465 + // FNH:410 + // FNDA:1,(anonymous_1) + // LF:4570 + // LH:4002 + // BRDA:13,1,0,1 + // BRF:2213 + // BRH:1684 + + // Convert to LCOV format + for (var filename in fileToCov) { + var cov = fileToCov[filename] + console.log('SF:' + filename); + for (var i = 0; i < cov.length; i++) { + if (cov[i] != null) { + console.log('DA:' + i + ',' + cov[i]); + } + } + console.log('end_of_record'); + } +}); -- 2.7.4