Reactテスト道場 〜e2eテスト / cypress編〜

ロジックもComponentもちゃんとテストが書けたぞ！！完璧だ！！
...しかし、それらを組み合わせたらサービスがちゃんと動くか、そこまでは担保してくれません。

そこで、e2eテストの出番です。

## e2eテストとは
e2e(End to End)テストとは、システム全体を通して正しく動くかを検証するためのテストです。
テストコードを書いて実行するテストを指しているわけではなく、人間が仕様書通りに動くか確認するテストも含まれます。

...といっても、人力でテストをするには、工数がかかったり、網羅性に欠けていたりと課題がありますね。
(人力のテストでしか気づけないことももちろんありますが。)
そこで、e2eテストを自動化するツールが

## e2eテストツールの種類

* ローコード(画面ぽちぽちするだけでできる！)
    * [autify](https://autify.com/ja)
    * [mabl](https://www.mabl.com/japan)
* コードを書く 
    * [cypress](https://www.cypress.io/)


ローコードのe2eがとても魅力的...ですが、自分のプロダクトではcypressを使っているので、
cypressにスポットを当てて作っていこうと思います！！

## cypressとは？
cypressは、「ブラウザで実行されるすべてのものに対する高速で簡単かつ信頼性の高いテスト」ができるツールです。
そのため、e2eテスト用というわけではなく、単体テストもできます！！

### その他cypressにできること
* cookieやlocalStrageなども操作できる
* スクリーンショットやビデオを記録できる

## cypressのディレクトリ構造
```js
🗂 cypress
   //テストで使用する静的データを管理するディレクトリ
   └ 🗂 fixtures

   //テストを管理するディレクトリ
   └ 🗂 integration

   // プラグインを管理するディレクトリ(テスト実行前に自動的に全部インポートされる)
   └ 🗂 plugins

   // カスタムコマンドやグローバルオーバーライドに時に使う(テスト実行前に自動的に全部インポートされる)
   └ 🗂 support

   // cypressの設定を書くjson
   cypress.json
```

## cypress始め方
###  インストール
```
yarn add -D cypress 
```

### 起動・実行
```
yarn run cypress open
```

## 書き方
基本的には、cypressが準備した「コマンド」をチェーンメソッドを用いて実行し、検証します。

### 大枠
jestとほぼ一緒ですが、検証では`test`ではなく`it`を使います。

```js
describe("大項目", () => {
  beforeEach(() => {
    // ...
  });

  it('テスト内容', () => {
    // ・・・
  });
  it('テスト内容', () => {
    // ・・・
  });
});
```

### 要素の取得
cypressでは、クラスやidなど色々な方法で要素の指定ができますが、
cypressで使われているか予測しづらいため、予期しない変更・削除をしてしまう可能性があります。

そのため、基本cypress用のカスタム属性(`data-test`)を付与して使います。
また、カスタムコマンドに定義して、使いまわせるようにすると良いです:qiitan:

```js
Cypress.Commands.add('getBySel', (selector, ...args) => {
  return cy.get(`[data-test=${selector}]`, ...args);
});

Cypress.Commands.add('getBySelLike', (selector, ...args) => {
  return cy.get(`[data-test*=${selector}]`, ...args);
});
```

```js
// data-test="cv-button" 属性を持つ要素を取得
cy.getBySel('cv-button')
```

▼ 参考

https://docs.cypress.io/guides/references/best-practices


### 要素の操作
取得した要素に対して、チェーンさせて使います。
ほとんどはjavascriptのイベント名と同様ですが、異なるものも多くあるためドキュメントをみて記載すると良いでしょう。

▼ よく使うイベント

* [type](https://docs.cypress.io/api/commands/type.html#Syntax) - DOMに対して入力
* [click](https://docs.cypress.io/api/commands/click) - 要素をクリック
* [blur](https://docs.cypress.io/api/commands/blur)  -フォーカスされたDOM要素をぼかす
* [focus](https://docs.cypress.io/api/commands/focus)  -DOM要素にフォーカス
* [clear](https://docs.cypress.io/api/commands/clear)  -入力またはテキストエリアの値をクリア
* [check](https://docs.cypress.io/api/commands/check)  -チェックボックスまたはラジオをチェック
* [uncheck](https://docs.cypress.io/api/commands/uncheck)  -チェックボックスのチェックをはずす
* [select](https://docs.cypress.io/api/commands/select) - select内のoptionを選択

また、同じ処理を繰り返すような場合は、`as()`を使ってエイリアスを切ることもできます。

```js
beforeEach(() => {
  cy.getBySel('cv-button').click().as('cvButton')
})

it('has access to text', function () {
  this.cvButton
})
```

https://docs.cypress.io/guides/core-concepts/variables-and-aliases#Aliases

### その他よく使う(?)コマンド

* [url](https://docs.cypress.io/api/commands/url) - 現在のページのURLを取得
* [visit](https://docs.cypress.io/api/commands/visit#Syntax) - URLにアクセス
* [wait](https://docs.cypress.io/api/commands/wait#Syntax) - 次のコマンドに進む前に、待機
* [clearCookies](https://docs.cypress.io/api/commands/clearcookies) - cookieを削除
* [clearLocalStorage](https://docs.cypress.io/api/commands/clearlocalstorage) - localStorageを削除
* [viewport](https://docs.cypress.io/api/commands/viewport.html) - viewportを変更(サイズ指定、デバイス指定など)
* [screenshot](https://docs.cypress.io/api/commands/screenshot) - スクショ撮影
* [go](https://docs.cypress.io/api/commands/go) - ブラウザの操作(ブラウザバックなど)

### 検証

cypressでは、[should](https://docs.cypress.io/api/commands/should.html#Syntax)コマンドに、[chai](https://github.com/chaijs/chai)というアサーションライブラリの文法を使って検証します。


```js
.should(chainers, value)
```

例)

```js
cy.getBySel('error').should('be.empty')
cy.getBySel('error').should('contain.text', '必須です')
```

また、[and](https://docs.cypress.io/api/commands/and)コマンドを用いて検証を連ねることもできます。

```js
cy.getBySel
  .should('have.property', 'name')
  .and('contain.text', '必須です')
```

▼ 参考 - アサーション一覧 | cypress

https://docs.cypress.io/guides/references/assertions.html#BDD-Assertions

▼ 参考 - アサーション一覧 | chaijs


https://www.chaijs.com/api/bdd/