GitHub ActionsとCypressを使って、テスト自動化環境をゼロから構築する

# はじめに
本記事は、アジャイル開発手法におけるQAの参考になれば、と作成しました。
開発、QA、また今後、それらに携わっていく方々の即戦的知識になればと思います。

また、本記事で作成したソースコードは下記に公開しています。
https://github.com/EIKINAKAYAMA/cypress-demo



# そもそもテストって？
システム開発では、システムがリリースされるまで、
作成された開発物に問題がないかを色んなテストでチェックします。

* UIテスト
* ブラックボックステスト
* 負荷テスト
* リグレッションテスト
* 退行テスト
* 受け入れテスト
* アドホックテスト
etc...


上記は一部を載せていますが、まだまだ沢山あります。
会社や組織によって呼び方が変わったり、テストというよりもテスト手法だったり、同じようで厳密には内容が異なったりと多種多様のテストが存在し、必ずしも全てのテストを実施しているわけではなかったりします。

**これだけ様々なテストがありますが、ざっくりと下記の3種に分けることができます。**
この3種類のテストを経てリリースされることが、現在のデファクトスタンダードとなっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165025/bfdd8fbf-889f-8342-b476-9405c1419654.png)
> 引用元: https://www.qbook.jp/academy/curriculum/0001/lessons/ad00003/

* **単体テスト（UT：Unit Test）**
  * 関数やメソッド単位で、正しく機能するかをテスト。
  * JUnit(Java), PHPUnit(PHP),Jest(JavaScript)などのフレームワーク利用しテスト。
  * 基本、開発者・QAエンジニアの領域。
  * ”A”という文字か表示できているか、”計算が正しくできてるか”というレベル。
  
* **結合テスト（IT：Integration Test）**
  * コンポーネント単位で、正しく機能するかをテスト。
  * テスト設計や手法に基づいて、漏れなく打検。
  * 基本、QAの領域。
  * ”決められた選択肢を選択した後、意図したポップアップが出るか”というレベル。

* **システムテスト（ST:System Test）**
  * 完成された開発物全体で、要件を満たしているかをテスト。
  * テスト設計や手法に基づき、漏れなく打検。
  * 基本、QAの領域。
  * "ログインから購入まで問題なく完了できるか"というレベル。


以上が通称、**V字モデル**の右側に該当する箇所となっています。
![Screen Shot 2022-05-26 at 23.50.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165025/aee0132f-8df4-9d62-0d15-9bd66a4a64dd.png)
> 引用元: https://ja.wikipedia.org/wiki/V%E3%83%A2%E3%83%87%E3%83%AB

# テスト自動化について

さて近年、アジャイル開発手法が流行しています。
高速開発手法と呼ばれるものですね、、、
![Screen Shot 2022-05-24 at 22.36.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165025/aebb1976-e51a-3022-285b-2aefeaef7b13.png)
> 引用元: https://cortechne.jp/dev_method

あまり着目されてないですが、**高速開発**ということは、本来**高速テスト**でもあるべきです。というよりそうであるのが理想です。
特に、開発変更箇所が1だったとしても、テストは100実施することが望ましいと考えると、超々々々スーパー高速テストを実施してあげるべきです。

ここで爆成長を遂げたのが、<font color="DarkTurquoise">テスト自動化</font>です！！！！!
![Screen Shot 2022-05-24 at 22.32.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165025/94491d84-b701-f8ee-0c3a-592417acee5c.png)
> 引用元: 民衆を導く自由の女神（ドラクロワ：ルーブル美術館)より


テスト自動化は、文字どおりテストを自動化することです。
つまり上記で記載した「V字モデル」の右側を人ではなく、システムにやらせようということです。

？？？？？？？？？

百聞は一見にしかずなので、実際に動くものを作ってみてみましょう！

# Cypressとは

と、その前に今回、自動テストを構築するにあたって**Cypress**というNode.jsを利用したJavaScriptのテストフレームワークを使います。

詳細については、公式サイトや他の記事でご参照ください。

公式サイト（https://docs.cypress.io/guides/overview/why-cypress）
Quiita記事（https://qiita.com/eyuta/items/a2454719c2d82c8bacd5）

簡単に特徴を挙げておきます。

メリット
・環境構築が楽、CI連携が楽、動作が軽い
（Web WebDriver API経由ではなく、ブラウザ上でランナーが動く）
・e2eテスト（UT~STの全てがテスト可能）
・クロスブラウザ対応（chrome、chromium、edge、electron、firefox）
・DOMが出現するまで、自動でリトライ
・Javascriptイベントをテストコード側でlistenすることが可能
・multi-domain対応（ドメインまたぎのテストが可能）

デメリット
・テスト特化、スクレイピングはできない
・Javascript（Typescript）以外の言語は対応されていない
・複数のブラウザウィンドウの同時操作ができない。チャットのテスト等はできない


実際に動かしてみると特徴が理解しやすので、いざ初めて行きましょう！！！

# 環境構築

<details>
 <summary>使用ツール バージョン一覧</summary>
 <ul>
  <li>node v18.2.0</li>
  <li>cypress v9.6.0</li>
 </ul>
</details>

