俺、サービス売って家買うんだ

Swift, Kotlin, Vue.js, 統計, GCP / このペースで作ってればいつか2-3億で売れるのがポっと出来るんじゃなかろうか

mocha + should.jsでNode.jsのテストを書く

f:id:ie-kau:20160510011026p:plain


また今度詳細は書こうと思うんですけど今年もGWにこのブログの著者二人で、都内のコワーキングスペースにこもって開発していました。
最近の記事を読んでくださってた方だと察しはつくと思いますが、FacebookのMessenger Platformを利用したbotです。

で、現在審査中なのでまだ紹介はできません。ごめんなさいorz
(先日テストユーザーからアクセスがあったのですが、うまい具合に使われてなかったので審査落ちの可能性大きいですが....)

そのbotを有用になものにするにあたって、多くの条件を無理やり仕込んだ結果、条件の追加・削除時に、追加してはバグ、削除してはバグ、どうにもならない状況に陥ってしまいました。思い切ったリファクタリングもしづらい状態になったので動作が安定してきたところで腹を括って複雑な箇所のテストを一通り揃えることにしました。

テストを書きながら開発される方が多いと思いますが、僕は個人製作ぐらいだと普段はテストを書かないんですよね。その弊害が今回顕著に出てしまいました。。

で、仕事でRailsを使ってるのでRspecは割りと慣れているのですが、今回利用したNode.jsでテストは書いたことがなく初めてmocha + should.jsを利用したので今回はその覚書をしておこうと思います。

テスト環境

mocha
JavaScriptの単体テスト向けテストフレームワークです。同期のテストも非同期のテストも簡単に行えます。
ただしアサーション機能は持っていません。
Mocha - the fun, simple, flexible JavaScript test framework

should.js
mochaで動作するアサーションライブラリ。
ぶっちゃけテストを書ければなんでも良かったので一番上にあったものを選択 。
GitHub - shouldjs/should.js: BDD style assertions for node.js -- test framework agnostic

テストの準備

インストール

npm install -g mocha
npm install should --save-dev

テストファイル作成
デフォルトだとこうする

 mkdir test
 vi test/test.js

自分の場合はこんな感じ

test
└── models
    ├── item.test.js
    └── message.test.js

テストの記述

この辺はあんまりRspecと変わらない

const should = require('should');
const conditionManager = require('../../libs/condition_manager');

describe('getScore', () => {
  it('nullが入力された場合スコアは0を返す', () => {
    conditionManager
      .getScore(null)
      .should.equal(0);
  });
});

せっかくJavaScriptなので設定データから動的にテストを生成して楽をする

const should = require('should');
const config = require('../../config');
const conditionManager = require('../../libs/condition_manager');

describe('getScore', () => {
  describe('getScoreが正しいスコアを返すか', () => {
    Object
      .keys(config.RELATION)
      .map((key) => {
        return [config.RELATION[key], key];
      })
      .forEach((elm) => {
        it(elm[0], () => {
          conditionManager
            .getScore(config.RELATION[elm[1]])
            .should.equal(config.CONDITION[elm[1]]);
        });
    });
  });
});

テストの実行

後はシンプルに実行するのみ

mocha --recursive # 再帰的に走らせるオプション付き

テストが通ると
f:id:ie-kau:20160510010625p:plain:w400

1000円区切りで,を入れる関数をわざと落としてみた例

f:id:ie-kau:20160510010634p:plain:w400

まとめ

bot自体は完全に力技になってますが、

  • ユーザーの入力に対して意味を持った返答
  • ユーザーの複数の発言の流れを記憶した上で、それらの発言をキーとした数多の条件に対応する返答

などを実装しつつbotを書き上げるにはテストは不可欠でした。
そのためこれぐらい気楽にテストがかけるエコシステムが揃っていると非常に助かりますね。

作ったものはまだ審査中なのでなんとか通して使ってもらうぞ!
乞うご期待(ง `ω´)۶オラッオラッ