26
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Angularを使ってテスト駆動開発しようとしたときの備忘録

Last updated at Posted at 2018-01-26

#はじめに
テスト駆動開発について勉強する機会がありました。
Angularのテストについても勉強する機会があったので、Angularを使ってテスト駆動開発を実験。
その時の備忘録。

##環境

  • Windows10
  • Angular 5.2
  • Angular-cli 1.6.5

#Angularを使ったテスト

##テストの種類

  • ユニットテスト
    =単体テスト
     個々の構成要素を単体で確認
  • E2Eテスト
    =インテグレーションテスト
     サーバーサイドとクライアントサイドの協調動作の確認

##Karma+Jasmineによるテスト
###Karma
 これを起動すると、Webサーバーが生成されます。
 そのあと自動的にブラウザが起動し、生成したWebサーバーを通じて、そのブラウザがテストを開始。
 Angular-cliを使っていると自動的にインストールされるのでおすすめ。

 image.png

###Jasmine
 テストコードの記述、テスト結果の確認、モックライブラリなどの機能を備えたテスティングフレームワーク。
 基本的にテストコードを記述するファイス名は末尾を".spec"として./appに作成が推奨。
 こちらもAngular-cliを使うと自動的に作成されてる。便利。

image.png

##テストコードかいてみる

app.component.spec.ts
describe('テスト',() => {
  beforeEach(() =>{
    //初期化処理
  });

it('1+1のテスト',() => {
  expect(1+1).toEqual(2);
  });
});

今回は1+1が2であることを確認するテストを書きました。
まず、describeメソッドで全体を囲むことで、テストのまとまりを表します。
beforeEachメソッドは、初期化処理が必要な場合に使用するので、省略可能です。
itメソッドでは、個々のテストをかいていきます。
expoectの中にはテスト対象のコードを、
toEqualの中には期待する値をかきます。

toEqualはアサーションメソッドとよばれ、toEqualの他にもいっぱいあります

##テスト実行
npm testコマンド実行でできます。

テストが成功するとこちらの画像がでます。
 image.png

デフォルトのテストが3件あったので、テストは全4件です。

上のコードを次のようにかえて失敗させてみます。

app.component.spec.ts
describe('テスト',() => {
  beforeEach(() =>{
    //初期化処理
  });

it('1+1のテスト',() => {
  expect(1+1).toEqual(3);
  });
});

 image.png

#テスト駆動開発について
##TDDサイクル
とっても簡単に言うと、

  1. 失敗するテストをかく。
  2. テストが成功するように実装する。
  3. テストが成功したままきれいなコードをかく。(リファクタリング)
    を繰り返すことらしいです。

ポイント
・テストはたくさんではなく1つかく。
・ステップ2ではテストが成功することだけを考える。
・テストが通る状態を維持する。

#Angularを使ったテスト駆動開発してみると
##FizzBazzを例に…
t_wadaさんのde:codeの講演にて、FizzBazzを使った例でデモをされていたので、
同じ例を使ってAngularでテスト駆動してみます。

まず目標を考えます。
今回の目標は以下6つに分けられます。細かくわけることが大事です。

  1. 数を文字列にして返す
  2. 3の倍数の時は数の代わりにFizzと返す
  3. 5の倍数の時はBuzzと返す
  4. 3と5両方の倍数の場合には「FizzBuzz」と返す
  5. 1から100までの数
  6. プリントする

さっそく一つ目の目標からテストをかいてみます。

##数字を文字列に変換

appcomponent.spec.ts
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');
  }));
});

テストコードを書くときは検証部分から埋めていき、
下から上にコードを書くとよいそうです。

テスト実行。
まだ何も実装してないので怒られます。

 image.png

テストコードが正しいことをテストします。
テストのてすと。

appcomponent.ts
export class AppComponent {
  title = 'app';
  numtest = Numtest(1);
  };

function Numtest(i: number): string {
    return '1';
  }

image.png

実装します。

export class AppComponent {
  title = 'app';
  numtest = Numtest(1);
  };

function Numtest(i: number): string {
    return i.toString();
  }

image.png

とりあえず実装できたみたい。

コードをきれいにします。(リファクタリング)

app.component.ts
export class AppComponent {
  title = 'app';
  numtest = Numtest(1);
  };
  
  //数字を文字列に変換する関数
  let Numtest = (i:number): string =>{
    return i.toString();
  };

今回はファンクションをシンプルにアロー関数でかきました。
ここでは変数名とかコメントの整理も含みます。

テストが通ることを確認。

 image.png

以上で一つのサイクルとなります。
似たサイクルの繰り返しでテストに慣れてきたら、
テストのテストは省略してもいいみたいです。
テストコードを書くということに慣れていないので、すごく時間がかかりました。
ごりごり実装派の私には苦手ですが、テストの自動化ができるので便利だなとも思います。

とりあえずここまで。

#参考

##参考にした本

26
29
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?