僕は技術ができない

技術のできないスーツ園児ニアが考えていること

Azure Functions for Node で単体テストする方法(園児向け)

今回は Azure Functions for Node で 単体テスト(Unit Test)するやり方を紹介します。
とはいえ、これってガッツリ公式ドキュメントに載っているので、MSのドキュメント自力で完璧に読めるぜ!って方はお帰りください。

docs.microsoft.com

MSのドキュメント色んな意味でムズ過ぎて読めないって人には役に立つかもです。

はじめに

  • 基本的には公式ドキュメントの通りです。
  • ただ、一部妙にわかりにくい部分があるので自分へのメモを兼ねて残しておきます。わかりにくい部分に関しては本記事の最後に書いています。
  • 公式ドキュメントとはフォルダ構成を少し変えています(gitignoreで管理しやすくするためテストに関するものはすべて外出ししている等)
  • フツーのAzure Functions (for Node)のUnit Test方法の紹介です。Durable Functions (for Node)のためのテスト方法ではありません。Jestの詳細な使い方にも触れていません。
  • ひょっとしたら、頑張ればDurable Functionsでもいけるかもしれません(いけないかもしれません)

Jest

Azure Functions for Node の Unit Test には Jest を使います。
JestというのはJavaScriptのためのテストツールです。Wikipediaでは以下のように定義されています。

Jest[1] is a JavaScript Testing Framework with a focus on simplicity. It works with projects using: Babel, TypeScript[2], Node.js, React, Angular and Vue.js. It aims to work out of the box and config free.
Jest (JavaScript framework)

公式ページはなんだか楽しそう。 f:id:contemporarycuz:20190716232313g:plain jestjs.io

本題(Functions向けのJest導入)

HttpTriggerタイプのFunction Appを用意

こんな感じ

> tree /f
C:...\UNITTEST
│  .gitignore
│  host.json
│  local.settings.json
│  proxies.json
│
├─.vscode
│      extensions.json
│      launch.json
│      settings.json
│      tasks.json
│
└─HttpTrigger
        function.json
        index.js
        sample.dat
上記UnitTestフォルダ直下で以下を実行
mkdir TestModule        // 名前はテキトー
cd TestModule
npm init -y                   // package.json作るため脳死実行
npm i jest                     // Jestインストール
package.jsonのscripts.testをjestに変更
  "scripts": {
    "test": "jest"
  },
TestModule直下で以下を実行
mkdir testing
cd testing
ni defaultContext.js        // Powershellを想定。niはtouchみたいなやつ。
ni index.test.js
defaultContext.jsに以下をコピペ
module.exports = {
    log: jest.fn()
};
index.test.jsに以下をコピペ(こいつがテストコードです)
const httpFunction = require('../../HttpTrigger/index');
const context = require('./defaultContext');

test('Http trigger should return known text', async () => {

    const request = {
        query: { name: 'Bill' }
    };

    await httpFunction(context, request);

    expect(context.log.mock.calls.length).toBe(1);
    expect(context.res.body).toEqual('Hello Bill');
});

これでテストの準備完了!!
この時点でTestModule内はこんな感じになってるはず。

│  package-lock.json
│  package.json
└─testing
        defaultContext.js
        index.test.js

テスト実行

npm test

f:id:contemporarycuz:20190716234932p:plain

無事、テスト実行することができました。

次回は一歩進んで、入出力Bindingのモック作成あたりに触れようかなと。

一部妙にわかりにくい部分について

その①:HttpTriggerとTimerTriggerのテストがごっちゃになって書かれている。

以下の手順の時点では
「HttpTriggerとTimerTriggerのFunctionに対するテストを実施します」
とも言われていないし、
そもそもFunctionすら作っていません。
今何をしようとしているのか全く見えないという状況に陥ります。 f:id:contemporarycuz:20190717000119p:plain

実はここら辺のことはC#を用いた単体テストの章に書かれていたりします。しかし、Nodeで開発している人はその部分は読まないでしょう。

f:id:contemporarycuz:20190717000435p:plain

その②:ワタシニホンゴワカリマセン的な珍訳

これはMSドキュメントあるあるですが、日本語が意味不明です。 f:id:contemporarycuz:20190717000655p:plain

関数を作成した後、index.test.js という名前の同じフォルダーに新しいファイルを追加

これだけ読むと、「index.test.jsという名前のフォルダ―」に「index.test.jsというファイルを追加する」ように読めてしまいます。
もちろん、優秀な皆さんであれば、コードを見て

const httpFunction = require('./index');

の部分から、どこにindex.test.jsを作るべきかわかるのだと思います。しかし、園児にはちょっと厳しいです。
ちなみに、英語版を読んでもちょっと混乱します(これは僕の英語力不足かも) f:id:contemporarycuz:20190717001056p:plain

[]が修飾される名詞、<>が修飾

正しい読み方
Once the function is created, add [a new file] <in the same folder> <named index.test.js>
in ~ と named ~がそれぞれ a new fileを修飾している

ダメな読み方(混乱する読み方)
Once the function is created, add [a new file] <in [the same folder] <named index.test.js>>
in から後ろが a new fileを修飾している。 named ~ が the same folder を修飾している。

よって、悩んだときはドキュメントを隅々まで読む。英語を読む(読んでも経験上無意味なことが多いけど)ことが重要ですね。