### 1. Node.jsをインストールする。
[MacにNode.jsをインストール](https://qiita.com/kyosuke5_20/items/c5f68fc9d89b84c0df09)

### 2. テストしたいアプリケーションを入れる。

:::note info
テストしたいアプリケーションを導入します。
:::

:::note warn
本記事では、Reactのアプリケーションを入れてみます。
:::

```terminal:コマンド
npx create-react-app cypress-demo
npm run start
```

### 3. 作成したアプリをリモートリポジトリをPUSHする。
[gitの使い方(git init 〜git push)](https://qiita.com/shungo_m/items/b73ff5b1ec6d69bb5c50)

### 4. Cypressをインストールする。
```terminal:コマンド
$ npm install cypress --save-dev

$ npx cypress open
``` 

するとこのような形で、Cypressが動いているのが確認できます。

![Screen Shot 2022-05-25 at 16.20.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165025/0fa900a8-009d-21e3-b0eb-5f708dcdd072.png)

### 5. CI内でCypressを実行するコマンドを追加作成します。
```json:package.json
"scripts": {
    "cy:open": "cypress open",
    "cy:run": "cypress run"
  }
```

### 5. テストファイルを作成する。

:::note info
こちらは、作成されたアプリケーションや実施したいテストによって、任意に変更ください。
:::

:::note warn
本記事は、Reactで作成されたデフォルトの画面を対象テストしています。
cypress/integration配下にあるファイルがテストファイルです。
:::

<details><summary>サンプルコード</summary>

```demo.spec.js
/// <reference types="cypress" />

describe('test demo', () => {
  beforeEach(() => {
// Port番号は各アプリケーションに応じて変えてください。
    cy.visit('http://localhost:3000')
  })

  it('text check', () => {
// containsは、画面に指定の文字が含まれているか否かをテストします。文字は任意に変更ください。
    cy.contains('Learn React')
  })
})
```
</details>

### 6. いざテスト開始！
```terminal:コマンド
$ #with browser
$ npm run cy:open

$ # OR

$ #headless
$ npm run cy:run
```

実行結果
|cy:open|cy:run|
|---|---|
|![Screen Shot 2022-05-25 at 17.28.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165025/605a4a06-cb28-170a-d6ef-6264145a8756.png)|![Screen Shot 2022-05-25 at 17.34.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165025/4f83639f-6bd2-d9c7-8f32-1a92f44fc509.png)

### 7. CI内でLocalサーバーが立ち上がるまで待機させる構成を入れる。
手順6までは、Localサーバーを立ち上げてからテストしましたが、CI内ではLocalサーバーが立ち上がっていることを判定して、テストを実施する必要があります。

:::note warn
本記事は、ReactのBuildされたファイルを対象にしています。
CI用のテスト実行コマンドのポート番号、サーバー起動コマンドは、必要に応じて変更ください。
:::


```terminal:コマンド
$ #判定ライブラリのインストール
$ npm install start-server-and-test --save-dev

$ #サーバー起動ライブラリのインストール(*必要があれば)
$ npm install serve 
``` 
CI用のテスト実行コマンドを追加
```json:package.json
"scripts": {
    "ci": "start-server-and-test 'serve -s ./build' 3000 'cy:run'"
  }
```

実行すると、サーバーが立ち上がってからテストが始まるのが確認できるはずです。
```terminal:コマンド
$ npm run build
$ npm run cy:ci
```

### 8. CI(GitHub Actions)をセッティングする。

今回は、GitHub連携が不要なGitHub Actionsを使いたいと思います。

https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions

GitHubのリポジトリにあるActionsのタブから「set up a workflow yourself」を押下して、yamlファイルを作成します。
![Screen Shot 2022-05-25 at 22.59.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165025/2c23a92b-3689-6828-62b5-03fb1124db46.png)


```yaml:./gitHub/workflows/main.yaml
name: build and cypress test

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: run ci command
        run: |
          npm install
          npm run build
          npm run ci
```

### 9. PRを作成してCommit！。

これをCommit, Pushすると、CIが走ります。
あとは、眺めているだけで自動でテストしてくれます。

**実行結果　OKの場合**
![Screen Shot 2022-05-25 at 22.29.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165025/fea8ad6b-e3a6-6dbc-65fe-dd318b481b1b.png)

**実行結果　NGの場合**
![Screen Shot 2022-05-25 at 23.09.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165025/ffa4a4c0-caad-a5ab-5ab6-41878d1d472e.png)

今回はシンプルなテストでしたが、テストを入れていけば活躍間違いなしです。

# その他の自動化

今回は、Cypressを利用して構築しましたが、
色々な自動化ツールがあるので、ご自身の環境にあったツールを利用して自動化構築を構築してみてください！

https://test-hack.com/automation_tools_trend_2022/

# おわりに

テスト自動化は9割が失敗するという記事があるように、失敗例が多いです。

https://service.shiftinc.jp/column/4634/

個人的には、下記のいずれかを満たすと失敗しそうだなと感じました。

・コードのメンテナンスコストと、テスト自動化範囲のバランスが悪い。
・1つのPR内に開発変更と自動テストの変更が入らない。(作成者が違う等の理由により)
・データが固定化されていない。

これから導入を考えている方の参考になればと思います。