はじめに
CoffeeScript で書かれたプログラムを Karma-Coverage でカバレッジを計測しようとしたときに、色々エラーがでて難航したのでそのメモです。
CoffeeScriptを使っていない場合は、こういう問題はおそらく起こらないですが、 CoffeeScriptを愛する同志の方々はお気をつけ下さい。
症状としては 「 preprocessor.coverage で Syntax Errorが出る 」というものなのですが、
その原因として2つほどありましたので共有します。
おさらい
Karma-Coverage をよく知らない方は、
Karma+istanbulを利用して、AngularJSで構築したプロダクトのCoverage計測
を参考にされると良いです。
上記はCoffeeScriptについては触れられていないので、併せて
の設定を見ると良いと思います。preprocessors
の部分が少し変わっている(coffee
というのが増えている)のがポイントです。
症状1: 変換後のJSファイルをもう一度 Coffee->JS 変換しようとしている
エラーメッセージ
例えば、以下の様なエラーが出ます。
ERROR [preprocessor.coverage]: Syntax error on line 2, column 5: unexpected 'A' (\u0041)
1 : 'use strict';
2 : var AccountModel;
^ :~~~~~^
3 :
4 : AccountModel = (function() {
5 : var _defaultAccount, _q, _tmpAccount;
これは一度 Coffee → JS に変換してあるものをもう一度 変換しようとしているように見えます。
そりゃあ Syntax Errorにはなるでしょうが、最初は原因がわかりませんでした。
原因と対策
原因は単純で、前述の karma.conf.js
の中の preprocessors
で指定したファイルが、
coffee
coverage
の両方に含まれていると発生します。
それぞれ重複しないように指定しないといけません。
なので、最初からそれが想定されたDIR構成になっていると楽できますね。
NG
preprocessors: {
'**/*.coffee': 'coffee',
'app/scripts/*/**/*.coffee': 'coverage'
},
OK
preprocessors: {
'app/scripts/*.coffee': 'coffee',
'app/scripts/*/**/*.coffee': 'coverage',
'test/**/*.coffee': 'coffee'
},
一応ドキュメントに書いてある
https://github.com/karma-runner/karma-coverage
のREADMEにそうかいてあります。
preprocessors: {
// source files, that you wanna generate coverage for
// do not include tests or libraries
// (these files will be instrumented by Istanbul via Ibrik unless
// specified otherwise in coverageReporter.instrumenter)
'src/*.coffee': ['coverage'],
// note: project files will already be converted to
// JavaScript via coverage preprocessor.
// Thus, you'll have to limit the CoffeeScript preprocessor
// to uncovered files.
'test/**/*.coffee': ['coffee']
},
症状2
エラーメッセージ
例えば、以下の様なエラーが出ます。
ERROR [preprocessor.coverage]: Syntax error on line 4, column 29: unexpected '\n' (\u000A)
1 : "use strict"
2 : app = angular.module "myApp"
3 : app.config ($stateProvider, $urlRouterProvider) ->
4 : $stateProvider.state("tab",
^ :~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
5 : url: "/tab"
6 : abstract: true
7 : templateUrl: "/templates/partial/common/tabs.html"
とか
ERROR [preprocessor.coverage]: Cannot read property 'loc' of undefined
などです。
原因
原因はおそらく以下のスレッドのコメント以降なのだと思います。
https://github.com/karma-runner/karma-coverage/issues/75#issuecomment-43605565
端的に言うと、
Karma-Coverage が利用している ibrik が IstanbulというJS Code Coverageツールを使っています。
問題はこの ibrikにあって、ibrikの中で CoffeeScriptRedux compilerというのを使っているが、それが現状のCoffeeScriptの仕様に合致していない
ということです。
従って、特定のCoffeeの文法に対してエラーになってしまいます。
ibrik が CoffeeScriptRedux を使用しているので、それを本家CoffeeScriptを使うように変更した、
HBOCodeLabs/ibrik
というForkがあります。しかしこれの CoffeeScriptのVersionも1.6.3のままです。
対策
それぞれ別の個人が管理しているため、依存関係的に根が深く、誰にどうPull Requestを送るか悩ましいところです。
そこでとりあえず、
- HBOCodeLabs/ibrikを Forkして、その package.json を修正して CoffeeScript の Version を 1.7系(最新)にする
- Karma-Coverage を Forkして、そのforkした HBOCodeLabs/ibriks のGithubリポジトリを指すようにする
というやっつけな対策があります。
- 現状:
Karma-Coverage -> ibrik -> CoffeeScript Redux
- 修正:
Karma-Coverage(fork) -> HBOCodeLabs/ibrik(fork) -> CoffeeScript ~1.7.1
という感じになります。
私の場合は
- Forkした Karma-Coverage: https://github.com/mokemokechicken/karma-coverage
- Forkした ibrik: https://github.com/mokemokechicken/ibrik
として、 package.json
の karma-coverage
を以下のようにしました。
"karma-coverage": "git+https://github.com/mokemokechicken/karma-coverage.git#master",
これで何とか動くようになりました。
この程度の修正なので、いずれこの辺の依存関係が整理されて、何も考えずに動くようになるとは思います(希望…)。