Katashin .info

webpack + Testem でフロントエンド JavaScript のテストを書く

webpack を使っているプロジェクトで、テストコードも webpack で依存関係の解決やトランスパイルをしたいということがあったので、その時に行ったことをまとめます。

webpack の設定 #

テストコードは個々のファイルがエントリポイントとなっているため、webpack の設定でもそのように指定する必要があります。 entry にエントリポイントにしたいファイルを配列で渡すことで、ロード時に指定されたファイルをすべて実行するようにビルドされます。webpack が標準で glob パターンなどをサポートしてないので、別途自分で書く必要があります。

// webpack.config.test.js
const path = require('path')
const glob = require('glob')

module.exports = {
  // ...
  entry: glob.sync('./test/**/*.js'),
  output: {
    path: path.resolve(__dirname, '.tmp'),
    filename: 'test.js',
  },
  // ...
}

Testem の設定 #

Testem には webpack で出力されたファイルを読み込ませます。 src_files パスを指定するだけで良いです。

# testem.yml
---
framework: mocha
src_files:
  - .tmp/test.js

watch させるスクリプトを書く #

テストコードが変更される度にテストの実行を行いたい場合、別途スクリプトを書く必要があります。Node で書く場合、以下のように、 Testem.prototype.startDev を実行することで Testem を起動させることができます (たぶんドキュメントに書かれてない)。gulp を使っているプロジェクトなら、 webpack と Testem を watch させるタスクを書くのが一番簡単だと思います。

// gulpfile.js
const fs = require('fs')
const webpack = require('webpack')
const Testem = require('testem')
const yaml = require('js-yaml')

gulp.task('webpack:test', () => {
  const compiler = webpack(require('...config_file...'))

  compiler.watch(200, (err) => {
    if (err) throw err
  })
})

gulp.task('testem', () => {
  const testem = new Testem()
  testem.startDev(yaml.safeLoad(fs.readFileSync(__dirname + '/testem.yml')))
})

gulp.task('test', ['webpack:test', 'testem'])

シェルスクリプトで書く場合は以下のようになります。単純に & で複数実行するだけだと、 ctrl-C した時にバックグラウンドタスクが終了しないため、終了させるための処理を書く必要があります。 trap 'kill %1' SIGINTctrl-C された時にバックグラウンドタスクにまわした webpack を終了してくれるようになります。また、Testem を終了させた時、webpack を終了させるまで待つために、 wait コマンドの実行が必要です。

#!/bin/bash

trap 'kill %1' SIGINT webpack --watch --config (config_file) & testem wait

テストコードを書く #

ここまでやれば後はテストコードを書くだけです。webpack がモジュール読み込みやトランスパイルなどをやってくれるため、ブラウザ上で動かす必要のあるテストも書きやすいと思います。

import assert from 'power-assert';
import module from '../src/some-module';

describe('Module', () => {
  it('should return true', () => {
    assert(module() === true);
  });

  ...
});

おわりに #

個人的に、テストコードを書くことは二の次になりやすいので、テストを行うまでのプロセスを簡単にすることや、テストコードを書くこと自体を楽にすることは重要視しています。テストコードを webpack でビルドできるようにしたり、変更を watch させたりすることで、テストコードをとても書きやすくなったと感じてます。