testling-ciとtravis-ciでクライアントサイドもサーバサイドもテストを実行する

まえがき

NHK番組表APIjavascript版を作りました。

NHKの番組表APIが発表されてて、皆思い思いに好きな言語で実装されていくのを見てました。

Golang : https://github.com/mattn/go-nhk

Scala : https://github.com/seratch/nhk4s

Perl : https://github.com/moznion/WWW-NHKProgram-API

Python : https://github.com/drillbits/nhk-api

Ruby : https://github.com/mitukiii/nhk_program-for-ruby

Emacs : https://github.com/gongo/emacs-nhk-program

Titanium : https://github.com/h5y1m141/TiNHKProgram

それのNode.js版ってよく見ると無いなと思ったんで作ったんですが、これは考えてみればbrowserifyでクライアントサイドでも使えるライブラリとして公開するチャンスだと思ってクライアントサイドjavascriptとしてもサーバーサイドのjavascriptとしても動作するハイブリッドのNHK番組表クライアントを作ってみました。

Node.js : https://github.com/yosuke-furukawa/nhk_api.js

npm : https://www.npmjs.org/package/nhk_api

bower : http://bower.io/search/?q=nhk_api

Getting Started

node.jsの場合
$ npm install nhk_api
browserから使う場合
$ bower install nhk_api

installしたらbowerをscriptで読めるようにする。

<!-- in browser -->
<script src="components/nhk_api/client/nhk_api.js"></script>

使い方

var NHK = require("nhk_api");

// KEYを設定してください。
var nhk = new NHK("YOUR_API_KEY");
var callback = function(err, result) {
  console.log(JSON.stringify(result));
};

//  nhk list api
nhk.list.get("130", "g1", callback);
nhk.list.get("東京", "NHK総合1", callback);
nhk.list.get("東京", "NHK総合1", "tomorrow", callback);
// nhk genre api
nhk.genre.get("130", "g1", callback);
nhk.genre.get("東京", "NHK総合1", callback);
nhk.genre.get("東京", "NHK総合1", "tomorrow", callback);
// nhk info api
nhk.info.get("130", "g1", "123456789", callback);
// nhk now on air api
nhk.now.get("130", "g1", callback);

本題

さて、これは単に作ったというだけで本題はここからなんですが、Node.js版、というかサーバーサイドはtravisとかあって簡単にバージョンを跨いだテストが出来ますよね。

クライアントサイドの場合はどうでしょう。ブラウザ間のバージョンを跨いだテストを実施したいところです。せっかくbrowserifyを使ってサーバーサイドとクライアントサイド両方共同じ使い方で使えているので、testling-ciというサイトを使ってブラウザ間のテストを実行しましょう。

testling-ciでテストを実行すると以下の様なバッジが生成されて見れるようになります。

どのブラウザでサポートされているのか一目瞭然で分かりやすいですね。

ちょっと前にsubstackが公開していた記事があって、それを見るとやり方が書いてあります。ちょっと長いんですが最後までお付き合いをお願いします。

簡単にやり方を紹介していきます。

テストツールのインストール

以下のツールをインストールしておきます。

// phantomjs は必須、そうでなくても何らかのヘッドレスブラウザがないとtestlingが動かない
$ brew install phantomjs
$ npm install browserify tape testling -g

browserifyはサーバーサイドのコードをクライアントでも使えるようにしてくれるツールですね。

tapeはtapが喋れるテストライブラリです、mochaでもいいんですが、substackが最近issue全部クローズした!!って騒いでたので使ってみました。

testlingはtestling-ciの動作確認ができるCLIツールです。インストールが終わったら準備完了。

まずはtapeを使ってテストを書いて、nodeのテストを実行します。

こんな感じのファイルをtestフォルダ以下に用意します。

var NHK = require('../index');
// tapeをrequire
var test = require('tape');

// 時間用ライブラリを利用
var moment = require('moment-timezone');

// this apikey for test
var apikey = process.env.NHK_API_KEY || "123456789";

// genreのurlがあっているかどうかテスト
test(' genre url ', function (t) {
  var nhk = new NHK(apikey);
  var url = nhk.genre.createUrl("130", "g1", "0000");
  var date = moment().tz("Asia/Tokyo").format("YYYY-MM-DD");
  // nhkのgenre apiのurlと合致することを期待
  var expected = "http://api.nhk.or.jp/v1/pg/genre/130/g1/0000/" + date + ".json?key=" + apikey;

  // t.equalで比較、第一引数が actual、第二引数が expected、第三引数がコメント
  t.equal(url, expected, "url is same");
  // t.endでテストが終了される。
  // t.endを呼ぶのは必須、非同期テストの場合はこっちのほうが嬉しい。
  t.end();

  //ちなむとt.planっていうメソッドがあって、それをcallすると指定回数のassetチェックが終わると自動でendされる仕組みになる。
  // t.plan(1);
});

test(' genre url to specify keyword ', function (t) {
  var nhk = new NHK(apikey);
  // 日本語でもgenre生成されるんですよ
  var url = nhk.genre.createUrl("東京", "NHK総合1", "0000");
  var date = moment().tz("Asia/Tokyo").format("YYYY-MM-DD");
  var expected = "http://api.nhk.or.jp/v1/pg/genre/130/g1/0000/" + date + ".json?key=" + apikey;
  t.equal(url, expected, "url is same");
  t.end();
});

テストの実行は簡単で

$ tape test/genre.js

で実行できます。

