Angular2 Unit Testing - 準備編

Angular2の実装の方法は記事をよく目にする機会が増えたので、テストについての自分が困らないように調べてみたシリーズ。

今回は準備編。

(注意)Angular 2.0.0-beta.9 をベースに話しています。
E2Eテストはprotractorがそのまま利用できると思うので、ここでのテストはユニットテストの話です。

Angular2 Unit Testing

  1. 準備
  2. 基本
  3. Mock, Spyの基本(TBD)
  4. DOMのテスト
  5. XHRのテスト
  6. Componentのテスト(TBD)
  7. Serviceのテスト(TBD)
  8. Pipeのテスト
  9. Directiveのテスト(TBD)
  10. カバレッジ

準備編

Angular1の場合と同様に、Angular2でもユニットテストを実行する前に少し下準備が必要です。
今回は、Angular1経験者向けに変更点などを紹介します。

サンプルはこちらを参考にしてください。
mitsuruog/angular2-minimum-starter: Minimum starter kit for angular2

Karma+Jasmineの構成はそのまま利用できる

ユニットテストの構成はAngular1と同じ構成です。

  • テストランナー
  • テスティングフレームワーク

Karmaの設定は次のような形です。

karma.conf.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
'use strict';
// Karma configuration

let baseLibs = [
'node_modules/systemjs/dist/system-polyfills.js',
'node_modules/systemjs/dist/system.js',
'node_modules/es6-shim/es6-shim.js',
'node_modules/rxjs/bundles/Rx.js',
'node_modules/angular2/bundles/angular2-polyfills.js',
'node_modules/angular2/bundles/angular2.dev.js',
'node_modules/angular2/bundles/router.dev.js',
'node_modules/angular2/bundles/http.dev.js'
];

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: [
...baseLibs,
'node_modules/angular2/bundles/testing.dev.js',
'karma.shim.js',
{ pattern: 'app/**/*.js', included: false }
],

// 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: {},

// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['mocha'],

// web server port
port: 9876,

// enable / disable colors in the output (reporters and logs)
colors: true,

// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,

// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,

// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],

// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,

// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
})
}

Karmaの設定ファイルのframeworksにてテスティングフレームワークを変更できるので、mochaなど他のものを利用することもできると思います。
(2016-03-10 追記) Angular2内部でJasmineのDefinitelyTypedを参照しているため、Jasmineを使った方が幸せになれる気がします。

karma.shim.jsという見慣れないファイルについては後で説明します。

モジュールロードシステムが独自からsystemjsに変更となった

Angular2で大きく変わった点の一つは、モジュールロードシステムがsystemjsに変更された点です。

Angular1はモジュール名の名前解決による独自のモジュールロードシステムを持っていました。
基本的には<script>タグでロードした外部スクリプトを、Angular上でモジュールとして再ロードすることで利用していました。

Angular2ではsystemjsの設定ファイルにて利用する外部スクリプトを定義して、systemjsを介してモジュールをロードするようになります。
これまではテストランナーでテスト用のファイル一式をロードすれば十分でしたが、間にsystemjsが1枚存在する形になります。

そこで、karma.shim.jsの登場です。

karma.shim.jsとは

karma.shim.jsとは、テストを行う前にsystemjsにてモジュールがロードされていることを保証するために、Karmaとsystemjsの初期化のタイミングを制御する役割をするものです。

karma.shim.jsの処理を大きく分けると次の3ステップでテストを実行しています。

  1. systemjs内にアプリケーションの静的リソースをロード
  2. テスト用のブラウザと接続
  3. Specをロード&テスト実行

refs https://github.com/mitsuruog/angular2-minimum-starter/blob/master/karma.shim.js

サンプルSpecを作成して実行してみる

最後に簡単なSpecを実装してみます。シンプルなAppComponentです。

app.component.ts

1
2
3
4
5
6
7
8
9
10
import {Component, OnInit} from 'angular2/core';

@Component({
selector: 'my-app',
template: `
<h1>Angular2 Minimum Starter Kit</h1>
`

})

export class AppComponent {}

Specを書いてみます。

app.component.spec.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import {
it,
inject,
injectAsync,
beforeEachProviders,
TestComponentBuilder
} from 'angular2/testing';

import {Component, provide} from 'angular2/core';
import {AppComponent} from './app.component';

describe('Test: AppComponent', () => {

beforeEachProviders(() => [
AppComponent
]);

it('AppComponentが存在すること', inject([AppComponent], (testee: AppComponent) => {
expect(testee).toBeDefined();
}));

});

テストを実行してみます。

1
karma start karma.conf.js

テストを実行すると結果が表示されます。

まとめ

モジュールロードシステムがSystemJSに変更されたことで、少し面倒になりましたがこれでAngular1と同様にユニットテストを行う準備ができるはず!!

PR

こちらに初学者のためのMinimum starter kitを作成しましたので、ぜひ利用してください。
(もちろんすぐテストできます!!)

mitsuruog/angular2-minimum-starter: Minimum starter kit for angular2 https://github.com/mitsuruog/angular2-minimum-starter

参考