Skip to content

Commit

Permalink
Code coverage done right
Browse files Browse the repository at this point in the history
* Moved code coverage from srunner to stest
* Updated README
* Updated deps

Rather than evaluate the entire code block at once,
this new methods continues to evaluate the code as
you call methods, ensuring that code inside timeouts
and stuff still gets evaluated.
  • Loading branch information
Siddharth Mahendraker committed Dec 19, 2011
1 parent 7c36a9c commit 0462253
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 178 deletions.
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,15 @@ See the source for more details and documentation.

Tests can be run en masse using `srunner`:

Usage: srunner [-s] [-c] [modules] -r [regexp]
Usage: srunner [-s] [modules] -r [regexp]

Options:
-s, --silent supress output [boolean]
-c, --cover files to output code coverage for [string]
-r, --regexp regexp of files to test [string] [required]
-s, --silent supress output [boolean]
-r, --regexp regexp of files to test [string] [required]

Which looks like this in the command line:

srunner -c lib/foobar.js -r test/test-.*\.js
srunner -r test/test-.*\.js

If you prefer not to use `srunner`, you can
still run tests like this:
Expand Down
131 changes: 0 additions & 131 deletions bin/coverage.js

This file was deleted.

37 changes: 1 addition & 36 deletions bin/srunner.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,12 @@ var path = require("path"),
color = require("colors"),
optimist = require("optimist"),
argv = optimist
.usage("Usage: $0 [-s] [-c] [modules] -r [regexp]")
.usage("Usage: $0 [-s] [modules] -r [regexp]")
.options("s",{
description: "supress output",
alias: "silent",
boolean: true
})
.options("c",{
description: "files to output code coverage for",
alias: "cover",
string: true
})
.options("r",{
description: "regexp of files to test",
alias: "regexp",
Expand All @@ -29,12 +24,10 @@ var path = require("path"),
*
* -r: regexp of files to test
* -s: silent
* -c: code coverage
*
*/

var silent = argv.s;
var coverage = argv.c ? argv.c.split(",") : [];
var r = path.join(process.cwd(), argv.r);

var info = function(buffer, colr){
Expand Down Expand Up @@ -75,31 +68,3 @@ filtered.forEach(function(file){
info(stdout);
});
});

if(coverage.length){
var codecover = require("./coverage").cover(/.*/);

coverage = coverage.map(function(file){ return path.join(process.cwd(), file); });
coverage.forEach(function(file){ require(file); });

filtered = filtered.map(function(file){ return dir+"/"+file; });
filtered.forEach(function(file){ require(file); });

var counter = 0;
coverage.forEach(function(obj, i){
counter++;
codecover(function(cd){
var stats = cd[obj].stats();

var col = "magenta";
info("Coverage for: "+path.basename(obj)+"\n", col);
info("Lines seen: "+stats.seen+"\n", col);
info("Lines missing: "+stats.missing+"\n", col);
info("Percentage seen: "+Math.floor(stats.percentage*100)+"%\n", col);
info("\n");
counter--;

if(counter === 0) codecover.release();
});
});
}
68 changes: 64 additions & 4 deletions lib/stest.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
var events = require("events"),
color = require("colors");
fs = require("fs"),
path = require("path"),
color = require("colors"),
coverage = require("runforcover").cover(/.*/);

/*
* @class stest
Expand All @@ -17,6 +20,15 @@ function stest(){
this.promise = new events.EventEmitter();
this._queue = [];

this._coverqueue = [];

this._out = function(col, str){
if(!str)
process.stdout.write(col);
else
process.stdout.write(color[col](str));
}

this._addTime = function(func){
var now = Date.now();
func();
Expand All @@ -38,12 +50,12 @@ function stest(){
}

// write results
process.stdout.write(color[c](result+" "+name+" - "+time+"ms\n"));
self._out(c, result+" "+name+" - "+time+"ms\n");
// print errs
errors.forEach(function(err){
process.stdout.write(color.red(err.message+"\n"));
self._out("red", err.message+"\n");
if(err.type !== "stest")
process.stdout.write(color.red(err.stack+"\n"));
self._out("red", err.stack+"\n");
});
}
}
Expand Down Expand Up @@ -119,6 +131,30 @@ stest.prototype.addCase = function(name, opts, test){
return this;
}

/*
* Allows stest to track function calls for
* code coverage
*
* @param {String} lib
*
* This method returns the same object as
* require(lib) except it allows stest to track
* which functions have been called and which
* haven't.
*
* @api public
*/


stest.prototype.cover = function(lib){

var realroot = path.dirname(module.parent.filename);
lib = path.resolve(realroot, lib);
this._coverqueue.push(lib);

return require(lib);
}

/*
* Runs the test cases synchronously
*
Expand Down Expand Up @@ -190,6 +226,30 @@ stest.prototype.run = function(){
totalTime += self._addTime(function(){ teardown.apply(self.ctx,[errors]); });
//give a report
self._report(name, errors, totalTime);

coverage(function(cd){
self._coverqueue.forEach(function(lib){
var file = fs.readFileSync(lib).toString().split("\n");
var stats = cd[lib].stats();
var c = "magenta", err = "red", g = "green";

self._out("\n");
self._out(c, "Module: "+path.basename(lib)+"\n");
self._out(c, "Percentage seen: "+Math.floor(stats.percentage*100)+"%\n");
self._out(c, "Lines seen: "+stats.seen+"\n");
self._out(c, "Lines missed: "+stats.missing+"\n");

stats.lines.forEach(function(line){
self._out("\n");
self._out(g, line.lineno-1+": "+file[line.lineno-2]+"\n");
self._out(err, line.lineno+": "+line.source()+"\n");
self._out(g, line.lineno+1+": "+file[line.lineno]+"\n");
});

self._out("\n");
});
coverage.release();
});
}, (opts.timeout > 0 ? opts.timeout : 250));
});
}
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
},
"main": "lib/stest.js",
"scripts": {
"test": "srunner -c lib/stest.js -r test/test-.*\\.js"
"test": "srunner -r test/test-.*\\.js"
},
"bin": {
"srunner": "bin/srunner.js"
Expand All @@ -27,7 +27,7 @@
"dependencies": {
"optimist": ">=0.2.8",
"colors": ">=0.6.0",
"bunker": ">=0.1.1"
"runforcover": ">=0.0.1"
},
"devDependencies": {}
}
6 changes: 6 additions & 0 deletions test/fixtures/coverage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
exports.something = function(a){
if(a > 0)
a = 5;
else
a = -5;
}
15 changes: 15 additions & 0 deletions test/test-coverage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
var assert = require("assert"),
stest = require("../lib/stest.js"),
cov = stest.cover("./fixtures/coverage.js");

// defaults to 250 ms
var opts = { timeout: 0 };

stest
.addCase("stest - code coverage", opts, {
setup: function(promise){
cov.something(1);
cov.something(-1);
},
})
.run();

0 comments on commit 0462253

Please sign in to comment.