#はじめに
テスト駆動開発について勉強する機会がありました。
Angularのテストについても勉強する機会があったので、Angularを使ってテスト駆動開発を実験。
その時の備忘録。
##環境
- Windows10
- Angular 5.2
- Angular-cli 1.6.5
#Angularを使ったテスト
##テストの種類
- ユニットテスト
=単体テスト
個々の構成要素を単体で確認 - E2Eテスト
=インテグレーションテスト
サーバーサイドとクライアントサイドの協調動作の確認
##Karma+Jasmineによるテスト
###Karma
これを起動すると、Webサーバーが生成されます。
そのあと自動的にブラウザが起動し、生成したWebサーバーを通じて、そのブラウザがテストを開始。
Angular-cliを使っていると自動的にインストールされるのでおすすめ。
###Jasmine
テストコードの記述、テスト結果の確認、モックライブラリなどの機能を備えたテスティングフレームワーク。
基本的にテストコードを記述するファイス名は末尾を".spec"として./appに作成が推奨。
こちらもAngular-cliを使うと自動的に作成されてる。便利。
##テストコードかいてみる
describe('テスト',() => {
beforeEach(() =>{
//初期化処理
});
it('1+1のテスト',() => {
expect(1+1).toEqual(2);
});
});
今回は1+1が2であることを確認するテストを書きました。
まず、describeメソッドで全体を囲むことで、テストのまとまりを表します。
beforeEachメソッドは、初期化処理が必要な場合に使用するので、省略可能です。
itメソッドでは、個々のテストをかいていきます。
expoectの中にはテスト対象のコードを、
toEqualの中には期待する値をかきます。
toEqualはアサーションメソッドとよばれ、toEqualの他にもいっぱいあります。
##テスト実行
npm test
コマンド実行でできます。
デフォルトのテストが3件あったので、テストは全4件です。
上のコードを次のようにかえて失敗させてみます。
describe('テスト',() => {
beforeEach(() =>{
//初期化処理
});
it('1+1のテスト',() => {
expect(1+1).toEqual(3);
});
});
#テスト駆動開発について
##TDDサイクル
とっても簡単に言うと、
- 失敗するテストをかく。
- テストが成功するように実装する。
- テストが成功したままきれいなコードをかく。(リファクタリング)
を繰り返すことらしいです。
ポイント
・テストはたくさんではなく1つかく。
・ステップ2ではテストが成功することだけを考える。
・テストが通る状態を維持する。
#Angularを使ったテスト駆動開発してみると
##FizzBazzを例に…
t_wadaさんのde:codeの講演にて、FizzBazzを使った例でデモをされていたので、
同じ例を使ってAngularでテスト駆動してみます。
まず目標を考えます。
今回の目標は以下6つに分けられます。細かくわけることが大事です。
- 数を文字列にして返す
- 3の倍数の時は数の代わりにFizzと返す
- 5の倍数の時はBuzzと返す
- 3と5両方の倍数の場合には「FizzBuzz」と返す
- 1から100までの数
- プリントする
さっそく一つ目の目標からテストをかいてみます。
##数字を文字列に変換
describe('数字を文字列にして返す', () =>{
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent //テストしたいコンポーネントを宣言
],
}).compileComponents();
}));
it('1を文字列1で返す',async(() => {
//準備
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
//検証
expect(app.numtest).toEqual('1');
}));
});
テストコードを書くときは検証部分から埋めていき、
下から上にコードを書くとよいそうです。
テスト実行。
まだ何も実装してないので怒られます。
テストコードが正しいことをテストします。
テストのてすと。
export class AppComponent {
title = 'app';
numtest = Numtest(1);
};
function Numtest(i: number): string {
return '1';
}
実装します。
export class AppComponent {
title = 'app';
numtest = Numtest(1);
};
function Numtest(i: number): string {
return i.toString();
}
とりあえず実装できたみたい。
コードをきれいにします。(リファクタリング)
export class AppComponent {
title = 'app';
numtest = Numtest(1);
};
//数字を文字列に変換する関数
let Numtest = (i:number): string =>{
return i.toString();
};
今回はファンクションをシンプルにアロー関数でかきました。
ここでは変数名とかコメントの整理も含みます。
テストが通ることを確認。
以上で一つのサイクルとなります。
似たサイクルの繰り返しでテストに慣れてきたら、
テストのテストは省略してもいいみたいです。
テストコードを書くということに慣れていないので、すごく時間がかかりました。
ごりごり実装派の私には苦手ですが、テストの自動化ができるので便利だなとも思います。
とりあえずここまで。
#参考
##参考にした本