TAP version 13
# genre url
ok 1 url is same
# genre url to specify keyword
ok 2 url is same
# genre url today
ok 3 url is today
# genre url tomorrow
ok 4 url is tomorrow
# get genre url
ok 5 error is not found
ok 6 msg is truthy
ok 7 msg.list is truthy
ok 8 msg.list.g1 is truthy

1..8
# tests 8
# pass 8

# ok

node-tapをインストールしているならtapコマンドが使えるようになるので、以下の様な感じになります。

$ tap test/genre.js

ok test/genre.js ........................................ 9/9
total ................................................... 9/9

ok 

と、ここまでは普通のNode.jsのテストですね。

testlingを使ってbrowserのテストも実行する。

testlingとbrowserifyを使ってbrowser側のテストも実行しましょう。実行はすごく簡単。

$ browserify test/genre.js | testling

TAP version 13
#  genre url
ok 1 url is same
#  genre url to specify keyword
ok 2 url is same
#  genre url today
ok 3 url is today
#  genre url tomorrow
ok 4 url is tomorrow
#  get genre url
ok 5 error is not found
ok 6 msg is truthy
ok 7 msg.list is truthy
ok 8 msg.list.g1 is truthy

1..8
# tests 8
# pass  8

# ok

ってやるだけですね、これはすごく単純なことしかしてなくて、

  1. browserifyでtestコードをブラウザでも実行できるようにする
  2. testlingからphantomjsを呼び出してそのコードを実行する

ということをやっているだけです。

※phantomjsを入れる前にtestlingを既にインストールしていると、phantomjsを入れてもtestlingがphantomjsを認識してくれない事があります、この場合は ~/.config/browser-launcher/config.json を一旦消してから再実行してみましょう。 

coverageを取る場合

substackが作っているcoverifyっていうツールを使います。

$ browserify -t coverify test/*.js | testling | coverify

...

# /Users/yosuke/Program/nhk-api/lib/base.js: line 53, column 9-28

          console.error(data);
          ^^^^^^^^^^^^^^^^^^^^

# /Users/yosuke/Program/nhk-api/lib/base.js: line 54, column 9-25

          console.error(e);
          ^^^^^^^^^^^^^^^^^

# /Users/yosuke/Program/nhk-api/lib/base.js: line 55, column 9-14

          cb(e);
          ^^^^^^

# /Users/yosuke/Program/nhk-api/lib/base.js: line 59, column 5-10

      cb(e);
      ^^^^^^

# coverage: 860/864 (99.53 %)

コレを使うと通っていないコードとテストのcoverageを取ってくれます。この場合は99.53%カバレッジですね。

tapeとbrowserifyとtestlingでサーバーサイドもクライアントサイドも同じテストコードでテストできるようになりました。ついでにcoverify使うとカバレッジも計測できます。

CIツールで自動テスト

サーバサイドのCIツールはtravisがあるのでそれを使いましょう。以下のサイトが参考になります。

http://d.hatena.ne.jp/hokaccha/20111110/1320910718

クライアントサイドはCIツールとして、testling-ciを使います、これを使うための前準備として、package.jsonに以下のように記述します。

{
  "name": "nhk_api",
  "version": "0.1.1",
  "description": "Node.js client for NHK API",
  "main": "index.js",
  "scripts": {
    "test": "tape test/*.js",
    "build": "browserify -g uglifyify -r ./index.js:nhk_api -o client/nhk_api.js"
  },
  "keywords": [
    "nhk",
    "api"
  ],
  "author": "yosuke furukawa",
  "license": "MIT",
  "dependencies": {},
  "devDependencies": {
    "tape": "~2.10.2",
    "uglifyify": "~1.2.3",
    "browserify": "~3.32.0",
    "moment-timezone": "0.0.3"
  },
  "testling": {
    "files": "test/*.js",
    "browsers": [
      "ie/6..latest",
      "chrome/22..latest",
      "firefox/16..latest",
      "safari/latest",
      "opera/11.0..latest",
      "iphone/6",
      "ipad/6",
      "android-browser/latest"
    ]
  }
}

こんな感じで、testlingプロパティを設定してください。ここにbrowserのどのバージョンをtestling-ciでテストするかを定義します。

設定したら、githubのwebhookページから、http://git.testling.comへのhookを設定してください。

git pushを実行したら、以下のページで実行が確認できます。

https://ci.testling.com/$YOUR_USERNAME_HERE/$YOUR_REPOSITORY_NAME

実際の状況はこちら:https://ci.testling.com/yosuke-furukawa/nhk_api.js

バッジを見る

バッジはこんな感じで手に入ります。

https://ci.testling.com/$YOUR_USERNAME_HERE/$YOUR_REPOSITORY_NAME.png

実際のコード


markdownに貼るならこちら

[![browser support](https://ci.testling.com/$YOUR_USERNAME_HERE/$YOUR_REPOSITORY_NAME.png)
](https://ci.testling.com/$YOUR_USERNAME_HERE/$YOUR_REPOSITORY_NAME)

まとめ

  • NHK番組表APIのサーバサイドでもクライアントサイドでも使えるハイブリッド版を作りました
  • browserifyとtestlingとtapeでクライアントサイドもサーバサイドも同じコードでテストが実行できます
  • testling-ciを使うと各ブラウザ間でテストが実行され、CIが使えます。

browserifyを使うことでサーバサイドもクライアントサイドもほぼ同じコードが使えるようになりました。そのクライアントサイドのテストをするならbrowserifyとtestling-ciの組み合わせは非常に相性が良いです。使っていきましょう。