開発環境に対して、無料でCypressの並列処理を実装する

# はじめに
cypressの並列処理を公式Dashboardで実施すると、テスト量に応じて課金されます。

https://docs.cypress.io/guides/guides/parallelization#Overview

本記事は、cypressの並列処理を、無料でできる方法はないかと模索した記録を残したものになります。

# 調査結果
sorry-cypressという公式のDashboardを模倣したオープンソースを使い実装が可能ですが、CIによっては、制約がありました。

#### 検証CI
* Jenkins
    * 制約なしで実装が可能。おすすめ。
    * 構築手順、SampleのStageを記載しました。

* Github Actions
  * Cypress公式のGithub Actions連携自体、他のCIと違いやや特殊。
  * sorry-cypressをGithub Actions外にデプロイする必要性あり。
  * そもそも開発環境の並列処理には向かいない。
  各JOBで開発環境を立ち上げる必要あり。
  * GitHub Actions内だけで並列処理を実装できたよ。という方、PRお待ちしています！(sorry-cypressを利用した、直列構成は実装済み)

https://github.com/EIKINAKAYAMA/parallel-cypress

# 実装手順

<details>
 <summary>使用ツール バージョン一覧</summary>
 <ul>
  <li>node v16.15.0</li>
  <li>cypress v9.6.0 (v10.0.0以上でもsorry-cypressが使えることは検証済)</li>
  <li>pm2 v5.2.0</li>
  <li>cy2 v2.0.0</li>

 </ul>
</details>


# 並列構成の導入

### 1. sorry-cypressのImageをPullする。

https://docs.sorry-cypress.dev/

```terminal:terminal
$ docker run -p 1234:1234 agoldis/sorry-cypress-director
```

### 2. 模倣サイト用の”Cypress”コマンドをInstallする。
Cypress公式では、Cypressコマンドが登録されているが、模倣機能ではCyコマンドが登録されているので、それをInstallする。

```terminal:terminal
$ npm install cy2 --save-dev
```

### 3. projectIdを設定する。
公式では、ProjectIdをキーとして並列処理の実行対象を判別している為、ProjectIdが並列処理の必須パラメーターとなっています。
これは模倣側でも同様で必須パラメーターの設定となっていますが、公式とは違い専有サーバーをDockerで起動させているので、模倣側では使用されないDummyキーとなってます。

```terminal:cypress.json
{
    "projectId": "sorry-cypress"
}
```
なんでも良いですが、sorry-cypressとしておきます。

### 4. 2つのターミナルで実行してみる
起動したDockerサーバーに対して、並列処理のリクエストを投げます。
```terminal:terminal1
$ CYPRESS_API_URL="http://localhost:1234/" npx cy2 run --record --key XXX --parallel --ci-build-id XXX
$#XXX：の箇所はなんでも構いませんが、２つのターミナルで同じものを設定してください。
```
同一環境に対して、並列処理が実行されていれば成功です。

## CIで開発環境に対して、並列処理構成を導入（発展）
:::note info
CI環境(Github Actions)への連結の記事は、下記を参考ください。
https://qiita.com/EIKINAKAYAMA/items/e0b9550152c19e229263
:::

直列の場合は、”start-server-and-test” Libraryを利用することで1つのサーバーで待機させてからCypressを実行できましたが、並列処理の場合は、開発環境を構築した１つのサーバーに対して、2つのLinuxサーバーでCypressを並列処理させるのが理想的です。

### 1. まずnodeアプリをバックグラウンドモードで実行できるようにします。

https://pm2.keymetrics.io/

```terminal:terminal1
$ npm install -g pm2
$ pm2 start 'npm start' 
```
![Screen Shot 2022-06-26 at 16.07.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165025/1db3fdd7-17ea-50e8-a737-99f2ac8ff8a0.png)
これでサーバーが起動した後にコマンドを入力できるようになリました。

### 2. 次にCI上で並列構成を構築します。

Github Actionsでの並列構成はリポジトリをご参考ください。

```javascript: Jenkins(stage抜粋)
stage('cypress') {
 agent{
  image ${agent_image}
 }
 environment {
   CYPRESS_API_URL = 'http://localhost:1234/'
 }
 stages {
   stage('npm install') {
     sh "npm install"
     sh "npm install -g pm2"
   }
   stage('start react-app') {
     sh "pm2 start 'npm start' --name react-app"
   }
   stage('build sorry-cypress') {
     sh "docker run -d -p 1234:1234 --name sorry-cypress ${sorry_image}"
   }
   stage('parallel test') {
     parallel {
       stage('test1') {
          sh "npm wait-on http://localhost:3000 && npx cy2 run --spec "cypress/integration/test1" --parallel --record --key somekey --ci-build-id ${env.BUILD_ID}"
       }
       stage('test2') {
          sh "npm wait-on http://localhost:3000 && npx cy2 run --spec "cypress/integration/test2" --parallel --record --key somekey --ci-build-id ${env.BUILD_ID}"
       }
     }
   }
   stage('stop and remove react-app') {
      sh "pm2 stop react-app"
      sh "pm2 delete react-app"
   }
   stage('stop and remove sorry-cypress') {
      sh "docker stop sorry-cypress"
      sh "docker rm sorry-cypress"
   }
}
```


# 最後に
調査結果に記載の通り、GitHub Actions上で、下記のようにJOBを並列化させて表示したいという場合は、残念ながらsorry-cypressを使うことはできませんでした。

![Screen Shot 2022-06-27 at 21.10.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1165025/a3bc54cf-f4bb-e519-d737-4f260626cbc5.png)

理由としては、執筆時点でGitHub Actionsでは
・Step内での並列化ができないから。
・Host runner, containerをJOB単位で共有することができないから。
　（つまり、仮想環境をBuildされた状態でShareすることができない。）

これにより、GitHub ActionsのJOB内で同一のsorry-cypressにアクセスことができず並列化することができないと判断しました。
（勿論、GitHub Actions外にsorry-cypressを起動させておけば、公式Cypressと同様の接続構成となるので可能となりますが、、、）

今後のアップデートで、課題が対応されるのを期待しています！

参考文献(各公式以外で)
* https://github.com/sorry-cypress/sorry-cypress/issues/46
* https://github.community/t/whats-the-recommended-way-to-pass-a-docker-image-to-the-next-job-in-a-workflow/17225