Angularユニットテスト
ユニットテスト・・・?
クラスやメソッドを対象に動作を保証するもの
進め方
- テスト対象を選定する
- その機能に関してのテスト項目を網羅する
- 実装する
- テストコードのレビュー
- テストをする
- 実装結果に応じてテスト対象の修正等を行う
- テストする
...
基準?
テスト設計技法
テストコードは数行で済むものにしなければならない
1つのテストには1つのアサーション
戒め
- テストを実施するということが目的ではない
- ユニットテストにはある程度の知識、スキルが必須
- テストをしながらテスト対象を改修する体制が必要
- ユニットテストの工数は実装コストの二倍以上
- テストしたから品質が上がるわけではない
- 全てのコードにテストが出来るわけではない
- カバレッジが品質や進捗を指し示すわけではない
- 書いて満足してはいけない
- 結合テストは別途必要
- テストに必ず効果があるわけではない
Angularのテストでは、JavaScriptで使用されているテストツールを使用する。
Angular公式ではJasmine+Karmaの組み合わせでユニットテストを実施することが推奨されている。
Jasmine
JavaScript用のテスティングフレームワーク
Karma
テストランニグツール
上記はAngular用である為、ionic-cliでプロジェクトを作成した場合は導入されていない
ionicプロジェクトにテストツール導入
テスト用のプロジェクト作成
ionic start PROJECT_NAME blank
公式からテストプロジェクトをクローン
git clone https://github.com/ionic-team/ionic-unit-testing-example.git my-project-name
公式のテストサンプルから必要ファイルを持ってくる為、フォルダを開いておく
テストを行いたいプロジェクトを開き必要なモジュールをインストール
cd PROJECT_NAME
npm install --save-dev angular2-template-loader html-loader jasmine jasmine-spec-reporter karma karma-chrome-launcher karma-jasmine karma-jasmine-html-reporter karma-sourcemap-loader karma-webpack karma-coverage-istanbul-reporter istanbul-instrumenter-loader null-loader protractor ts-loader ts-node @types/jasmine @types/node
テストを行いたいプロジェクトのpackage.json
を開きscrip
部分に以下を追加
"test": "karma start ./test-config/karma.conf.js",
"test-ci": "karma start ./test-config/karma.conf.js --single-run",
"test-coverage": "karma start ./test-config/karma.conf.js --coverage",
"e2e": "npm run e2e-update && npm run e2e-test",
"e2e-test": "protractor ./test-config/protractor.conf.js",
"e2e-update": "webdriver-manager update --standalone false --gecko false"
文末のカンマを忘れてはならない
クローンしたプロジェクトから以下ファイルが含まれているtest-config
フォルダをテストを行いたいプロジェクトのルートにコピーする
test-config
>-karma-test-shim.js
>-karma-config.js
>-mocks-ionic.js
>-protractor.conf.js
>-webpack.test.js
e2eテスト用にe2e
フォルダをテストを行いたいプロジェクトのルートにコピーする
e2e
>-app.e2e-spec.ts
>-app.po.ts
>-tsconfig.json
必要なモジュールをインストールする
npm install
テストを試してみる
クローンしてきたサンプルの/src/app
内のapp.component.spec.ts
をテストしたいプロジェクトの/src/app
にコピー
テストを実行
npm run test
other
テストが実行できない場合はクローンしてきたプロジェクトのpackage.jsonのdevDependencies
の値に合わせる
descrive
等が赤線がついている場合は、spec.ts
ファイルに以下を追加する
import {} from 'jasmine';
Jasmineでのテストの書き方
descrive
descrive(name,specs)
name:テストスイートの名前
specs:テストケース
テストコード全体をdescrive
で囲む
テストグループを作成するもの
beforeEach
→テスト実行前の事前準備
afterEach
→テスト実行後の後処理
it
it(name,test)
name:テストケースの名前
test:テスト内容
it
が個々のテストケース
expect
expect(resultValue).matcher(expectValue)
resultValue:テスト対象のコード
matcher:検証メソッド
expectValue:期待値
expect().matcher()
でテスト検証を行う
SAMPLE
descrive('テストサンプル',()=>{
beforeEach(() =>{
//初期化
});
it('テスト内容サンプル',() =>{
expect(1+1).toEqual(2);
});
});
具体的なテストの書き方
パイプ
通常のクラスを検証するときと同様にテストコードを作成する。
パイプクラスをインスタンス化し、itメソッドでパイプのメソッドを呼び出してMatcherで検証する
//小文字を大文字に変換するパイプの場合
descrive('パイプテストのサンプル',()=>{
let pipe = new SamplePipe();
let check_msg = 'sample';
it('挙動確認',()=>{
expect(pipe.sample(check_msg)).toEqual('SAMPLE');
});
});
サービス
パイプと同様にクラスを実行し、Matcherで検証する
//格納されたデータを取り出すサービスの場合
import{SampleService} from './sample.service';
descrive('サービスのサンプルテスト',()=>{
let service SampleService;
beforeEach(()=>{
service = new SampleService();
});
it('getDataメソッドの動作確認',()=>{
let data = service.getData();
//データが取得できたのか確認
expect(data).toBeDefined();
});
});
サービスが単体で完結することは少ない
→http/jsonpなどの非同期通信サービスに依存することが多い
コンポーネント
Angular内部の処理を意識する必要がある為、複雑になる
コンポーネントのテストには、
テストモジュールの準備→コンポーネントのインスタンス化→変更検知
というAngular内部の処理をテストコードとして明示的に記載しなくてはいけない。
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MyApp } from './app.component';
import { By } from '@angular/platform-browser';
import { DebugElement} from '@angular/core';
describe('MyApp Component', () => {
let de: DebugElement;
let component: MyApp;
let fixture: ComponentFixture;
beforeEach(() => {
//テスト用モジュール
TestBed.configureTestingModule({
declarations: [MyApp]
});
//コンポーネントのインスタンス化
fixture = TestBed.createComponent(MyApp);
component = fixture.componentInstance;
//テスト対象要素を取得
de = fixture.debugElement.query(By.css('h1'));
});
it('<h1>要素の存在確認', () => {
fixture.detectChanges();
const h1 = de.nativeElement;
expect(h1.innerText).toMatch(/angular/i);
});
});
TestBedはユニットテストのための環境を初期化/設定するためのクラス。コンポーネント/サービス作成するのためのメソッドも提供。