Skip to content

Commit

Permalink
chore: Determine code coverage during the first test run
Browse files Browse the repository at this point in the history
  • Loading branch information
honzajavorek committed Mar 20, 2017
1 parent d274515 commit fe2d4c2
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 58 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Expand Up @@ -19,8 +19,8 @@ before_install:
install: "npm install --no-optional"
script:
- "npm run lint"
- "npm test"
- "npm run test:coverage"
#- "npm run test:hooks-handlers" # disabled because of https://github.com/apiaryio/dredd/issues/672
after_success:
- "npm run coveralls"
- "npm run coveralls || true"
- "npm run semantic-release || true"
33 changes: 16 additions & 17 deletions bin/dredd
@@ -1,6 +1,7 @@
#!/usr/bin/env node

var fs = require('fs');
var path = require('path');


// Ignore this block, it's pure magic, temporary fix
Expand All @@ -10,7 +11,7 @@ var fs = require('fs');
});


var dir = process.env.COLLECT_COVERAGE ? 'src' : 'lib';
var dir = process.env.COVERAGE_DIR ? 'src' : 'lib';
var DreddCommand = require('../' + dir + '/dredd-command');


Expand All @@ -24,38 +25,36 @@ var dreddCli = new DreddCommand({


function exit(exitStatus) {
if (process.env.COLLECT_COVERAGE) {
if (process.env.COVERAGE_DIR) {
// Before Dredd exits, we need to collect coverage stats and save them to
// a file. We abuse 'mocha-lcov-reporter' to do this.
var LCov = require('mocha-lcov-reporter');

// Pretending there is Mocha runner
var EventEmitter = require('events').EventEmitter;
var runner = new EventEmitter();

// Monkey-patching 'process.stdout.write' to catch all stdout in a variable
// Monkey-patching 'LCov.prototype.write' to catch all output to a variable
var content = '';
var write = process.stdout.write;
process.stdout.write = function(stdout) {
content += stdout;
};
var write = LCov.prototype.write;

LCov.prototype.write = function(string) {
content += string;
}

// Collecting the stats
var LCov = require('mocha-lcov-reporter');
LCov(runner);
new LCov(runner);
runner.emit('end');

// Undo the monkey-patching
process.stdout.write = write;
LCov.prototype.write = write;

// Save stats as lcov file
fs.appendFile('./lcov/dredd-bin.info', content, function (err) {
if (err) { console.error(err); }
process.exit(exitStatus);
});
} else {
// Regular exit, no coverage collecting
process.exit(exitStatus);
var file = path.join(process.env.COVERAGE_DIR, 'dredd-bin.info');
fs.appendFileSync(file, content);
}

process.exit(exitStatus);
}


Expand Down
8 changes: 4 additions & 4 deletions package.json
Expand Up @@ -16,11 +16,11 @@
"build": "coffee -b -c -o lib/ src/ && coffee scripts/generate-cli-docs.coffee",
"pretest": "npm run build",
"test": "mocha \"test/**/*-test.coffee\"",
"test:coverage": "scripts/coverage.sh",
"test:hooks-handlers": "coffee scripts/test-hooks-handlers.coffee",
"prepublish": "npm run build",
"coverage": "scripts/cov",
"coveralls": "npm run coverage && cat cov.info | coveralls",
"semantic-release": "scripts/semantic-release"
"coveralls": "scripts/coveralls.sh",
"semantic-release": "scripts/semantic-release.sh"
},
"repository": {
"type": "git",
Expand Down Expand Up @@ -65,7 +65,7 @@
"jscoverage": "^0.6.0",
"lcov-result-merger": "^1.2.0",
"mocha": "^3.0.0",
"mocha-lcov-reporter": "^1.2.0",
"mocha-lcov-reporter": "^1.3.0",
"nock": "^9.0.4",
"ps-node": "^0.1.4",
"semantic-release": "^6.3.2",
Expand Down
34 changes: 0 additions & 34 deletions scripts/cov

This file was deleted.

49 changes: 49 additions & 0 deletions scripts/coverage.sh
@@ -0,0 +1,49 @@
#!/bin/sh
# Runs tests and collects code coverage to ./cov.info file


PROJECT_DIR=$(pwd -P)

COVERAGE_FILE="$PROJECT_DIR"/cov.info
COVERAGE_DIR="$PROJECT_DIR"/lcov
INSTRUMENTED_CODE_DIR="$PROJECT_DIR"/src-cov
BIN_DIR="$PROJECT_DIR"/node_modules/.bin


# Cleanup & preparation
rm -rf "$INSTRUMENTED_CODE_DIR" "$COVERAGE_DIR" "$COVERAGE_FILE"
mkdir "$INSTRUMENTED_CODE_DIR" "$COVERAGE_DIR"


# Creating directory with instrumented JS code
"$BIN_DIR"/coffeeCoverage \
--exclude=node_modules,.git,test,scripts \
--path=relative \
"$PROJECT_DIR" "$INSTRUMENTED_CODE_DIR" 1>&2

cp "$PROJECT_DIR"/package.json "$INSTRUMENTED_CODE_DIR"

cp -r "$PROJECT_DIR"/bin "$INSTRUMENTED_CODE_DIR"/bin
chmod +x "$INSTRUMENTED_CODE_DIR"/bin/*

cp -r "$PROJECT_DIR"/scripts "$INSTRUMENTED_CODE_DIR"/scripts
cp -r "$PROJECT_DIR"/docs "$INSTRUMENTED_CODE_DIR"/docs
cp -r "$PROJECT_DIR"/test "$INSTRUMENTED_CODE_DIR"/test

mkdir -p "$INSTRUMENTED_CODE_DIR"/node_modules/.bin
ln -s "$BIN_DIR"/* "$INSTRUMENTED_CODE_DIR"/node_modules/.bin


# Testing
export COVERAGE_DIR
cd "$INSTRUMENTED_CODE_DIR" && npm test
cd ..


# Merging LCOV reports
"$BIN_DIR"/lcov-result-merger "$COVERAGE_DIR/*.info" "$COVERAGE_FILE"
echo "Coverage saved as '$COVERAGE_FILE'"


# Output & cleanup
rm -rf "$INSTRUMENTED_CODE_DIR" "$COVERAGE_DIR"
14 changes: 14 additions & 0 deletions scripts/coveralls.sh
@@ -0,0 +1,14 @@
#!/bin/sh
# Picks up the ./cov.info file and sends the coverage to coveralls.io


# Input validation
if [ ! -f ./cov.info ]; then
(>&2 echo "Coverage file 'cov.info' was not found.")
(>&2 echo "First run the test suite as 'npm run test:coverage'.")
exit 1
fi


# Coveralls
cat ./cov.info | ./node_modules/.bin/coveralls
File renamed without changes.
2 changes: 1 addition & 1 deletion test/mocha.opts
@@ -1,4 +1,4 @@
--compilers=coffee:coffee-script/register
--reporter=spec
--reporter=test/reporter.js
--timeout=120000
--recursive
30 changes: 30 additions & 0 deletions test/reporter.js
@@ -0,0 +1,30 @@
fs = require('fs');
path = require('path');

Spec = require('mocha').reporters.Spec;
LCov = require('mocha-lcov-reporter');


/**
* Combined reporter
*
* Behaves the same way as Mocha's built-in 'Spec' reporter, but if
* the environment variable 'COVERAGE_DIR' is set to a directory,
* collects code coverage to './lcov/mocha.info' file.
*
* If you want to learn more about how coverage collecting works
* in Dredd's test suite, see the 'npm run test:coverage' script.
*/
module.exports = function (runner, options) {
new Spec(runner, options);

if (process.env.COVERAGE_DIR) {
// Monkey-patching the 'LCov.prototype.write' so we could save
// the LCov output to a file instead of a standard output
LCov.prototype.write = function (string) {
var file = path.join(process.env.COVERAGE_DIR, 'mocha.info');
fs.appendFileSync(file, string);
}
new LCov(runner, options);
}
};

0 comments on commit fe2d4c2

Please sign in to comment.