Skip to content

Instantly share code, notes, and snippets.

@kt3k
Created July 28, 2013 10:58
Show Gist options
  • Save kt3k/6098204 to your computer and use it in GitHub Desktop.
Save kt3k/6098204 to your computer and use it in GitHub Desktop.
grunt-contrib-jasmine + travis-ci + coveralls.io

jscoverage で instrumented version の src tree を作る

jscoverage src src-cov

instrumentation の command を grunt 化する (grunt-shell を使うと便利)

shell:
  instrument:
    command: 'jscoverage src src-cov'

これで、grunt shell:instrument というタスクが jscoverage src src-cov と同じになります。

instrumented version で jasmine test を走らせる。

jasmine:
  cov:
    src: 'src-cov/**/*.js'

jasmine に独自 reporter を追加して、jscoverage データを拾って console に出力する

jasmine.getEnv().addReporter() を呼ぶと独自の reporter を追加する事が出来る。 grunt-contrib-jasmine の config で spec の helper を登録出来るので、helper 内で下のような reporter を登録する。

jasmine.getEnv().addReporter({
    reportRunnerResults: function (runner) {
        if (window._$jscoverage != null) {
            phantom.sendMessage('writeln', '\ncoverage:' + JSON.stringify(window._$jscoverage));
        }
    }
});

phantom.sendMessage('writeln', '\ncoverage:' + JSON.stringify(window._$jscoverage));

jscoverage では coverage データは window._$jscoverage という object 内にためられるので、これを reportRunnerResults ( spec 終了時 hook ) の中で拾う。

phantom.sendMessage は、grunt-contrib-jasmine が提供している phantomjs から grunt に対して通信するための bridge method。

この呼び出しで grunt の出力に coverage:{...} という行が追加される。

jscoverage データを coveralls.io 形式に変換

#! /usr/bin/env node

/**
 * take jscoverage data from stdin
 * and output coveralls.io json to stdout
 */

var SOURCE_DIR = './';
var SERVICE_NAME = 'travis-ci';
var JOB_ID = process.env.TRAVIS_JOB_ID;

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

var reCoverageLine = /^coverage:(.*)/;

exports.main = function (done, logger) {
    'use strict';

    var coverage;

    var rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout,
        terminal: false
    });

    rl.on('line', function (line) {
        var match = reCoverageLine.exec(line);

        if (match) {
            var data;

            try {
                data = JSON.parse(match[1]);
                coverage = Coverage.createFromJscoverage(data, SERVICE_NAME, JOB_ID);

            } catch (e) {
                logger('coverage data broken');
                logger(e);
            }
        }
    });

    rl.on('close', function () {
        if (coverage != null) {
            logger(coverage.toCoverallsJson());
        };

        done();
    });
};

var Coverage = (function () {
    'use strict';

    var Coverage = function (files, service_name, job_id) {
        this.files = files;
        this.service_name = service_name;
        this.job_id = job_id;
    };

    Coverage.createFromJscoverage = function (data, service_name, job_id) {
        var files = [];

        Object.keys(data).forEach(function (file) {
            var cov = data[file];
            cov.shift();

            files.push({
                name: file,
                coverage: cov,
                source: Coverage.readFile(file)
            });
        });

        return new Coverage(files, service_name, job_id);
    };

    Coverage.readFile = function (file) {
        return fs.readFileSync(SOURCE_DIR + file).toString();
    };

    var coveragePt = Coverage.prototype;

    coveragePt.toCoverallsFormat = function () {
        return {
            service_job_id: this.job_id,
            service_name: this.service_name,
            source_files: this.files
        };
    };

    coveragePt.toCoverallsJson = function () {
        return JSON.stringify(this.toCoverallsFormat());
    };

    return Coverage;
}());

exports.main(function () {}, function (log) {
    console.log(log);
});

(↑ travis-ci 上で動かす前提)

上の utility を

grunt cov --no-color | ./convert-to-coveralls.js

と実行すると coveralls.io 用の json が出力される。

これを travis-ci 環境から https://coveralls.io/api/v1/jobs に post すれば、coveralls.io 上にめでたく coverage データが生成される。

travis-ci 環境にいるかどうかは TRAVIS_JOB_ID 変数が定義されているかどうかで判定出来るのでたとえば下のような Makefile を作成する。

.PHONY: default test coveralls

GRUNT = ./node_modules/.bin/grunt

default:
ifndef TRAVIS_JOB_ID
    @$(MAKE) test
else
	@$(MAKE) coveralls
endif

test:
	$(GRUNT)

coveralls:
	$(GRUNT) cov --no-color | ./convert-to-coveralls.js | curl -F "json_file=@-" https://coveralls.io/api/v1/jobs

以上を用意した上で、package.json の scripts.test を make にしておけば、local では、普通に test が実行されて、travis-ci 上では test しつつ coveralls.io に coverage データを送りつける repository 環境が出来上がる。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment