coffeescript + webpack をjasmine + mocha + karmaでテストしてJenkinsに管理

# 背景

1. coffeescript - JavaScriptのコードを生成するためのコンパクトなスクリプト言語
2. webpack - module bundler
3. jasmine - js test framework
4. mocha - js test framework
5. karma - js test runner
6. phantomjs - browser

# 全体像

1. coffeescriptで各Moduleを作成。
2. webpackでModuleを使いentryファイルからCompileして一つのJSファイルを作成。
3. karma(runner)でjasmine(test)とmocha(reporters)を使い、Unitテストを作成する。テスト作成時にもwebpackを利用し、entry-test.jsにCompileしてから karmaで実行。

# 各準備

## coffeescript

module を作成

```coffeescript:src/test.coffee
class TestClass
  ...
module.exports = TestClass
```

## npmで必要なものをインストール

適宜必要なものをインストール

```package.json
{
  "private": true,
  "name": "client",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "webpack-watch": "webpack -w",
    "webpack-build": "webpack -p"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "coffee-loader": "^0.7.3",
    "istanbul-instrumenter-loader": "^3.0.1",
    "jasmine": "^3.1.0",
    "jasmine-core": "^3.1.0",
    "jquery": "3.1.1",
    "jquery-pjax": "*",
    "karma": "^2.0.0",
    "karma-chrome-launcher": "^2.2.0",
    "karma-coffee-preprocessor": "^1.0.1",
    "karma-coverage": "^1.1.1",
    "karma-jasmine": "^1.1.1",
    "karma-junit-reporter": "^1.2.0",
    "karma-mocha-reporter": "^2.2.5",
    "karma-phantomjs-launcher": "^1.0.4",
    "karma-sourcemap-loader": "^0.3.7",
    "karma-webpack": "^3.0.0",
    "webpack": "2.3.3"
  },
  "devDependencies": {}
}
```

## webpack

Compileの定義を書く

```javascript:webpack.config.js
var webpack = require('webpack');
module.exports = {
    entry: ['./src/entry.js'],
    output: {
        path: '/path/to/output'
        filename: 'webpack-out.js'
    },
    module: {
        loaders: [
            { test: /\.coffee$/, loader: "coffee-loader" }
        ],
    },
    resolve: {
        extensions: [".coffee"]
    },
    plugins: [
        new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery',
            jquery: 'jquery',
            'window.jQuery': 'jquery'
        })
    ]
}
```


```
npm run webpack-build
```
これでwebpack-out.jsが完成　※これは、Karmaでテストするときには、全く関係ない。Karmaでテストするときの、webpackの設定は全てkarma.config.unit.jsに記載。ここで作成されたwebpack-out.jsはbundleされたjsでそのままappで使うもの。



## testファイルを用意

```test/entry-test.js
var TestClass = require('!coffee-loader!./test_class.coffee');
describe('TestClass', function() {
    describe('test ', function() {
        it('expects to pass', function() {
            var testClass = new TestClass();
            expect().toBe(true);
        });
    });
});
```

## karma

```client/karma.config.js
module.exports = function(config) {
  config.set({

    basePath: '.',

    frameworks: ['jasmine'],

    files: [
        'test/entry-test.js',
    ],

    exclude: [
    ],

    preprocessors: {
        'src/test.coffee': ['coffee', 'webpack'],
        'test/entry-test.js': ['webpack', 'coverage'],
    },

    coffeePreprocessor: {
       options: {
           sourceMap: true
       }
    },

    reporters: ['mocha', 'junit', 'coverage'],

    junitReporter: {
        outputDir: 'report',
        outputFile: 'karma-results.xml',
        suite: '',
        useBrowserName: false,
        nameFormatter: undefined,
        classNameFormatter: undefined,
        properties: {}
    },

    coverageReporter: {
        dir: 'report',
        subdir: 'coverage',
        reporters: [
            { type: 'html' },
            { type: 'cobertura' }
      ]
    },

    port: 9876,


    colors: true,

    logLevel: config.LOG_DEBUG,

    autoWatch: true,

    browsers: ['PhantomJS'],

    singleRun: false,

    concurrency: Infinity,

    webpack: {
        module: {
            loaders: [
                {
                    test: /\/.coffee$/,
                    loader: "coffee-loader",
                    exclude: /(test|node_modules)/,
                }
            ],
        },
        devtool: 'inline-source-map',
    }
  })
}
```

ここでのポイントは、`useBrowserName: false`と`subdir: 'coverage`であり、これを指定しないと、Browserの名前がDir名になってしまうので、めんどくさくなってしまう。

## テストを実行

```
node_modules/karma/bin/karma start karma.config.unit.js --single-run
```

結果ファイルが`report/karma-results.xml`と`report/coverage/index.html`にでてくるので、Jenkinsにセットする。

## Jenkinsに追加

jenkinsのマシンにnpmが入ってるのを前提に以下のようにテストをExecute Shellに追加

```
...
node --version
which npm
npm --version
npm install && node_modules/karma/bin/karma start karma.config.unit.js --single-run --no-colors --reporters junit,dots,coverage
...
```
karma-resultを以下のようにJunitの部分にセット
![image.png](https://qiita-image-store.s3.amazonaws.com/0/7059/c483ba41-e324-2934-dc0f-71aba5b61aa6.png)

CoverageをPublish documentsにセット
![image.png](https://qiita-image-store.s3.amazonaws.com/0/7059/6531b0e6-b2fd-843a-d2cf-674abd3bbc5d.png)


完了！


# 課題

entryファイルをcoffeescriptにしたらなんかうまくいかなかったので、そのまま放置したが、何か間違えてるはずなので、いつかできたら更新。

とりあえず、rails5でもwebpackerが導入されてるし、ちょっとwebpackいじったのでメモしておいた。

# 参考

1. https://github.com/karma-runner/karma-junit-reporter
2. https://www.npmjs.com/package/karma-coverage
3. https://www.codementor.io/codementorteam/javascript-testing-framework-comparison-jasmine-vs-mocha-8s9k27za3