スクールアイドルです

冷やし中華はじめました

NodeでInfratasterっぽいことができるTasteSpoonというNPMモジュールを作った

github.com

動機

Infratasterは素晴らしいGemで、インフラの振る舞いをコードで表現できることはこの上なくありがたい。ただ、使っていると不便に感じるところもいくつかある。

  • RSpecにロックインされる
  • RSpecの大量に存在するマッチャAPIで消耗する
  • RSpec2からRSpec3で構文が変わって非本質的な部分で消耗する
  • RSpec上で併用することの多いServerspecとコンテクストが混ざる
  • RSpecでは待ち合わせの概念が入ると途端にコードがダサくなる

最後の「待ち合わせ」だけ補足すると、これはWebSocketなどの通信が確立することを確かめたい場合が例としてあげられる。infrataster-plugin-socket.ioを作った際、通信が確立できることを確かめるのに、こういうダサいコードを書くことになった。

タイムアウトの概念が存在して、マッチャAPIがシンプルで、それでいてdescribe, context, itの表現力を備えている代替品が欲しいと思ったら、身近にあるではないか。mocha, power-assertと組み合わせて同じようなことができればよいのではと考えた。

ので作った。

TasteSpoonの使い方

インストール

TasteSpoonはすでにNPMにて公開されているので、npm installコマンドから直接インストールできる。テスト実行のために必要なmocha, power-assert, さらにES2015で書くのでespower-babelを一緒にインストールする。

$ npm install tastespoon mocha power-assert espower-babel --save-dev

mocha, power-assertを使うのが嫌でも、Jasmineやchaiなど他のNodeベースのテストツールと組み合わせられるはずなので、ベストと思う組み合わせで使ってほしい。

使い方

ここからは、Infratasterでリバースプロキシのテストをする - クックパッド開発者ブログあたりに目を通していて、Infratasterで何ができるかを把握していること前提で書く。

まずはテスト対象となるサーバを用意しよう。今回はTasteSpoonに最初から備わっているHTTPのテストを考える。とりあえずTasteSpoon.httpの動作を見るということで、ローカルにサーバを立ち上げてそこに接続するテストを書いてみよう。

$ python -m SimpleHTTPServer 8080
import TasteSpoon from "tastespoon"
import assert from "power-assert"

TasteSpoon.define("http", "127.0.0.1")

let server = TasteSpoon.server("http")
describe(server, () => {
  let http = TasteSpoon.http("http://example.com:8080")
  describe(http, () => {
    it("returns 200", () => {
      return http(server).result().then((response) => {
        assert(response.statusCode == 200)
      })
    })
  })
})
$ ./node_modules/.bin/mocha --compilers js:espower-babel/guess http_test.js

example.comへのリクエストはTasteSpoonの内部でhttpサーバとして定義された127.0.0.1へと差し向けられるので、心配は無用である。また、HTTPリクエストの結果はPromiseとして返されるので、.catch()されることが想定されるというテストも書くことができる。

慣れたらDockerを立ち上げて、コンテナ内でNginxを動かしてテストするのも試してみてほしい。

mocha統合モード

どうだろう、元になったInfratasterに構文が近いと感じるだろうか。それとも全く似ていないと感じるだろうか。構文をもう少しだけInfratasterに似せられるような、mocha統合モードも用意した。

import TasteSpoon from "tastespoon"
import assert from "power-assert"

TasteSpoon.define("http", "127.0.0.1")

describe(server("http"), () => {
  describe(http("http://example.com:8080"), () => {
    it("returns 200", () => {
      return this.result().then((response) => {
        assert(response.statusCode == 200)
      })
    })
  })
})
$ ./node_modules/.bin/mocha --compilers js:espower-babel/guess --ui tastespoon/mocha http_test.js

これでいくらか見た目は近くなったが、突如thisが出現するので、JavaScriptの特殊なthisをOO式のthisに変えてしまうAltJSとは相性が悪いので要注意。

次回予告

第一歩の解説は終了したので以下の内容を予定している。

  • 待ち合わせのテストでコードがダサくなるという問題が、TasteSpoonとmochaでどう解決されるか
  • TasteSpoonプラグインの作り方