Skip to content

Instantly share code, notes, and snippets.

@jsakamoto jsakamoto/01.note.md
Last active Oct 27, 2016

Embed
What would you like to do?
Jasmine による TypeScript/JavaScript 単体テストを実行する環境を作る - Grunt 編

注意 - 本記事の内容は古いです。karma をテストランナーに採用した、「Jasmine による TypeScript/JavaScript 単体テストを実行する環境を作る - karma 編」の採用をご検討ください。

基本ステップ

OS 環境の整備

  1. node.js をインストールしておく (Windows ならここからインストーラをダウンロード)
  2. > npm istall -g grunt-cli で、システムグローバルに grunt-cli をインストール

プロジェクトごとの環境構築

  1. 作業フォルダ(プロジェクトフォルダ)に移動
  2. > npm init で作業場所を準備、package.json を生成
  3. > npm install grunt --save-dev./node_modules 以下に grunt をインストール
  4. > npm install grunt-contrib-jasmine --save-dev./node_modules 以下に grunt-contrib-jasmine をインストール
  5. ./Gruntfile.js を書き上げる
  6. Gruntfile.js 内で指定したとおりのパス及びファイル名に合致するように、Jasmine フレームワークに基づく単体テストコードを TypeScript 又は JavaSccript で記述。TypeScript で記述した場合は JavaScript へのコンパイルを済ませる。

以上で環境構築完了。
> grunt test を実行すると、Gruntfile.js 内の記述に従って、.js ファイルをロードしてテストが実行されるようになる。

なお、プロジェクト構成としては、jasmine.js のインストールは不要
ただし TypeScript でテストコードを書く場合は、TypeScript コンパイルのために、型定義ファイル jasmine.d.ts はインストールしておく必要がある。

何が起きてるか?

npm install grunt によって、プロジェクトフォルダ上で grunt コマンドが実行できるようになる。
grunt コマンドは、./Gruntfile.js を読み込み、そこに記述されている "タスク" を実行する。

npm install grunt-contrib-jasmine によって、grunt のタスクとして Jasmine による単体テスト実行を行う "jasmine" タスクが使えるようになる。
また、grunt-contrib-jasmine のインストールによって、./node_modules フォルダ以下に、jasmine フレームワーク本体である jasmine.js はもちろんのこと、"ヘッドレスブラウザ" である "PhantomJS" もインストールされる。

grunt の jasmine タスクが実行されると、以下のような動作になる。

  1. jasmine タスクは、Gruntfile.js 内の指定に従って、jasmine.js を含むテスト実行に必要な .js ファイルを <script> タグで読み込むよう記述したテストランナー HTML ファイルを、プロジェクトフォルダに自動生成する。
  2. こうして生成したテストランナー HTML を、PhantomJS に読み込ませることでテスト実行を行う

補足

Gruntfile.js 内に記述できる、grunt-contrib-jasmine による Jasmine タスクに対するオプション指定について詳しくは、下記ドキュメントを参照。

https://github.com/gruntjs/grunt-contrib-jasmine#options

ソース管理について

./node_modules フォルダはソース管理から除外する(ソース管理に Git を使用しているのであれば .gitignore ファイルに node_modules/ の1行を書き加えることになるだろう)。

package.json はソース管理に登録しておく。

こうしてコミットされたソースコードを、空の作業フォルダ状態から新たにソース取得して開発を開始する場合は、いちどはじめに npm install をコマンドプロンプトから実行すること。

そうすることで、npm コマンドは package.json を読み取って、必要な Node パッケージをダウンロードしてきて ./node_modules フォルダを復元する。

Visual Studio 上での開発作業と統合

基礎編

手順1. 外部ツールコマンドとして "grunt test" を登録

  1. Visual Studio を起動して、メニューから [Tools]-[External Tools...] を選び、[External Tools] ダイアログを開く。
  2. [Add] をクリックして新たな外部ツール登録を始める。
  3. 以下のとおり記入して [OK] をクリックして登録完了。このとき、外部ツールの一覧上、何番目の登録になったかを覚えておく。
入力項目 入力内容
Title run jasmine
Command cmd.exe
Arguments /c grunt test
Initial Directory $(SolutionDir)

手順2. 登録した外部ツールコマンドに、キーボードショートカットを割り当てる

  1. 次に Visual Studio のメニューから [Tools]-[Options...] を選び、[Options] ダイアログを開く。
  2. [Options] ダイアログで [Environment]-[Keyboard] カテゴリを開く。
  3. [Show command contains:] に "Tools.ExternalCommand" と入力してコマンド一覧を絞り込み。
  4. そして、先に外部ツール登録した "run jasmine" コマンドの順番に該当する "Tools.ExternalCommand~" を選択 (例: "run jasmine" コマンドを、外部ツール一覧上3番目に登録したのであれば、"Tools.ExternalCommand3" を選択 )
  5. 続けて [Press shortcut keys:] の欄にフォーカスを移動。そしてキーボードから、Ctrl+R, Ctrl+J と2ストロークを打鍵。”Ctrl+R, Ctrl+J" と表示されていることを確認して [OK] をクリック。

結果

以上の Visual Studio の設定を済ませておくと、以後、Ctrl + R, Ctrl +J の 2ストロークのキーボードショートカットを打鍵するだけで、コマンドプロンプトが別途開いて、grun test コマンドが実行されるようになる。

つまり、テスト対象やテストコードを編集して Ctrl + S で保存(※)したら、続けて Ctrl + R, Ctrl + J を打鍵するだけで即座にテストを実行することができるようになる。

