フォームの送信テストにcypressを使ってみた

みなさん、フォーム送信テストの時は手動で入力されていますか。
私は手動で入力する時間が無駄な気がしています。
できることなら自動でフォーム入力して欲しい、その間にコーヒーでも飲みたいです。

そんな方への処方箋、Cypressを使用した自動入力テストをお勧めします。

## 使用バージョン
Cypress 11.2.0 を使用しています。

## Cypressとは
JavaScriptで構築されたテスト自動化ツールです。
E2Eテストに分類され、ユーザーが実際に操作しているかのように全体を通してテストを行うことができます。

今回で言うと、ユーザーがフォームを入力して送信ボタンを押すまでをテストすることになります。

## 環境構築
[Cypressの公式サイト](https://docs.cypress.io/guides/getting-started/installing-cypress#Installing)を参照しつつ、構築していきます。

### npmを使用してインストール
まずは適当な場所にプロジェクトディレクトリを作成します。
```shell
mkdir /your/project/path
cd /your/project/path
```
次にcypressをインストールしてきます。
```shell
npm install -D cypress
```

:::note warn
Node.jsは12か14以降をサポートしています。
あらかじめ自身の環境のNode.jsバージョンを確認してください。
:::

### cypressの起動
package.jsonに起動用のスクリプトを登録します。
```json
{
  "scripts": {
    "cy:open": "cypress open"
  }
}
```
そして以下のコマンドで起動することができます。
```
npm run cy:open
```

するとcypressが起動し、以下のようなGUIが出現します。
![スクリーンショット 2022-12-05 18.15.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882125/08765257-5a97-ce0b-b4fa-7bbd7a7acbe5.png)

E2E Testingを選択し、設定ファイルを作成します。
![スクリーンショット 2022-12-05 18.16.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882125/e035317c-36fb-e496-cc9d-91ae2d122790.png)
設定ファイルは自動で作成されるので、自分で設定する必要はありません。
Continueをクリックし、設定を終えましょう。

次にどのブラウザで検証するか選択できます。ただし、自身の環境にインストールしているブラウザのみ選択可能です。
![スクリーンショット 2022-12-05 18.16.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882125/7dfa22a9-ba0f-c868-9421-3a361addf601.png)

### サンプルテストを実施する
あとは簡単なサンプルテストを実施してみましょう。

`cypress/e2e`に以下ファイルを追加します。
```javascript:sample.cy.js
describe('サンプルテスト', () => {
    it ('ルートパスにアクセスする', () => {
        cy.visit('https://goq.co.jp')
    })
})
```
画面上ではファイルが選択できる状態になっています。
![スクリーンショット 2022-12-05 18.31.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882125/662aefc2-f4c8-adb1-0557-c0d6c7a26e62.png)

実際に実行してみましょう。sample.cy.jsをクリックします。
![画面収録-2022-12-06-19.03.08.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882125/081f9d64-3b8e-3d05-923c-ef0034f7068c.gif)


このように実際にユーザーが操作しているようにテストができます。
また、左側でどのようなアクションが起こったのか確認することができ、マウスオーバーすることでその時の状態を右側で表示することができます。とても便利です。

## 【本題】フォーム自動入力をする
では本題に入っていきましょう。
ここでは簡単なフォームを作成し、入力した値がレスポンスで返ってきてメッセージとして表示させるようにしていきます。

### htmlファイル
まずはhtmlファイルを作成します。
```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>form test with cypress</title>
</head>
<body>
    <h1>フォームをcypressで送信するよ</h1>
    <form id="js-form">
        <div>
            <label for="name">名前</label>
            <input type="text" id="name" name="name" required>
        </div>
        <div>
            <label for="email">メールアドレス</label>
            <input type="email" id="email" name="email" required>
        </div>
        <input type="submit" value="送信">
    </form>
    <p id="js-result"></p>

    <script>
        const form = document.getElementById('js-form')
        const resultText = document.getElementById('js-result')
        
        form.addEventListener('submit', function(event) {
            event.preventDefault()
            const payload = {
                name: this.name.value,
                email: this.email.value
            }
            fetch('form.php', {
                method: 'POST',
                body: JSON.stringify(payload)
            })
                .then(res => res.json())
                .then(data => {
                    const message = data.message
                    resultText.innerHTML = message
                })
                .catch(e => {
                    alert(e)
                })
        })
    </script>
</body>
</html>
```

### phpファイル
データを受け取り、メッセージとして返すphpを作成します。
```php:form.php
<?php
$request = json_decode(file_get_contents("php://input"), true);

$name = $request["name"];
$email = $request["email"];

$message = "ようこそ{$name}さん\nメールアドレスは{$email}です";

echo json_encode([
    "message" => $message
]);
```

### テストファイル
テストケースを作成していきます。
ここでは名前、メールアドレスを入力し、送信しています。無事メッセージが表示され、入力された内容が入っていればテストが通るようになります。
```js:form.cy.js
describe('フォームテスト', () => {
    it ('正常に送受信できる', () => {
        const name = 'iwata'
        const email = 'iwata@example.com'

        cy.visit('http://localhost:8080') // 自身の環境に合わせてください
        // 名前を入力
        cy.get('input[name=name]').type(name)
        // メールアドレスを入力
        cy.get('input[name=email]').type(email)
        // 送信する
        cy.get('input[type=submit]').click()
        // メッセージが表示される
        cy.get('#js-result').contains(name).contains(email)
    })
})
```
![画面収録-2022-12-05-19.05.17.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882125/3ac13f54-a506-6266-3234-b43b777db3ec.gif)

### Cypressでテストを行うメリット
今回簡単なフォームをテストしましたが、以下のメリットがあります。
- ユーザーが同じ操作をした場合に意図した挙動をしているか、実際のブラウザ上で確認できる（入力、送信ボタンを押す、メッセージが表示されるなど）。
- 実行したアクションが細かく記録されており、原因の特定が容易になっている。

## GoQSystemでは一緒に働いてくれる仲間を募集中です！
ご興味がある方は以下リンクよりご確認ください。

https://goqsystem.recruit.site?qiita=de379c67a5ff03c097e5