Cypressを使えばWebアプリケーションのE2Eテストが簡単にできます!

f:id:val-fukui:20211210224819p:plain

ヴァル研究所 Advent Calendar 2021 15日目の記事です。

こんにちは。mixway teamに所属する平久江と申します。
mixway teamでは主にフロント部分の「mixwayのWebサイト」とバックエンドの「mixway API」に分かれており、私は主にフロント向けのWebサイト(長いので「mixway Web」と呼称しています)の保守運用を担当しています。

今回の記事ではタイトルそのままで、E2EテストのフレームワークCypressを使ってWebアプリケーションのE2Eテストを簡単に行う方法を紹介していきたいと思います。
Webエンジニア向けの記事となりますが、そうでない方にもWebアプリの保守の裏側はこうなっているんだなというのを感じ取っていただけますと幸いです!

テストの作り方

今回は私の担当している「mixway Web」をサンプルとしまして、Cypressでのテストの簡単な書き方を紹介していきたいと思います。

なお、Cypressの導入方法についてはプロジェクトによっても変わってくるかと思いますので省略いたします。こちらも気になる方は公式ドキュメントなどを参考にしてみてください!
また、前提条件としてテスト対象のアプリを別に立ち上げておく必要があります。今回の場合では裏側で「mixway Web」のアプリを 4567Port にて立ち上げています。

準備ができたら cypress/integration ディレクトリに以下のようなファイルを追加してください。

describe('検索画面にアクセスした際', () => {
  it('mixway-webのロゴが表示される', () => {
    cy.server();
    cy.visit('http://localhost:4567/');
  })
})

この状態でコンソールに npx cypress open と入力すると、こちらのCypressのアプリが立ち上がります。

f:id:hirakue:20211205204624p:plain

さきほど追加した index.spec.js をクリックするとデバッグ用のChromeアプリが立ち上がり、トップページにアクセスできていることがわかります。

f:id:hirakue:20211205204738p:plain

こちらはまだ単純にトップページにアクセスしただけで、テストではありません。 まず最初のテストでは画面上部にある「mixway」のロゴが出ているかのテストを書いていきます。

「mixway」のロゴの有無のチェックをする前に、まず前面に出ている初期モーダルを閉じる必要があります。
今回は「閉じる」ボタンを選択してクリックしたいので以下の一行を追加します。

cy.contains('閉じる').click();

するとこちらのように、初期モーダルをCypress上で閉じることができます。

f:id:hirakue:20211205224054p:plain

こちらのコマンドを簡単に解説します。
cy.contains('閉じる') で対象のDOM要素を探し、 .click() でクリックを行います。
もし 閉じる ボタンが複数ある画面の場合には、クリックしたい要素に <div data-cy="close-button"></div> のように data-cy 属性を付与します。
その上で cy.get('[data-cy=close-button]') のように書くと、狙った箇所をターゲットにすることができます。

この辺りももう少し詳しく知りたい方は 公式ドキュメント を見てみてください。

ここまでできたら、あとはロゴがあるかどうかを判定するだけになります。
さきほどと同じ要領でロゴ画像に data-cy=brand-logo 属性を加えた上で、以下の一文にて判断します。

cy.get('[data-cy=brand-logo]').should('exist');

f:id:hirakue:20211205225446p:plain

ちゃんとロゴが存在する場合には、テストに緑色のチェックが入ります。
逆に存在しない要素の場合は、以下のように弾かれて赤色の警告が出てきます。

f:id:hirakue:20211205225649p:plain

モックの置き換え

テスト自体はこれで動くようになりましたが、外部のAPIから取得したリクエストをモックに置き換える必要があります。
例として、mixway APIを利用した経路検索ではあまりにも昔の日付を指定して検索をするとエラーになってしまいます。
mixway APIを使って検索結果画面のテストをする場合、テストを書いた当初は問題なく稼働しますが、数ヶ月経過するとAPIからの経路検索レスポンスがエラーを返すようになってしまい、フロントエンド側は問題ないにも関わらずテストが落ちるようになってしまいます。

これを避けるためにも外部APIからのリクエストをモックに置き換えることで、外部API起因のエラーを排除して、フロントエンドに起因するエラーだけを特定することができるようになります。
モックで置き換える例として、ブログツールのAPIから取得しているこちらの赤枠で囲った部分(ニュース一覧)で試してみます。

f:id:hirakue:20211205235019p:plain

モックに置き換えるためには、置き換え対象のデータを取ってくる必要があります。 ブラウザの開発者ツールを開き、ネットワークタブから置き換え対象のデータを探していきます。
今回は記事( /api/blog-articles )を置き換えるので検索欄に blog-articles と入力し、ヒットしたリクエストのレスポンスからJSONデータを持ってきます。

f:id:hirakue:20211207223909p:plain

そうして持ってきたデータを cypress/figuresblog-articles.json に保存し、その上でテストコードを以下のように置き換えます。

describe('検索画面にアクセスした際', () => {
  beforeEach(()=>{
    cy.server();
    // ブログ記事レスポンス
    cy.route({
      method: "GET",
      url: `http://localhost:1337/api/blog-articles**`,
      response: "fixture:blog-articles.json"
    });
  })
  it('mixway-webのロゴが表示される', () => {
    cy.visit('http://localhost:4567/');
    cy.contains('閉じる').click();
    cy.get('[data-cy=brand-logo]').should('exist');
  })
})

モックに置き換わったかを確認するため、モックデータとして持たせているJSONファイルを書き換えた上でテストを実行してみると、ちゃんと置き換えた記事が出ていることがわかります。

f:id:hirakue:20211207231319p:plain

モックの置き換えはこちらで行っています。
methodはどのHTTPメソッドでリクエストをした時に置き換えをするか、urlは置き換え対象のURLを、responseは実際のリクエストの代わりにどのモックを使うかを指定します。

cy.route({
  method: "GET",
  url: `http://localhost:1337/api/blog-articles**`,
  response: "fixture:blog-articles.json"
});

こちらも色々とオプションがあるので、気になる方は 公式ドキュメント を見てみてください。

次回予告

以上、簡単ではありますがCypressを使ったE2Eテストの使い方をご紹介しました!
Cypressの使い方はまだまだ多くありますので、気になる方はぜひ調べてみてください。

さて、明日は通勤費Web開発チームの福井がお届けする、「コロナ禍でメンターとして心がけたこと」です。
明日もぜひお越しください!

vallaboratory.hatenablog.jp