Node-REDのノードのユニットテスト(単体テスト)を実装・実行する

# 概要

Node-REDのノードを自作したときのユニットテストの実装と実行方法の例を紹介します。
[Node-RED公式サイト](https://nodered.org/docs/creating-nodes/first-node#testing-your-node-in-node-red)に説明されていたことを試しましたが、
微妙にコードが間違っていてうまくいかなかったので、直して紹介します。

ソースコードは[GitHub](https://github.com/s1r-J/node-red-unittest-example)に置きましたので、適宜参照してください。

また、[Node-RED日本ユーザ会のサイト](https://nodered.jp/docs/creating-nodes/first-node)には、ユニットテストの項目は書かれていなかったので、一応邦訳らしきものを最後につけておきます。

# ユニットテスト作成・実行

## 準備

テスト対象のノードは、公式ドキュメントで紹介されているlower-caseノードです。

ドキュメントを参考にファイルを作成してください。下記のような構成になるはずです。[^1]
[^1]: [GitHubにおいたコード](https://github.com/s1r-J/node-red-unittest-example)だとbeforeブランチの状態です。

```
node-red-contrib-example-lower-case/
　├ lower-case.js
　├ lower-case.html
　└ package.json
```

## テストファイル生成(test/lower-case_spec.js)

テストする項目、期待値などを記載したテストファイルを作成します。
Node-RED公式に書かれているソースコードでは**実行できません！！**[^2]
[^2]: requireの部分が間違っているのと、helper.initが不足しています。

[テスト支援モジュール](https://www.npmjs.com/package/node-red-node-test-helper)に記載されているソースコードを利用しましょう。

1. testフォルダを作成
2. testフォルダ以下にlower-case_spec.jsを作成

## package.jsonの書き換え

ファイル内のscriptsのtestを書き換えます。

npm initでpackage.jsonを作成したとき、testに何も書かなければ
`"echo \"Error: no test specified\" && exit 1"`になっているはずです。
以下のように書き換え、[mocha](https://www.npmjs.com/package/mocha)というモジュールでtestフォルダのlower-case_spec.jsでテストすると示します。

```json:package.json
...
"scripts": {
    "test": "mocha test/lower-case_spec.js"
},
...
```

## 実行

テストを実行するのに必要なモジュールをインストールします。
まずは[mocha](https://www.npmjs.com/package/mocha)です。
これはNode.jsで実行できるテストフレームワークです。

```
npm i -g mocha
```

次のモジュールは開発での依存関係となるので、`--save-dev`をつけます。

```
npm install node-red --save-dev
npm install should --save-dev
npm install node-red-node-test-helper --save-dev
```

これらを実行することで、package.jsonが更新されます。

```json:package.json
...
"devDependencies": {
    "node-red": "^0.19.5",
    "node-red-node-test-helper": "^0.1.8",
    "should": "^13.2.3"
}
```

これで準備完了です。あとはテストを実行しましょう。

```
npm test
```

以下のように表示され、テストが通過したことがわかります。

 ```
 > node-red-contrib-example-lower-case@1.0.0 test \path\node-red-contrib-example-lower-case
 > mocha test/lower-case_spec.js

   lower-case Node
     √ should be loaded
     √ should make payload lower case

   2 passing (45ms)
 ```

これでテストの作成・実行ができるようになりました。
あとはテストファイルを書き換えてテストを増やしたり、他のノードのテストを作成したりしましょう！

テストファイルの書き方は私自身がまだ全く理解できていないです。[node-red-node-test-helper](https://www.npmjs.com/package/node-red-node-test-helper)に詳しそうなので、確認してみてください。

# Node-RED Creating your first node Unit Testingの邦訳

間違っているソースコードが書かれているとこを訳すのはどうなのよ、とは思うものの...
参考程度にどうぞ。

<details><summary>原文</summary>
<p>
> ## Unit Testing
> To support unit testing, an npm module called node-red-node-test-helper can be used. The test-helper is a framework built on the Node-RED runtime to make it easier to test nodes.

> Using this framework, you can create test flows, and then assert that your node properties and output is working as expected. For example, to add a unit test to the lower-case node you can add a test folder to your node module package containing a file called _spec.js

> **ここに_spec.jsのコード**

> These tests check to see that the node is loaded into the runtime correctly, and that it correctly changes the payload to lower case as expected.

> Both tests load the node into the runtime using helper.load supplying the node under test and a test flow The first checks that the node in the runtime has the correct name property. The second test uses a helper node to check that the output from the node is, in fact, lower case.

> The helper module contains other examples of tests taken from the Node-RED core nodes. For more information on the helper module, see the associated README.
</P>
</details>

## ユニットテストの実行

ユニットテストを支援するため、[`node-red-node-test-helper`](https://www.npmjs.com/package/node-red-node-test-helper)と呼ばれるnpmモジュールを利用することができます。このテスト支援モジュールはNode-RED実行時に基づいて作成されたフレームワークで、ノードのテストをより簡単にしています。

このフレームワークを使うことで、テストフローを作成することができ、さらにノードの設定値と出力結果が期待通りに動作していることを確認できます。例えば、lower-caseノードにユニットテストを追加するため、` _spec.js`ファイルを含んだ`test`フォルを、自身のノードモジュールパッケージに追加しましょう。

<details><summary>test/_spec.js[^2]</summary>
<p>

```js:_spec.js
var should = require("should");
var helper = require("node-red-test-helper");
var lowerNode = require("../lower-case.js");

describe('lower-case Node', function () {

  afterEach(function () {
    helper.unload();
  });

  it('should be loaded', function (done) {
    var flow = [{ id: "n1", type: "lower-case", name: "test name" }];
    helper.load(lowerNode, flow, function () {
      var n1 = helper.getNode("n1");
      n1.should.have.property('name', 'test name');
      done();
    });
  });

  it('should make payload lower case', function (done) {
    var flow = [{ id: "n1", type: "lower-case", name: "test name",wires:[["n2"]] },
    { id: "n2", type: "helper" }];
    helper.load(lowerNode, flow, function () {
      var n2 = helper.getNode("n2");
      var n1 = helper.getNode("n1");
      n2.on("input", function (msg) {
        msg.should.have.property('payload', 'uppercase');
        done();
      });
      n1.receive({ payload: "UpperCase" });
    });
  });
});
```
</P>
</details>

これらのテストではノードが実行環境に正しくロードされていること、そしてノードがpayloadの値を期待通りに小文字に変換していることをチェックしています。

どちらのテストも、`helper.load`を利用してテスト対象ノードを実行環境にロードし、テストの実施・テストフローへの配置をおこないます。最初のテストでは、実行時のノードの名前プロパティが正しいことを確認しています。2番目のテストでは、支援ノードを利用してテスト対象ノードからの出力が実際に小文字にされていることを確認しています。

支援モジュールはNode-REDのコアノードから選びだしたユニットテスト例が含まれています。支援モジュールについてさらに知りたければ、関連したREADMEを参照してください。