Skip to content

Commit

Permalink
Merge pull request #9 from hammerlab/coverage
Browse files Browse the repository at this point in the history
Generate code coverage data
  • Loading branch information
ihodes committed Feb 25, 2015
2 parents 2eca1e1 + bd658c1 commit eea0cdf
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ node_js:

before_install: npm install -g grunt-cli

script: grunt travis
script: grunt travis && ./scripts/post-coverage.sh
38 changes: 34 additions & 4 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ module.exports = function(grunt) {
},
test: {
files: {
'build/tests.js': ['test/**/*-test.js']
},
'build/tests.js': ['src/**/*.js', 'test/**/*-test.js', '!src/main.js']
}
},
options: {
transform: [
Expand All @@ -51,20 +51,50 @@ module.exports = function(grunt) {
}
}
},
jscoverage: {
src: {
expand: true,
cwd: 'build/',
src: ['tests.js'],
dest: 'build/cov/',
ext: '.js'
}
},
exorcise: {
bundle: {
options: {},
files: {
'build/tests.map': ['build/tests.js'], // externalize source map
}
}
},
mocha_phantomjs: {
all: ['test/**/*.html']
run: {
src: ['test/runner.html']
},
cov: {
src: ['test/coverage.html'],
options: {
reporter: 'test/lcov-reporter.js',
output: 'build/bundled.lcov'
}
}
}
});

grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-flow-type-check');
grunt.loadNpmTasks('grunt-mocha-phantomjs');
grunt.loadNpmTasks("grunt-jscoverage");
grunt.loadNpmTasks("grunt-exorcise");

grunt.registerTask('watchFlow', ['flow:app:start', 'watch:flow']);
grunt.registerTask('watchFlowProd', ['flow:app:start', 'watch:flowProd']);
grunt.registerTask('prod', ['browserify:dist']);
grunt.registerTask('browsertests', ['browserify:test']);
grunt.registerTask('test', ['browsertests', 'mocha_phantomjs']);
grunt.registerTask('test', ['browsertests', 'mocha_phantomjs:run']);
grunt.registerTask('travis', ['flow', 'test']);
grunt.registerTask('coverage',
['browsertests', 'exorcise', 'jscoverage', 'mocha_phantomjs:cov']);
};
7 changes: 7 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,26 @@
},
"devDependencies": {
"chai": "^2.0.0",
"coveralls": "^2.11.2",
"es5-shim": "^4.1.0",
"flow-bin": "^0.4.0",
"grunt": "^0.4.5",
"grunt-browserify": "^3.3.0",
"grunt-contrib-watch": "^0.6.1",
"grunt-env": "^0.4.2",
"grunt-exorcise": "^1.0.0",
"grunt-flow-type-check": "^0.4.2",
"grunt-jscoverage": "^0.1.3",
"grunt-mocha-phantomjs": "^0.6.0",
"grunt-mocha-test": "^0.12.7",
"lcov-parse": "0.0.9",
"mocha": "^2.1.0",
"mocha-lcov-reporter": "0.0.1",
"parse-data-uri": "^0.2.0",
"react-tools": "^0.12.2",
"reactify": "^1.0.0",
"sinon": "^1.12.2",
"source-map": "^0.3.0",
"text-encoding": "^0.5.2"
}
}
13 changes: 13 additions & 0 deletions scripts/post-coverage.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash
# Generate code coverage and post it to Coveralls.
set -o errexit
set -x

# Generate LCOV data for the bundled tests
grunt coverage

# Convert code coverage data on the bundled test file back to the originals.
./scripts/transform-coverage.js \
build/tests.map \
build/bundled.lcov \
| ./node_modules/.bin/coveralls
67 changes: 67 additions & 0 deletions scripts/transform-coverage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/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;
});

// 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');
}
});
4 changes: 2 additions & 2 deletions test/RemoteFile-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ describe('RemoteFile', () => {
FakeXHR.restore();
});

it('should fetch a subset of a file', () => {
it('should fetch a subset of a file', (done) => {
FakeXHR.addResponse('http://example.com/file.txt',
new TextEncoder('utf-8').encode('01234567890').buffer);

var f = new RemoteFile('http://example.com/file.txt');
var promisedData = f.getBytes(10, 20);
var promisedData = f.getBytes(10, 11);

expect(FakeXHR.numRequests).to.equal(1);
// expect(req.requestHeaders.Range).to.equal('bytes=10-29');
Expand Down
32 changes: 32 additions & 0 deletions test/coverage.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<html>
<head>
<meta charset="utf-8">
<title>pileup.js Tests</title>
<link rel="stylesheet" href="../node_modules/mocha/mocha.css" />
</head>
<body>
<div id="mocha"></div>

<!-- Polyfills for PhantomJS -->
<script src="../node_modules/es5-shim/es5-shim.min.js"></script>
<script src="../node_modules/es5-shim/es5-sham.min.js"></script>
<script src="../node_modules/text-encoding/lib/encoding.js"></script>

<!-- Mocha -->
<script src="../node_modules/mocha/mocha.js"></script>
<script>mocha.setup('bdd')</script>

<!--<script src="../build/cov/tests-debug.js"></script>-->
<!--<script src="../build/tests-debug.js"></script>-->
<script src="../build/cov/tests.js"></script>

<script>
mocha.checkLeaks();
if (window.mochaPhantomJS) {
mochaPhantomJS.run();
} else {
mocha.run();
}
</script>
</body>
</html>
44 changes: 44 additions & 0 deletions test/lcov-reporter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// See https://github.com/StevenLooman/mocha-lcov-reporter/pull/7

/**
* Expose `LCov`.
*/

exports = module.exports = LCov;

/**
* Initialize a new LCOV reporter.
* File format of LCOV can be found here: http://ltp.sourceforge.net/coverage/lcov/geninfo.1.php
* The reporter is built after this parser: https://raw.github.com/SonarCommunity/sonar-javascript/master/sonar-javascript-plugin/src/main/java/org/sonar/plugins/javascript/coverage/LCOVParser.java
*
* @param {Runner} runner
* @api public
*/

function LCov(runner) {
runner.on('end', function(){
// In a browser context, coverage will be in window.$jscoverage.
var g = typeof(global) != 'undefined' ? global : window;
var cov = g._$jscoverage || {};

for (var filename in cov) {
var data = cov[filename];
reportFile(filename, data);
}
});
}

function reportFile(filename, data) {
process.stdout.write('SF:' + filename + '\n');

data.source.forEach(function(line, num) {
// increase the line number, as JS arrays are zero-based
num++;

if (data[num] !== undefined) {
process.stdout.write('DA:' + num + ',' + data[num] + '\n');
}
});

process.stdout.write('end_of_record\n');
}

0 comments on commit eea0cdf

Please sign in to comment.