yaakaito.org

テスト書きながらTypeScript書ける環境作る

Mocha, Testem, Testing, TypeScript

こんにちは!うきょーです!TypeScriptを書いています。 というのもBackbone、というかJavaScriptでのMVCにガッツリと関わるような状況になってしまったので、 触ってるだけでもわからんとこ多いし、勉強がてらTypeScriptでクローンつくってみるかーという感じです。

そこで、テストを書きたいわけなんですが、TypeScriptのテスト環境の情報が少ないので、手探りでやったところまで記録しておきます。

前回、Mocha + Testem + HTMLCov で基礎的な部分を作ったので、これをベースにします。 なのでこれにTypeScriptのコンパイルやらを乗せていく感じです。

リポジトリはgithubにあるので、見ながら読むと分かりやすいかもしれません。

TypeScriptのコンパイル

TypeScriptのコンパイルには tsc を使うので、npmで入れます。

1
$ npm install -g tsc

tsc でコンパイルする時に、--out オプションを付けると refrence を解決しながらビルドしてくれます。 で、これは流儀的にどうなのかは分からないんですが、これを利用して、コンパイル対象は reference するだけにしました。

1
2
3
// src/backbone.ts
/// <reference path="events.ts" />
/// <reference path="model.ts" />

とりあえずBackbone.EventsBackbone.Modelだけ用意します。

1
2
3
4
5
6
7
8
// src/events.ts
/// <reference path="../vendor/underscore.d.ts" />

module Backbone {
  export class Events {
  // ....
  }
}
1
2
3
4
5
6
// src/model.ts
module Backbone {
  export class Model {
  // ....
  }
}

こういう感じにしておいて、以下のコマンドでビルドします。

1
$ tsc --out backbone.js src/backbone.ts

すると、backbone.jsevents.tsmodels.ts をコンパイルして、依存を解決したものが吐き出されます。 これには underscore は含まれません。

テスト用のビルドとTestem

テストもTypeScriptで書きます。といっても、Mochaを使うので、ほとんどJavaScriptになります。

【追記】d.tsファイルについて

TypeScriptからMocha(JavaScript)を利用する為に、d.tsというファイルが必要になります。 これは安全に既存のJavaScriptをTypeScriptから利用する為の仕組みです。

d.ts ファイル自体はただのテキストで、コードと対して変わらないです。

入手方法としては自分で書く(ある程度自動生成できるっぽい?)、他の人が作ったものを使う、tsdを利用するの3つがあります。 tsdはd.tsのパッケージマネージャみたいなものなんですが、僕はそこまで大げさなものじゃないよなーと思っているので、適当に拾ってきて突っ込んでいます。(あんまりツール的なの増やしたくないのもある。)

DefinitelyTyped を見ると有名どころは大体揃ってるので、ほとんどの場合はここから取得すれば済むと思います。 mochaとchaiはこの中になかったので、僕は下のを使ってます。

mocha.d.ts | chai.d.ts

テストを書く

1
2
3
4
5
6
7
8
9
10
// test/events-test.ts
/// <reference path="../src/events.ts" />
/// <reference path="../vendor/mocha.d.ts" />
/// <reference path="../vendor/chai.d.ts" />

describe('Backbone.Events', function(){
  it('test name', function(){
    // ....
  });
});

test/bootstrap.ts みたいなのを作って、こっちも reference だけにします。(expectのexportだけ書いてます。)

1
2
3
4
/// <reference path="events-tests.ts" />
/// <reference path="../vender/chai.d.ts" />

var expect = chai.expect;

これをビルドします。

1
$ tsc --out backbone.test.js test/bootstrap.ts

これで、全部のreferenceが解決されると、さっきのbackbone.jsの下にテストが丸々ついたようなファイルが生成されます。 これをTestemに食わせます。

1
2
3
4
5
6
7
8
9
// testem.json
{
  "framework" : "mocha",
  "src_files" : [
    "vendor/chai.js",
    "vendor/underscore.js",
    "backbone.test.js"
  ]
}

これでTestemでテストできるようになりました、tsc には watch があるので、これを使って 変更監視 -> 自動コンパイル -> テスト自動実行 というすてき環境を作ります。

1
$ tsc --watch -out backbone.test.js test/bootstrap.js

やったー!これでいける! ・・・と思ったんですが、どうもちゃんと watch が動いていなくて、うまくコンパイルできません。 なのでGuardで代用しました。

ちょっと面倒ですが、すてき環境ができましたね!

カバレッジ

カバレッジをとるときは、backbone.js側にjscoverageをかける必要があるので、別々にコンパイルが必要です。 となると、さっきの test/bootstrap.js なんかで依存関係を解決しながらコンパイルできないので、個別にコンパイルします。 個別にコンパイルしたテストを全部 catで繋げて、all-tests.js みたいなのを作ります。あとは前回を参考にしてください。

Makefileにするとこんな感じ

1
2
3
4
5
6
7
8
9
10
11
compile:
  tsc --out backbone.js src/backbone.ts

compile-test:
  tsc test/*.ts
  cat test/*.js > all-tests.js
  rm test/*.js

cover: compile compile-test
  jscoverage backbone.js backbone.cover.js
  mocha-phantomjs -R json-cov cover-runner.html | json2htmlcov > cover.html

とりあえず

こんな感じで一旦は不満なく開発できる環境ができました。

TypeScriptまだ勝手がよく分かってないので、コードはあんまり見ないでーーー^ー^

あと、Backboneの移植をやってるからか、テスト側がどうしてもほとんどJavaScriptっぽい感じになるんですが、 無駄にコンパイラに怒られてだるいなーと思う事も。(まあ当然なのだが) なんでこういう場合は、テスト側は生のJavaScriptでも十分なのかなーと思った。