※ Visual Studio の既定の構成であれば、.ts の保存時に .js へのコンパイルも同時実行される
※上記の記載では「Crl+R, Ctrl+J」のコンビネーションによるキーボードショートカットを設定するよう記載しているが、このキー割り当ては各自の好みのキーを割り当てることで差支えない。ちなみに「Ctrl+R, Ctrl+J」の割り当ての由来は、「Run Jasmine」を想起させることから。

拡張編

先に説明した [External Tools...] ダイアログを再度開き、"run jusmine" コマンドの設定にて、[Use Output window] のチェックを On にして [OK] で登録更新しておくと、"run jusmine" コマンド実行時に、別のコマンドプロンプトウィンドウが開くのではなく、Visua Studio の出力ウィンドウにテスト実行結果の標準出力が表示されるようになる。

しかし、実際にやってみると以下の2点の不具合がある。

  1. コンソール表示時の色指定の制御コードが表示されてしまう (Visual Studio 出力ウィンドウではカラー表示はできない)。
  2. テストの成功/失敗のインジケータ文字や、日本語の出力 (スペック名なども含む) が文字化けてしまう。

この二点は以下の手順で解消する。

手順1. grunt にカラー表示をやめさせる

grunt コマンドには --no-color スイッチが用意されている。このスイッチを指定すれば色指定の制御コードが標準出力に出力されなくなる。

Visual Studio の [External Tools] ダイアログの設定上、以下のように設定変更すればよい。

入力項目 入力内容
Arguments /c grunt test --no-color

手順2. iconv コマンドを使って grunt の標準出力の文字コードを UTF-16 に変換する

文字化けの原因は、grunt によるテスト実行の標準出力が、UTF-8 でエンコードされていることによるものである (Visual Studio では、出力ウィンドウへのリダイレクトは、ASCII か UTF-16LE のいずれかのみが想定されている)。

そこで、iconv コマンドをパイプで使い、grunt コマンドの標準出力の内容を UTF-8 から UTF-16LE に変換してから、Visual Studio で受け取るようにする。

iconv コマンドは、このような文字コード変換に利用できるコマンド。
Windows OS 環境における iconv コマンドは OS 標準では搭載されておらず、別途インターネット上などから入手する必要がある。
幸い、git がインストールされていれば同時にインストールされているはず。

これを前提に、Visual Studio の [External Tools] ダイアログの設定上、以下のように設定変更すればよい。

入力項目 入力内容
Arguments /c grunt test --no-color | iconv -f utf-8 -t utf-16le

さらに [Treat output as Unicode] のチェックを On にしておくこと。

※上記の設定例は iconv コマンドに PATH が通っている場合の例。もし PATH が通っていない、すなわち任意のカレントディレクトリで iconv を実行できないのであれば、iconv コマンドへのフルパス (例: "C:\Program Files\Git\usr\bin\iconv.exe") で記述してもよい。

以上で「Ctrl+R, Ctrl+J」を打鍵してテストが実行されると、文字化けすることなく、Visual Studio の出力ウィンドウにテスト結果が表示される。

おまけ: テスト結果のインジケータ文字が見にくい場合の対処

最初に注意: 汚いハックなので、お勧めするわけではない。

以上の環境構築で、Visual Stuio 上でも快適に jasmine ベースの単体テストを実践できるようになるが、表示上、少々気になるところがある。

それはテストの成功を示すインジケータ文字であるチェックマークが、Visual Studio の出力ウィンドウ上、√記号のように見え、見にくいこと。

このテスト成否を示すインジケータ文字を変更するには、以下の手順で grunt-contrib-jasmine を直接書き換えてしまうという荒業がある。

  1. .\node_modules\grunt-contrib-jasmine\tasks\jasmine.js をエディタで開く。
  2. バージョンにも依ると思うが、50行目あたりに、Windows OS であればの条件判断の中、symbols = { ... } のオブジェクト定義がある。ここの、check, error が、テストの成功/失敗時に表示するインジケータ文字列なので、これを "S" と "F" などの ASCII 文字列に書き換えてしまう。

幸い、この魔改造は、ソース管理を経由して他のメンバーに伝播することはないため、この改造に起因する何か問題が起きても、被害はこの魔改造を施した本人にのみ発生する...はず。

将来構想

  1. 先述のような汚いハックをせずとも、Gruntfile.js 内に記載する grunt-contrib-jasmine に対するオプション指定にて、成功/失敗のインジケータ文字を上書き変更できるように、grunt-contrib-jasmine を fork & commit & pull request する
  2. summary オプションを true に設定しておいた際、テスト失敗時にスタックトレースとして .js ファイルのファイル名と行番号が表示される。これを Visual Studio の出力ウィンドウ上でのダブルクリックで該当箇所へのジャンプができる書式で出力するオプションを設けるよう、grunt-contrib-jasmine を fork & commit & pull request する
  3. 上記の 2 の件をさらに拡張し、ソースマップがあるならば、.js のファイル名と行番号ではなく、そのコンパイル元となった .ts ファイルの名前と行番号を表示できるよう、grunt-contrib-jasmine を fork & commit & pull request する
// Gruntfile.js の記述例
module.exports = function(grunt) {
"use strict";
grunt.initConfig({
pkg: grunt.file.readJSON("package.json"),
jasmine: {
// ここに何が記述できるか/どう影響するのかについては、下記のドキュメントを参照。
// https://github.com/gruntjs/grunt-contrib-jasmine#options
all: {
src: ['*/*.js', '*/models/**/*.js'],
options: {
display: 'full',
summary: false,
keepRunner: true,
vendor: [
'*/Scripts/angular.js'
],
specs: '**/_spec/**/*.spec.js',
},
},
},
});
grunt.loadNpmTasks('grunt-contrib-jasmine');
grunt.registerTask('test', ['jasmine']);
grunt.registerTask("default", []);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.