mocha + webpack = mocha-loader が便利

※ Webpackを使って開発されている方向けです。

みなさんは、開発しながら同時にテストを流していますか？

[mocha-loader](https://webpack.js.org/loaders/mocha-loader/)

このローダを`webpack`のConfigに追加するだけで、`webpack-dev-server`で開発中や、ビルド時に自動でテストを流してくれます。
せっかく書いたテスト、流し忘れがなくなるのはいいことですよね。

## 代替フレームワーク

「`mocha-loader`」個人的には好きなのですが、これから発展していくのかは微妙です。
一応、mocha + webpackなら他にもフレームワークがあります。

- [mocha-webpack](https://github.com/zinserjan/mocha-webpack)
- [mochapack](https://github.com/sysgears/mochapack)

ちなみに`mochapack`は、`mocha-webpack`の更新が止まっているようなので、作ったらしいです。
ただ、`webpack4`との相性なのか、私の環境が悪かったのか、どちらもうまく動かなかったので、`mocha-loader`を使いました。

では、使い方を説明していきます。

## 使い方

### インストール

```bash
npm i -D mocha mocha-loader
```

この通り、`mocha`がインストールされてある必要があります。
逆に言えば、インストールされている`mocha`のバージョンが使われます。

### 設定

`entry`と`module`に設定を足すだけです。

`entry`には、テストファイルを指定します。
`module`で、mocha-loaderを読み込みます。

これだけです。

```javascript:webpack.config.js
module.exports = {
  ...
  entry: [
    "test": [
      "./test/sample1.spec.js",
      "./test/sample2.spec.js",
    ]
  ]
  ...
  module: {
    rules: [
      {
        test: /spec\.js$/,
        use: {
          loader: "mocha-loader",
          options: {
             // mocha.setup(option)に渡すオプションが書ける
             // https://mochajs.org/#running-mocha-in-the-browser
          }
        },
        exclude: /node_modules/
      }
    ]
  }
}
```

テストのサンプルです。

```javascript:sample1.spec.js
import { add } from "../src/index.js";

import chai from "chai";

chai.should();

describe("sample1 test", () => {
  it("add test", () => {
    add(1, 2).should.be.eqaul(3);
  });
});
```

### テスト結果を確認する。

[html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin)を使います。

```javascript:webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  ...

  plugins: [
    new HtmlWebpackPlugin({
      filename: "test.html",
      inject: "body",
      chunks: ["test"]
    })
  ]
}
```

[ここ](https://github.com/webpack-contrib/mocha-loader/blob/master/src/web.js)を見ると分かりますが、テスト結果は、`id=mocha`の要素に入るので、`HtmlWebpackPlugin`で、テンプレートを用いて埋め込むことも可能です。

`webpack`コマンドでビルドすることで、`dist/test.html`ができ、そちらで結果が見れます。

上のサンプルだと、chaiのメソッド名が間違っています。
× `eqaul`
○ `equal`

ので、こんな結果が見れます。

![mocha-example1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169861/e292ea43-648d-6c58-b1ec-107ba54240d2.png)

## CI

残念ながら、`mocha-loader`はドキュメントが簡潔すぎてCIへの導入がよくわからないです。
なので、少々強引な方法ですが、test.htmlをスクレイピングすることで、エラーを集めることは可能です。

ここでは、[puppeteer](https://github.com/GoogleChrome/puppeteer)を使いました。

```javascript:ci.js
const puppeteer = require("puppeteer");

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto(`file://${__dirname}/../dist/test.html`);

  await page.waitFor("#mocha-report");

  const error = await page.evaluate(() => {
    const errorElements = document.getElementsByClassName("error");

    return [...errorElements].map(x => x.innerText).join("\n\n");
  });

  await browser.close();

  if (error !== "") {
    console.error(error);

    process.exit(1);
  }
})();

```

## まとめ

どうでしたでしょうか。
紹介した例はこちらのリポジトリに入れておきましたので、よかったら見てください。

[mocha-loader-example](https://github.com/coder-ka/mocha-loader-example)