2015/04/20

TypeScript+Jasmineでテスト駆動開発(ビヘイビア駆動開発)をする

膨大なユニットテストを手動でやりたくないし、リグレッションテスト(回帰テスト)も面倒で、テストの自動化をしたい。

ということで、JavaScriptのテストフレームワーク「Jasmine」をつかったテスト駆動開発(ビヘイビア駆動開発)をやってみた。


開発環境と各種バージョンは、以下の通り。
  • Visual Studio Community 2013
  • TypeScript
  • Jasmine 2.2(現時点での最新版)

追記:2015/06/07
bowerやtsdを使うともっと簡単にJasmineとその型定義ファイルをダウンロードすることができる。
詳しくは、以下のエントリで。


Jasmine の導入


Visual StudioのNuGetからもインストールできるけど、ディレクトリが変に作られてしまうので、GitHubからダウンロードする。
※ 私の環境では、scriptフォルダ直下に"jasmine.js"などが作られ、contentフォルダに"jasmine.css"が作られた。

上記リンクのdistディレクトリからダウンロードする。
※ 現時点の最新版は「jasmine-standalone-2.2.0.zip」

GitHubから特定のファイルをダウンロードする方法は、SVNを使えばできるらしいが、ここではリポジトリトップの「Download ZIP」からダウンロードする。

ダウンロードしたZIPファイルの「dist」フォルダの中にある「jasmine-standalone-2.2.0.zip」を展開する。

│  MIT.LICENSE
│  SpecRunner.html
│
├─lib
│  └─jasmine-2.2.0
│          boot.js
│          console.js
│          jasmine-html.js
│          jasmine.css
│          jasmine.js
│          jasmine_favicon.png
│
├─spec
│      PlayerSpec.js
│      SpecHelper.js
│
└─src
        Player.js
        Song.js

この中で必要なのは、「lib\jasmine-2.2.0」配下のみ。
specフォルダやsrcフォルダ配下のファイルは、サンプルのため必要ない。
SpecRunner.htmlはテストのテストのサンプルなので、書き換えて使うのもOK。



Jasmine の型定義ファイルのダウンロード


NuGetから「jasmine」で検索し、「jasmine.TypeScript.DefinitelyTyped」をインストールする。
検索時に「並べ替え基準」を"発行日"にすると上の方にでてくる。(現時点では)



SpecRunnerの作成


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Jasmine Spec Runner v2.2.0</title>
    <link rel="shortcut icon" type="image/png" href="../scripts/jasmine-2.2.0/jasmine_favicon.png">
    <link rel="stylesheet" href="../scripts/jasmine-2.2.0/jasmine.css">
    <script src="../scripts/jasmine-2.2.0/jasmine.js"></script>
    <script src="../scripts/jasmine-2.2.0/jasmine-html.js"></script>
    <script src="../scripts/jasmine-2.2.0/boot.js"></script>

    <!-- include source files here... -->
    <script src="../FizzBuzz.js"></script>

    <!-- include spec files here... -->
    <script src="../test/specifications.js"></script>
</head>
<body>
</body>
</html>
SpecRunner.htmlの13行目(include source files here)にテストしたいコードを指定する。
16行目(include spec files here)にテストコードを指定する。

このとき参照するファイルは、tsファイルではなく、コンパイル後のjsファイルを指定する。



テストコードの作成


まずテストコードを作成する。
// specifications.ts
/// <reference path="../scripts/typings/jasmine/jasmine.d.ts" />

describe('FizzBuzzのgenerateメソッドは',() => {
    beforeEach(() => {
        this.fizzbuzz = new FizzBuzz();
        this.FIZZ = 'FIZZ';
        this.BUZZ = 'BUZZ';
        this.FIZZ_BUZZ = 'FIZZ_BUZZ';
    });

    it('1を渡すと、1が返ってくる',() => {
        var result = this.fizzbuzz.generate(1);
        expect(result).toBe(1);
    });
    it('2を渡すと、2が返ってくる',() => {
        var result = this.fizzbuzz.generate(2);
        expect(result).toBe(2);
    });
    it('3を渡すと、Fizzが返ってくる',() => {
        var result = this.fizzbuzz.generate(3);
        expect(result).toBe(this.FIZZ);
    });
    it('4を渡すと、4が返ってくる',() => {
        var result = this.fizzbuzz.generate(4);
        expect(result).toBe(4);
    });
    it('5を渡すと、Buzzが返ってくる',() => {
        var result = this.fizzbuzz.generate(5);
        expect(result).toBe(this.BUZZ);
    });
    it('6を渡すと、Fizzが返ってくる',() => {
        var result = this.fizzbuzz.generate(6);
        expect(result).toBe(this.FIZZ);
    });
    it('10を渡すと、Buzzが返ってくる',() => {
        var result = this.fizzbuzz.generate(10);
        expect(result).toBe(this.BUZZ);
    });
    it('15を渡すと、FizzBuzzが返ってくる',() => {
        var result = this.fizzbuzz.generate(15);
        expect(result).toBe(this.FIZZ_BUZZ);
    });
    it('30を渡すと、FizzBuzzが返ってくる',() => {
        var result = this.fizzbuzz.generate(30);
        expect(result).toBe(this.FIZZ_BUZZ);
    });
});


この状態でSpecRunner.htmlを開くと、以下のようになる。



テストしたいコードを書く


ちゃんとテストされているか確認するために、わざとエラーがでるパターンを書いてみた。
// FizzBuzz.ts
class FizzBuzz {
    generate(input: number) {
        return input;
    }
}


この状態でSpecRunner.htmlを開くと、以下のようになる。
いくつかのテストで失敗していることがわかる。


次に、すべてのスペック(テスト)を通るようなコードを書く。
// FizzBuzz.ts
class FizzBuzz {
    generate(input: number): any {
        if (input % 3 == 0 && input % 5 == 0) {
            return 'FizzBuzz';
        } else if (input % 3 == 0) {
            return 'Fizz';
        } else if (input % 5 == 0) {
            return 'Buzz';
        } else {
            return input;
        }
    }
}

この状態でSpecRunner.htmlを開くと、以下のようになる。



おまけ:フォルダ階層


Jasmineを使うときに一番悩んだのがこのフォルダ階層。
特に正解はないが、どのフォルダにどのファイルを配置すれば良いのかわからなかった。

そこで、GitHubでいろんなリポジトリを覗いて、以下の階層に落ち着いた。
※ bowerとかのパッケージマネージャとか使うと変わってくるかもしれないけど。


ちなみに、「TypeScript実践プログラミング」の「第9章 テストの自動化」でTypeScriptでのJasmineの使い方が説明されている。



以上

written by @bc_rikko

0 件のコメント :

コメントを投稿