LoginSignup
4
2

More than 3 years have passed since last update.

Node-REDの'node-red-node-test-helper'でなぜかノード取得するとnullになっちゃう時の例

Last updated at Posted at 2019-12-04

Node-RED Adventcalendar 12/5担当の ウエンツです。
最近テストコードを書いててよくハマるのでそれについて書こうと思います。

Node-REDでテストコードを書いていて、意外にハマったのが、動かすためのNodeがなぜかnullになっちゃう!!!という問題でした。

node.js
  it('should be loaded', function(done) {
    var flow = [{ id: 'n1', type: 'hoge', name: 'hoo' }]
    helper.load(hogeNode, flow, function() {
      var n1 = helper.getNode('n1') // ここがnullになっちゃう!!
      n1.should.have.property('name', 'hoo')
      done()
    })
  })

今までテストを書いていてハマったポイントは2つあったので、それをお伝えしようと思います。

その1 本体コード・テストコードが間違ってる

まずはここを疑う必要があります。
本体コードを動かしている時にエラーが出てもそのエラー内容はテスト実行時には出してくれません。そこがかなりのハマりポイントになる。

上のテストコードは、ただノードを置いてエラーにならないか?というテストですが、flowに入れたフローズ構造に必須項目が漏れてたからエラーになってたと かいうことが発生しているとかになるとnullになってしまいます。

テストコードの間違いの例

node.js
  it('should be loaded', function(done) {
    var flow = [{ id: 'n1', type: 'hoge', hissu: 'hisssu', name: 'hoo' }] // ここに必須項目入れなきゃいけなかったけどなかった!!!
    helper.load(hogeNode, flow, function() {
      var n1 = helper.getNode('n1')
      n1.should.have.property('name', 'hoo')
      done()
    })
  })

本体コードの間違い例

node.js

  function hogeNode(config) {
    RED.nodes.createNode(this, config)

    if (!config.hissu) {
      this.error('No device specified')
      return // ここのリターン書いてなかった!!!
    }

なのでnullになる時はまず、必須項目が入っているか?Defaultは設定してあるか?エラーが起きた時はきちんと'return'しているか?などを疑ってみると改善が見込めます。

その2 Credentialの使い方が間違ってる

Credentialの使い方は公式にいまいち詳しく書いていないのでハマることも多いかと思います。
Credentialを利用する場合は、flowにそのcredentialを記述し、credentialを作成し、helper.loadでそのcredentialを定義しているノードを渡してあげる必要があります。
文字で書いててもよくわかんないので、コードを以下に示します。

node.js

const credentialNode = require('../credential') // これが必要!
const hogeNode = require('../hoge')

・・・

  credential = {
    'fc7980bd.49f74': { // 以下に出てくるflow内のcredentialノードのIDと名前を合わせる
      id: 'username',
      password: 'password'
    }
  }

    it('Success', function(done) {
      var flow = [
        {
          id: 'b962aadc.99ef58',
          type: 'hoge',
          z: '2ca93200.9acbde',
          name: 'hoge node',
          login: 'fc7980bd.49f74', // ここ必須
          x: 280,
          y: 160,
          wires: [['h1']]
        },
        {
          id: 'h1',
          type: 'helper'
        },
        {
          id: 'fc7980bd.49f74', // ここのノードが大事。上のノードで定義したIDを同じものにする
          type: 'credentials',
          z: ''
        }
      ]

      helper.load([credentialNode, hogeNode], flow, n1_credential, function() { // credentialノードと本体ノードをどちらも渡す!
        var helper_node = helper.getNode('h1')

        helper_node.on('input', function(msg) {
          try {
            expect(msg)
              .to.be.an('object')
              .with.any.keys('payload')
              .and.property('payload')
            done()
          } catch (err) {
            done(err)
          }
        })
      })
    })

ポイントはhepler.nodecredentialNodeもarrayで渡す必要があるということです。
ドキュメント( https://github.com/node-red/node-red-node-test-helper#loadtestnode-testflows-testcredentials-cb )に、testCredentialsがあるので、「ここでとりあえず渡せばいいのかなー」とおもって情報だけ渡しても動いてくれない点です。
きっちりルールになっているので、IDを合わせて、requireした物も一緒に渡し、flowにも含めてあげなければいけません。

知っとくと便利

フローをいちいちテストで手書きするのは面倒ですよね。
そういう時は、実際にNode-RED上でフローを作って、それをエクスポートしたものを貼り付けて不要なものを消す、などとすればミスが減らせます。
スクリーンショット 2019-11-27 15.17.44.png

おわりに

これ以外でも多分色々と問題は起きると思いますが、まだNode-REDのテストの情報はとても少ないです!
これがみなさんんお役に立つことを望むと共に、みなさんのナレッジが今後も増えていくと嬉しいなあ。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2