0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

n8nでJavaScriptコードをデバッグしたりテストする

Posted at

はじめに

n8nというワークフローのサービスがあるのですが、日本ではほとんど話題になっていません。SaaSもあるけど、自分で建てることもできて、それだと月数百円でできるので、是非広まってほしい。自分で建てる方法は下記をご覧ください。

ちなみに、Qiitaで大変バズっていた『しらせ君』、これはn8nで動いていると書かれています。

わたしも真似をして、Slackの通知ボット『Tsutchy』を作り、かなり活躍しています。

本題

n8nでは、Notionからデータを取得したり、Google Driveにファイルを格納したり、Xでツイートしたり、APIさえ公開されていれば、いろいろなことができます。でもその組み合わせだけだとあまり問題解決には至らず、途中で加工します。
単純なところだと、Notionから取得した情報をもとにツイートする文面を作るとか、AというデータソースとBというデータソースを合わせて何かするとか、まぁ切りがないわけですが。

そういう痒い所には、JavaScriptを書くモジュールがあります。これはエンジニアにとっては結構大きいです。(Pythonでも書けます)
ループさせたいとか、フィルタしたいとか、Group Byしたいとか思っても、それ用のモジュールの入力方法がわからないとかできない、ストレスがたまるサービスもあるのです。外部のJavaScriptを実行するサービスに登録して、それを呼び出すとか。まどろっこしすぎる!

そんな便利なn8nですが、課題があって、今回の記事。デバッグしづらい問題
JavaScriptのモジュールで、コードを書く欄は👇この画面。大きな入力欄があるだけです。

image.png

公式掲示板でもデバッグはどうやるのって話題に出ていて、console.log()しかないよ😭という会話がありました。

そうは言ってもそれはちょっと・・・ということで

解決案:VSCodeで書く

普通ー・・・。すみません。

メリットは3つあります。

1️⃣ テストコードをしっかり書いて、実行しておくことで、インプットとアウトプットの想定が可視化されます。

2️⃣ n8nでは、前のワークフローを何度も実行できないことがあるのですが、外でテストができれば、何度も実行できます。何度も実行できないとは、例えばXへポストし、コードでその結果を使うとか。

3️⃣ 細かく関数化することで、細かくテストできます。

メイン処理を関数化

Codeモジュールの大きな入力欄1つに対して、1つのファイル・1つの関数で定義して、jestでその関数をテストするだけです。はい、普通。
ちょっとした工夫としては、関数にするっていうことくらいでしょうか。

code1.js
// 新しいフィールドを作って1を設定する
function code1() {
  for (const item of $input.all()) {
    item.json.myNewField = 1;
  }
  
  return $input.all();
}
// return oneCode();

こんな感じで、Code1.jsは関数定義で、テスト後、それをn8nへコピペすればOK。

VSCodeならテスト💯もできるし、デバッグ🪲もできる。

$オブジェクトの定義💰

n8nでは、$オブジェクト(jQueryではありません)で、ワークフローの前に実行した結果を参照できます。$('node1').all()で、node1の結果配列要素を取得。

デフォルトで入っている$inputは、直前の処理のアウトプットだと思いますが、順序を入れ替えたりすると"直前の処理"というのが変わって嫌なので、$('node1')とノード名を指定するようにしています。

コード内では、それを書くので、テスト用に作りました。👇
私は、今のところ$('~~').all()$('~~').first()しか使わないので

n8n_object.js
/*
    n8nのcodeモジュールで使用する"$"関数をモック
*/
const mockResults = {};

const $ = function (nodeName) {
    return {
        // 前処理の結果データを登録する
        registerMockData: (objectArray) => {
            console.assert(
                Array.isArray(objectArray),
                'objectArray must be an array'
            );

            mockResults[nodeName] = objectArray.map((obj) => ({json: obj}));
        },

        // n8nで使用する関数
        all: () => mockResults[nodeName],
        first: () => mockResults[nodeName][0],
    };
};

module.exports = $;

これをテストで使うときには、👇こんな感じで。

Code1.test.js
const $ = require('../n8n_object');
const code1 = require('../code1');

describe('code1', () => {
    it('code1_simple_test1', () => {
        // テストデータの準備
        $('node0').registerMockData([
            {
                id: 1,
                val: "abc",
            },
            {
                id: 2,
                val: "def",
            },
        ]);

        // 実行
        result = code1();

        // 検証
        expect(result.length).toBe(2);
        expect(result[0].id).toBe(1);
        expect(result[0].val).toBe("abc");
        expect(result[0].myNewField).toBe(1);
        expect(result[1].id).toBe(2);
        expect(result[1].val).toBe("def");
        expect(result[1].myNewField).toBe(2);
    });
});

jestのテストケースを、VSCodeのデバッグ実行ができるので、デバッグもできます。この設定は「vscode jest デバッグ」あたりでググれば出てきます。

おわりに

n8nはとても便利なのですが、コーディングがメインではないので、手厚くはないです。なので自前で外に環境を作って、外でテストをして、n8nへ移行するという形でした。

Qiitaを見てn8nを使うような人は、Codeモジュールは必ず使うと思います。これを作っておくことで安心感・安定感が増すので、n8nを使う人はやってみてください。

ではよきワークフローライフを!

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?