f:id:shogonir:20170529011413p:plain

 

目次

  1. この記事の目的
  2. テスト対象のコードを準備する
  3. karmaとbabel, webpack
  4. karmaでカバレッジを測定する
  5. テストを実行します
  6. まとめ

 

1. この記事の目的

最近、babel, webpackを使っていてkarmaでテストを書いています。

カバレッジの測定をしたくてkarma-coverageを使ってあれこれしていました。
しかしどうも依存するライブラリまでカバレッジ対象になってしまいます。
そこで今回はistanbulを使った解決策を紹介します。

ソースコードをGithubに上げました。

github.com

 

2. テスト対象のコードを準備する

今回はthree.jsに依存するCanvasController.jsを準備します。
最終的に、このCanvasController.jsをテストするコードを書き、three.jsを除いたカバレッジを計測します。

まずは、必要なパッケージを導入します。

yarn add three
yarn add --dev 
    babel-core 
    babel-loader 
    babel-preset-es2015 
    babel-preset-es2016 
    webpack

 
次にwebpackの設定ファイルを準備します。

module.exports = {
  context: __dirname + /src,
  entry: {
    application: ./application,
  },
  output: {
    path: __dirname + /dist,
    filename: app.js
  },
  module: {
    loaders: [
      { 
        test: /.js$/, 
        exclude: /node_modules/, 
        loader: "babel-loader", 
        query:{
          presets: [es2015, es2016]
        }
      }
    ]
  }
};

 
次にエントリーポイントのsrc/application.jsを次のように保存します。

export { default as CanvasController } from ./CanvasController;

 
次にsrc/CanvasController.jsを下記の通り保存します。

import * as THREE from three;

export default class CanvasController {
  
  constructor(canvasId) {
    let canvas = document.getElementById(canvasId);
    let renderer = new THREE.WebGLRenderer({canvas});
  }
}

 
これで、canvasのHTML要素を探して、three.jsのWebGLRendererを初期化するコードができました。
ではこれからはkarmaを使って、このCanvasController.jsをテストしていきます。
しかし、three.jsはカバレッジの対象外にするようにしていきます。

 

3. karmaとbabel, webpack

まず前提として、karmaでテストを実行するには、テストコードとテスト対象のコードがes5のJSである必要があります。
しかし、babelを使ってes2016などの記法で開発を進めている方も多いかと思います。
そこで、preprocessorという仕組みを使って、テスト実行前の処理を指定します。

今回はwebpackをpreprocessorとすることで、テストができるようにします。
この際のwebpackのloaderにbabelを指定することで、es2016->es5に変換してからwebpackに渡します。
webpackが最終的に1つのファイルにまとめたものをkarmaに渡し、テストを実行します。

まずは必要なパッケージを導入しましょう。

yarn add --dev 
    assert 
    karma 
    karma-chrome-launcher 
    karma-mocha 
    karma-webpack 
    mocha

 
次にkarmaの設定ファイルkarma.conf.jsを次のように保存します。

module.exports = function(config) {
  config.set({
    frameworks: [mocha],
    browsers: [Chrome],
    singleRun: true,
    logLevel: config.LOG_INFO,
    
    plugins: [
      karma-chrome-launcher,
      karma-mocha,
      karma-webpack
    ],
    
    files: [
      ./test/**/*.js
    ],
    preprocessors: {
      ./test/**/*.js: [webpack]
    },
    
    webpack: {
      module: {
        loaders: [
          {
            loader: babel-loader,
            exclude: /node_modules/,
            query: {
              presets: [es2015, es2016]
            }
          }
        ]
      }
    },
  });
};

 
これで、babel -> webpack -> karmaという順番でテスト実行できるようになりました。
次にテストコードを書きます。test/CanvasController.karma.jsを次の通り保存します。

import assert from assert;

import CanvasController from ../src/CanvasController;

describe(CanvasController, () => {
  describe(constructor, () => {
    it(no throw, () => {
      let canvas = document.createElement(canvas);
      canvas.id = canvas;
      document.body.appendChild(canvas);
      let canvasController = new CanvasController(canvas);
    });
  });
});

 
今回はカバレッジが本質なのでテストコードの書き方については省略します。
この状態でpackage.jsonのscripts.test: “karma start"として、yarn testを実行するとテストが走るはずです。

 

4. karmaでカバレッジを測定する

karmaでカバレッジを測定するために下記のパッケージを導入していきます。

  • istanbul-instrumenter-loader
    • 渡されたコードにinstrumentを仕込むローダー
    • instrument: その場所をテスト実行時に通ったか測定するセンサー
  • karma-coverage-istanbul-reporter
    • テスト実行してカバレッジをまとめて出力する

 
実際にパッケージを導入するコマンドは下記の通りです。

yarn add --dev 
    istanbul-instrumenter-loader 
    karma-coverage-istanbul-reporter

 
次にkarmaの設定ファイルkarma.conf.jsを修正します。

module.exports = function(config) {
  config.set({
    ...
    plugins: [
      karma-chrome-launcher,
      karma-coverage-istanbul-reporter,
      karma-mocha,
      karma-webpack,
      istanbul-instrumenter-loader
    ],
    ...
    webpack: {
      module: {
        loaders: [
          {
            loader: babel-loader,
            exclude: /node_modules/,
            query: {
              presets: [es2015, es2016]
            }
          },
          {
            loader: istanbul-instrumenter-loader,
            exclude: /node_modules/,
            include: /src/,
            enforce: post
          }
        ]
      }
    },
    reporters: [progress, coverage-istanbul],
    coverageIstanbulReporter: {
      reports: [text-summary]
    }
  });
};

 
修正したことは下記の通りです。

  • pluginsを追加
  • loadersにistanbul-instrumenter-loaderを追加
    • node_modulesを除外してsrc配下のソースのみ測定対象にします
    • enforce: ‘postとしてbabelより後になるようにしています
      • このローダーもes5のjsファイルにのみ対応していたはず
  • reportersにistanbulを追加
    • text-summaryの形式でカバレッジを出力します

 

5. テストを実行します

yarn testを実行すると、テストが実行され、カバレッジが出力されます。

f:id:shogonir:20170529021653p:plain

 

6. まとめ

今回はbabel, webpack, karmaを使ってテストのカバレッジを測定する方法を紹介しました。
ポイントはistanbul-instrumenter-loaderでnode_modulesをカバレッジ測定対象外にしている点です。
さて、これでブラウザでテストが動きますし、カバレッジも測定できます。
テストを書きつつモダンな環境でどんどん開発していきましょう。