AngularJS TIPS
AngularJSアプリの単体テストを実施するには?(実行編)
テスティングフレームワーク「Karma+Jasmin」を使って、AngularJSアプリの単体テストを記述して、それをテスト実行するまでの手順を説明する。
別稿1「TIPS:AngularJSアプリの単体テストを実施するには?(準備編)」では、AngularJSアプリの単体テストを実施するための環境として、Karma+Jasmineをインストールする手順を紹介しました。本稿では、この環境を利用して、具体的なテストコードを書いて、実際にテストを実行するまでを解説します。
(1)テスト対象のコード
テスト対象のコードには、別稿2「TIPS:フィルターを自作するには?」で紹介した自作のtrim
フィルターを採用します。別稿2ではtrim.html
ファイルを作成していますが、本稿で説明するテスト用に、/angular_tips/UnitTest/scripts
フォルダー内にtrim.js
ファイルを新規作成し、別稿2のtrim.html
ファイルで示しているJavaScriptコード部分のみをtrim.js
ファイルにコピーしてください。具体的にはリスト1のようになります(コードの詳細は別稿2を参照してください)。なお、今後のTIPSで使い分けるために、今回のサンプルコードではモジュール名を「myApp」から「myApp.filter」に変更しているので注意してください。
angular.module('myApp.filter', [])
// trimフィルターを定義
.filter('trim', function() {
return function(value) {
// 加工対象の値が文字列であるかを判定
if (!angular.isString(value)) {
return value;
}
// 文字列の前後から空白を除去
return value.trim();
};
})
.controller('MyController', ['$scope', function($scope) {
$scope.msg = ' こんにちは、世界! ';
}]);
|
(2)テストスクリプトを準備する
まずは、テストのためのコードを準備します。テストスクリプト(リスト2)は、Karmaの初期化ファイルkarma.conf.js
のfiles
パラメーターで指定したフォルダー(本連載では/spec
)に「~_spec.js」のような名前で保存してください。
1
2
3
|
describe('trimフィルターのテスト', function() {
beforeEach(module('myApp.filter'));
it('文字列の前後から空白を除去', inject(function($filter) {
var msg = ' こんにちは、世界! '; // 引数
var result = 'こんにちは、世界!'; // 期待される結果
// trimフィルターを実行して、結果を検証
var trim = $filter('trim');
expect(trim(msg)).toEqual(result);
}));
});
|
Jasmineでテストスクリプトを記述する場合の基本的な構文を押さえておきます。
まず、テストスクリプト全体を、describe
メソッドでくくります(1)。
[構文]describeメソッド
describe(name, specs)
- name: テストスイートの名前
- specs: テストケースの集合
テストスイートとは、関連するテストをまとめた入れ物のようなものです。具体的な個々のテストケースは、引数specs
(function型)の配下で定義します。
beforeEach
メソッドは、個々のテストを実施する前に呼び出される初期化処理です(2)。ここでは、module
関数を利用して、テスト対象となるtrim
フィルターが属するmyApp.filter
モジュールを登録しておきます。AngularJS標準のng
モジュールや、モック(後日解説)を提供するngMock
モジュールは自動的に有効になりますので、明示的に登録する必要はありません。
ここでは省略していますが、テストの終了処理にはafterEach
メソッドも利用できます。
そして、個々のテストケースを表すのが3のit
メソッドです。ここでは、1つだけテストケースを用意していますが、複数のテストケース(it
メソッド)を列記することも可能です。
[構文]itメソッド
it(name, test)
- name: テストケースの名前
- test: テストの中身
引数test
(function型)にAngularJSのサービスを注入するには、inject
関数を利用します。inject
関数を利用することで、引数と同名のサービスを注入できます(この挙動については、別稿3「TIPS:AngularJSの依存性注入を利用するには?」でも解説しています)。
あとは$filter
メソッドでtrim
サービスを呼び出し、その結果を以下の構文で検証するだけです。
[構文]コードの結果を検証
expect(test_code).matcher(expect)
- test_code: テスト対象のコード(式)
- matcher: 検証メソッド
- expect: 期待する値
この例であれば、trim(msg)
でtrim
フィルターを実行し、(toEqual
メソッドにより)その結果が変数result
の値と等しいことを確認しています。
toEqual
は検証メソッド、アサーションメソッド、あるいはMatcherとも呼ばれ、結果確認のための機能を提供するメソッドの一種です。Jasmineでは、標準で以下のような検証メソッドを用意していますので、時と場合とで使い分けてください。
メソッド | 概要 |
---|---|
toEqual(expect) | 期待値expect と同じ値か |
toBe(expect) | 期待値expect と同じオブジェクトか |
toMatch(regex) | 正規表現regex にマッチするか |
toBeDefined() | 定義済みか |
toBeNull() | nullか |
toBeTruthy() | trueと見なせる値か |
toBeFalsy() | falseと見なせる値か |
toContain(expect) | 期待値expect が配列に含まれているか |
toBeLessThan(compare) | 比較値compare より小さいか |
toBeGreaterThan(compare) | 比較値compare より大きいか |
toBeCloseTo(compare, precision) | 精度precision に丸めた値が比較値compare と同じか |
toThrow() | 例外が発生するか |
否定を表すならば、not
メソッドを併用してください。例えば、以下は「等しくない」ことを確認するためのコードです。
expect(trim(msg)).not.toEqual(result));
|
(3)テストスイートを実行する
準備したテストを実行するには、karma start
コマンドを実行してください。引数には、準備済みの設定ファイルkarma.conf.js
を指定します。
> karma start karma.conf.js
……中略……
Chrome 51.0.2704 (Windows 10 0.0.0): Executed 1 of 1 SUCCESS (0.035 secs / 0.028 secs)
|
テスト環境(本稿では別項1でkarma init
コマンド実行時に指定したChrome)が起動し、テストを実行します。テスト実行可能な状態では図1のように[connected]と表示され、実行中には実行状況も表示されます。
テストの結果はコマンドプロンプト(Windows)/ターミナル(Mac)から確認できます。リスト4の最終行を見ると、1つのテストが1つ成功(SUCCESS)したことが見て取れます。
試しに、先ほどのテストスクリプトを、あえてテストが失敗するように修正してみましょう。
expect(trim(msg)).not.toEqual(result));
|
別稿1で作成したkarma.conf.js
ではautoWatch: true
とコードの変更を検知して、テストを再実行する設定になっています。このため、trim_spec.js
ファイルを保存したところでテストが実行され、コマンドプロンプトに以下の結果が反映されるはずです。
Chrome 51.0.2704 (Windows 10 0.0.0) trimフィルターのテスト 文字列の前後から空白を除去 FAILED
Expected 'こんにちは、世界!' not to equal 'こんにちは、世界!'.
at Object.<anonymous> (spec/trim_spec.js:8:27)
at Object.invoke (lib/angular.js:4709:19)
at Object.workFn (lib/angular-mocks.js:3109:20)
Chrome 51.0.2704 (Windows 10 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.05 secs / 0.036 secs)
|
処理対象:Karma+Jasmine カテゴリ:基本
処理対象:フィルタリング カテゴリ:基本
処理対象:カスタムフィルター カテゴリ:基本
API:angular.module カテゴリ:ng(コアモジュール) > function(関数)
API:$injector カテゴリ:auto > service(サービス)
※以下では、本稿の前後を合わせて5回分(第67回~第71回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
67. パラメーター付きのサービスを定義するには?(providerメソッド)
value/service/factoryメソッドに比べてより原始的なproviderメソッドの利用場面を紹介し、使い分け指針をまとめる。またproviderメソッドを使ってサービスを定義する方法を解説する。
68. AngularJSアプリの単体テストを実施するには?(準備編)
AngularJSで一般的に採用されているテスティングフレームワーク「Karma+Jasmin」による単体テスト環境を構築する手順を説明する。
69. 【現在、表示中】≫ AngularJSアプリの単体テストを実施するには?(実行編)
テスティングフレームワーク「Karma+Jasmin」を使って、AngularJSアプリの単体テストを記述して、それをテスト実行するまでの手順を説明する。
70. AngularJSのサービスを単体テストするには?
テスティングフレームワーク「Karma+Jasmin」を使って、AngularJSの「サービス」の単体テストを記述し、それを実行する方法を解説する。
71. AngularJSのコントローラーを単体テストするには?
テスティングフレームワーク「Karma+Jasmin」を使って、AngularJSの「コントローラー」の単体テストを記述し、それを実行する方法を解説する。