Skip to content

Instantly share code, notes, and snippets.

@jsakamoto
Last active November 18, 2018 04:15
Show Gist options
  • Save jsakamoto/e4a957821216c38cdb7e9e20ba17e569 to your computer and use it in GitHub Desktop.
Save jsakamoto/e4a957821216c38cdb7e9e20ba17e569 to your computer and use it in GitHub Desktop.
Jasmine による TypeScript/JavaScript 単体テストを実行する環境を作る - karma 編

基本ステップ

OS 環境の整備

  1. node.js をインストールしておく (Windows ならここからインストーラをダウンロード)

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

  1. 作業フォルダ(プロジェクトフォルダ)に移動。
  2. > npm init で作業場所を準備、package.json を生成。
  3. 続けて、以下の npm パッケージを ./node_modules 以下にインストール
  • テストランナー「karma」コマンド本体
  • karma が、ヘッドレスブラウザ「PhantomJS」でテスト実行するためのランチャー
    (PhantomJS それ自体も、依存性解決の一環で同時インストールされる)
  • karma が、テストフレームワーク「Jasmine」を扱うためのアドイン
  • karma が、コンパイル前の AltJS 言語ソース行を特定できるアドイン
  • テスト実行に必要となるテストフレームワーク「Jasmine」本体
> npm install karma --save-dev
> npm install karma-phantomjs-launcher --save-dev
> npm install karma-jasmine --save-dev
> npm install karma-sourcemap-loader --save-dev
> npm install jasmine-core --save-dev
  1. > .\node_modules\.bin\karma init を実行し、karma に対する構成ファイル karma.conf.js を生成。
    karma コマンドは、コンソール上で対話方式でどのような構成にするか尋ねてくるので、下図要領で回答。
    karma init
  2. さらに、こうして生成した karma.conf.js をテキストエディタで編集し、下記内容となるよう構成を調整して保存する。
module.exports = function(config) {
  config.set({
    // テストフレームワークに Jasmine を使う指定。
    frameworks: ['jasmine'],

    // テスト実行環境に読み込む JavaScript ファイルの指定。
    // 下記はとあるプロジェクトのフォルダ構成に基づく例。
    files: [
        // vendor
        'Scripts/jquery-2.2.4.js',
        'Scripts/angular.js',
        'Scripts/angular-mocks.js',
        // src
        'bundle.js',
        // spec
        '_spec/**/*Spec.js'
    ],
    
    // ソースマップを読み込んで、コンパイル前の AltJS ソースコード行を特定する指定。
    preprocessors: {
      '**/*.js': ['sourcemap']
    },

    // Visual Studio の出力ウィンドウで表示するため、
    // テスト進捗状況の表示は progress ではなく dots を指定。
    reporters: ['dots'],

    // Visual Studio の出力ウィンドウで表示するため、
    // コンソール出力はモノクロを指定。
    colors: false,

    // テスト実行に使うブラウザは PhantomJS を指定。
    browsers: ['PhantomJS'],

    // テストを実行するごとに処理終了させる指定。
    singleRun: true
  })
}
  1. あとは、karma.conf.js 内の files プロパティに指定したとおりのパス及びファイル名に合致するように、Jasmine フレームワークに基づく単体テストコードを TypeScript 又は JavaScript で記述。
    TypeScript で記述した場合は JavaScript へのコンパイルを済ませる (ソースマップ .js.map も生成するようにしておくとなおよい)。

以上で環境構築完了。

> .\node_modules\.bin\karma start karma.conf.js を実行すると、karma.conf.js 内の記述に従って、.js ファイルをロードしてテストが実行されるようになる。

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

何が起きてるか?

> .\node_modules\.bin\karma start karma.conf.js が実行されると、以下のような動作になる。

  1. karma コマンドは karma.conf.js を読み込み、これに記載の構成に従ってヘッドレスブラウザ "PhantomJS" を起動。jasmine.js や karma.conf.js の files プロパティで指定したファイルをはじめとした、テスト実行に必要なコンテンツ類を PhantomJS に読み込ませる。
  2. これらコンテンツを読み込んだ PhantomJS は、そのコンテンツの解釈と実行によって、結果として Jasmine ベースのテストコードを実行することになる。
  3. karma は PhantomJS からの出力を拾い、レポートにまとめあげて表示する。

ソース管理について

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

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

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

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

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

基礎編

手順1. package.json を編集し、"npm test" でテスト実行されるようにする

package.json をテキストエディタで編集し、scripts.test の項目を下記のように書き換えて保存する。

{
  ...
  "scripts": {
    "test": "karma --silent --no-color start karma.conf.js"
  },
  ...
}

これでプロジェクトフォルダ上で「npm test」と実行することで、karma によるテスト実行が行われるようになる。

直接 karma コマンドを各種引数とともに実行してもよいのだが、npm を挟むことで以下の利点が得られる。

  1. node_modules フォルダ以下にインストールされた karma コマンドは既定では PATH が通っていないので実行にあたってのタイプ数多く面倒。
    npm なら PATH が通っているので「npm test」とだけ打鍵すればよい。
  2. 他の方式や旧来、あるいは今後将来、いろいろなテスト実行環境がプロジェクト違いで散在する可能性がある。
    しかしすべて「npm run」でテスト実行するようにしておけば、この節で解説している Visual Studio 統合がどのプロジェクトでも機能することになる。
    (テスト実行環境の違い、テスト実行コマンドの違いを、package.json で吸収する形)

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

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

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

  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ストロークのキーボードショートカットを打鍵するだけで、コマンドプロンプトが別途開いて、npm 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. npm にカラー表示をやめさせる

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

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

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

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

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

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

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

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

入力項目 入力内容
Arguments /c npm test --silent --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 の出力ウィンドウにテスト結果が表示される。

将来構想

  • テスト失敗時にスタックトレースとして .js ファイルのファイル名と行番号が表示される (ソースを TypeScript で記述していて、ソースマップもある場合は、もとの TypeScript ソース行も表示される)。
    これを Visual Studio の出力ウィンドウ上でのダブルクリックで該当箇所へのジャンプができる書式で出力するオプションを設ける
// Karma configuration
// Generated on Thu Oct 27 2016 18:44:30 GMT+0900 (Tokyo Standard Time)
module.exports = function (config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
// vendor
//'Scripts/jquery-2.2.4.js',
//'Scripts/angular.js',
//'Scripts/angular-mocks.js',
// src
// 'bundle.js',
//'app.js',
// spec
'_spec/**/*Spec.js'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'**/*.js': ['sourcemap']
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['dots'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: false,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_ERROR,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
})
}
{
"name": "jasmine-on-karma",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "karma --silent --no-color start karma.conf.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"jasmine-core": "^2.5.2",
"karma": "^1.3.0",
"karma-jasmine": "^1.0.2",
"karma-phantomjs-launcher": "^1.0.2",
"karma-sourcemap-loader": "^0.3.7"
}
}
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": true,
"sourceMap": true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment