様々なテストツールをいじってみた。

# はじめに
今回の目的はいろんなテストツールを実際に書いて学習していこう！というものです。
簡単なコードですが、同じコードをそれぞれの記法で書きながら比較していこうとうものです。
基本の「き」しかかいていないので公式のリファレンスをゴリゴリ読むことをおすすめします。

# 対象テストツールのご紹介

![スクリーンショット 2018-12-08 17.14.13.png](https://qiita-image-store.s3.amazonaws.com/0/194863/34a4a2de-94d5-4b1b-285d-3636c52a1851.png)

> 引用: https://github.com/kamranahmedse/developer-roadmap

こちらの`developer-roadmap`や いろんなライブラリーを調べながら進めていきたいと思います。

```

1 Jest
2 Jasmine
3 Mocha
```

# テスト対象
今回expressを用いて、簡単な認証システムを作成しました。

実際に`Login`と`Logout`について書いてみました。
今回は`Router`オブジェクトのテストをやりやすくるために`supertest`というモジュールをインストールしています。
https://github.com/visionmedia/supertest


# [Jest](https://jestjs.io)

## 導入

```
$ npm install --save-dev jest
```
## コード
```login-spec.js
const request = require('supertest');
const app = require('../app');

describe('/login', () => {
  test('it returns status code is 200', (done) => {
    request(app).get('/login').then((response) => {
      expect(response.statusCode).toBe(200);
      done();
    });
  });

  test("it returns Content-Type is 'text/html'", (done) => {
    request(app).get('/login').then((response) => {
      expect(response.headers["content-type"]).toBe('text/html; charset=utf-8');
      done();
    });
  });
});

```

```logout-spec.js
const request = require('supertest');
const app = require('../app');

describe('logout', () => {
  test('it returns status code is 302', (done) => {
    request(app).get('/logout').then((response) => {
      expect(response.statusCode).toBe(302)
      done();
    });
  });

  test('it redirects root path', (done) => {
    request(app).get('/logout').then((response) => {
      expect(response.headers['location']).toBe('/')
      done();
    });
  });
});

```

**実行結果**
①
![スクリーンショット 2018-12-10 11.55.06.png](https://qiita-image-store.s3.amazonaws.com/0/194863/f9cb41df-af3b-3ab9-3312-f01d7a3589b3.png)

②
![スクリーンショット 2018-12-10 12.09.48.png](https://qiita-image-store.s3.amazonaws.com/0/194863/786034dd-db5d-e89d-8df2-446e8110a789.png)

## 所感
標準設定でこれらの情報を表示してくれるのは親切だなと思ってしまいました。
またに `--watch`というような watchオプションをつけると監視モードに入ってくれるので、テストを変更した際に自動で走るようになってくれます。(①)他にも `--covarage`といったcovarageオプションをつける下記のようなグラフ上で結果を表示してくれます！(②)
Mactherも直感的でわかりやすかったです！


# [Jasmine](https://jasmine.github.io/index.html)

## 導入

```
$ npm install --save-dev jasmine

```

## コード

```loginSpec.js
const request = require('supertest');
const app = require('../app');

describe('/login', () => {
  it('returns status code is 200', (done) => {
    request(app)
      .get('/login')
      .end((err, res) => {
        try {
          expect(err).toBeNull()
          expect(res.status).toEqual(200)
          done();
        } catch (err) {
          done.fail(err);
        }
      });
  });

  it('responses content-type is 'text/html'', (done) => {
    request(app)
      .get('/login')
      .end((err, res) => {
        try {
          expect(err).toBeNull()
          expect(res.status).toEqual(200)
          expect(res.headers['content-type']).toEqual('text/html; charset=utf-8')
          done();
        } catch (err) {
          done.fail(err);
        }
      });
  });
});

```

```logoutSpec.js
const request = require('supertest');
const app = require('../app');

describe('/logout', () => {
  it('returns status code is 302', (done) => {
    request(app)
      .get('/logout')
      .end((err, res) => {
        try {
          expect(err).toBeNull()
          expect(res.status).toEqual(302)
          done();
        } catch (err) {
          done.fail(err);
        };
      });
  });

  it('redirects root path', (done) => {
    request(app)
      .get('/logout')
      .end((err, res) => {
        try {
          expect(err).toBeNull()
          expect(res.headers['location']).toEqual('/')
          done();
        } catch (err) {
          done.fail(err);
        };
      });
  });
});

```

## 実行結果
![スクリーンショット 2018-12-11 21.11.42.png](https://qiita-image-store.s3.amazonaws.com/0/194863/3d2dda94-59ee-0600-c6ef-509cca20c40b.png)

## 所感
いろんな記事にも書かれていたのですが、`Ruby/RailsでRSpecを使ってテストを書く習慣がベースとしてあって、RSpecと似たような記法のJasmineは違和感がない`というのは実際に感じました。
Matcherも似たような感じなので、イメージでできてしまいます。(実際にはちゃんと調べましょう！)
Angularで使われることが多々あるようですね！

# [Mocha](https://mochajs.org/)

## 導入

```
$ npm install --save-dev mocha
```

## コード

```login_spec.js
const request = require('supertest');
const app = require('../app');

describe('/login', () => {
  
  it ('return status code is 200', (done) => {
    request(app)
      .get('/login')
      .expect(200, done);
  });

  it ('returns Content-Type is text/html; charset=utf-8', (done) => {
    request(app)
      .get('/login')
      .expect('Content-Type', 'text/html; charset=utf-8', done);
  });
});
```

```logout_spec.js
describe('/logout', (done) => {
  it('returns status code is 302', (done) => {
    request(app)
      .get('/logout')
      .expect(302, done);
  });

  it('redirect root page', (done) => {
    request(app)
      .get('/logout')
      .expect('Location', '/', done);
  });
});
```

## 実行結果

![スクリーンショット 2018-12-11 21.20.31.png](https://qiita-image-store.s3.amazonaws.com/0/194863/412ffc00-2b40-0a98-35e0-579ba6951262.png)

## 所感
今回はmochaというよりも、`supertest`風な書き方になってしまいました....
ですが期待する値と結果を引数で書くやり方はこれまでと一線を画しています。
またGithub上で調べてみると、比較的古めのプロダクトはmochaで書かれている印象を持ちました。
いろんなOSSを参考にしながら、構成を考えたり、リーディングできたりすることはとても魅力的ですね！

# まとめ
どんなアプリケーションでも必ずテストは書くかと思います。
実際３つのテストツールを書いてみて感じたことは`Jest`は使いやすいというか、defaultでいろんなことができるなーという印象を持ちました。
また、ReactやVueなどにもしっかり対応しています。Vue jsの [Vue Test Utils](https://vue-test-utils.vuejs.org/ja/guides/choosing-a-test-runner.html)では `Jest は最も充実したテストランナです`とまで言っていますw
それほど、多くのエンジニアから認められていることを裏付けるかのようです。
今回のこのアドベントカレンダーのおかげさまで、一度に３つのテストツールに触れることができました。簡単なコードではありましたが、沢山リファレンスを読むことができたのでとても勉強になりました！みなさんも個人、会社用のQiita、または会社のブログ、年一回のアドベントカレンダーなどの機会を上手に使いながら学習していきましょう！