CypressでE2Eテストを自動化する方法とは?基本的な使い方から押さえておきたいコマンドまで解説

Autify, Inc.

近年、ウェブアプリケーションの複雑化に伴い、E2Eテストの重要性が増しています。その中で、Cypressは効率的なE2Eテスト自動化ツールとして注目を集めています。

従来のE2Eテストは時間と労力がかかり、開発サイクルのボトルネックになることがありました。Cypressは、これらの課題を解決し、より迅速で信頼性の高いテストを可能にします。

例えば、ログイン機能や特定画面への遷移など、ユーザーの一連の操作を模倣したテストシナリオを、Cypressを使って簡単に作成・実行することが可能です。

本記事では、cy.visit()やcy.get()などの基本的なコマンドから、非同期処理の扱い方まで、実践的な内容を解説します。

読者の皆様がCypressを活用してE2Eテストを効果的に自動化し、アプリケーションの品質向上に役立つ情報をまとめているので、ぜひ参考にしてください。

Cypressとは?

Cypressは、現代のWebアプリケーション向けに設計された次世代のフロントエンドテストツールです。開発者やQAエンジニアが、現代のアプリケーションをテストする際に直面する主要な課題を解決することを目指しています。

(参考: https://docs.cypress.io/guides/overview/why-cypress

Cypressは、基本の自動テスト部分を担う Cypress App と、ダッシュボードや分析、レビューなどの機能を提供する Cypress Cloud で構成されています。Cypress App はオープンソースツールで、無料で提供されています。

次のセクションでCypressの特徴や利用するメリット、SeleniumやPlaywrightなどの他のフレームワークとの違いをご紹介します。

Cypressの特徴・メリット

Cypressは2015年にBrian Mannによって作成され、2016年に最初のバージョンがリリースされました。その後、急速に成長し、フロントエンド開発者に広く受け入れられるようになり、現在も修正とリリースが続いています。

(参考: https://docs.cypress.io/guides/references/changeloghttps://www.cypress.io/about-us/our-story

Cypressは、JavaScriptで構築されたオープンソースのフロントエンドテストツールです。軽量かつ直感的なインターフェースが特徴で、E2Eテストや単体テストなど幅広いテストに利用できます。

他のフレームワークとの違い

Cypressは他のE2Eテストフレームワークと比較して独自の特徴を持ち、特定のユースケースで優れた選択肢となります。

E2Eテストフレームワークの選択は、プロジェクトの要件、開発チームのスキル、テスト対象のアプリケーションの性質によって異なります。Cypressと他のフレームワークを比較することで、最適な選択が可能になるでしょう。

以下の表で、Cypress、Selenium、Playwrightの主要な特徴を比較します。

詳しい比較については、別記事「E2Eテストフレームワーク “Cypress” とは?他のフレームワークとの違いやデメリットについても解説!」 に記載しています。こちらもぜひご覧ください。

Cypressを活用したE2Eテスト自動化の進め方

Cypressを用いてE2Eテストを自動化するには、しっかりとした手順を踏んで進めることが重要です。

Cypressは強力で直感的なツールですが、その効果を最大限に引き出すためには、基本的な設定やテストケースの設計から、テストコードの実装、そして実際のテスト実行に至るまでの各ステップを理解し、適切に進める必要があります。

この章では、Cypressを使ってE2Eテスト自動化を成功させるための具体的な進め方を詳しく解説します。

Cypressを使う上での必須知識・技術

Cypressを効果的に活用するためには、ある程度のプログラミング知識とエンジニアスキルが求められます。

特にJavaScriptに関する理解は不可欠です。CypressのテストコードはすべてJavaScriptで記述されるため、基本的な文法や構文、関数の使い方に慣れていることが前提となります。

また、非同期処理の理解も重要です。Webアプリケーションでは非同期通信が頻繁に行われるため、Cypressを使ってこれらの処理を正確にテストするためには、Promiseやasync/awaitといった非同期プログラミングの概念に慣れておく必要があるでしょう。

1.Cypressのインストールと初期設定

Cypressのインストール手順について、事前準備から実際のインストール、そして動作環境の設定までを順を追ってご紹介します。

今回は、Windows環境での初期設定について詳しく解説しますが、macOS環境でもほとんど同じ手順で進められるので、参考にしてください。

前提条件

Cypressをインストールする前に、PCにNode.jsとnpmがインストールされていることが必要です。

Node.jsはJavaScriptの実行環境であり、npmはNode.jsに付随するパッケージ管理ツールです。これらがなければ、Cypressのインストールや動作はできません。

まず、Windowsのコマンドプロンプトを起動し、以下のコマンドを入力して、Node.jsとnpmが既にインストールされているかを確認しましょう。

node --version
npm --version

これらのコマンドを実行すると、それぞれのバージョンが表示されます。

上記のイメージのように、v20.13.1や10.8.0のようにバージョン番号が表示されれば、インストールは正常に完了しています。

もし、バージョン番号が表示されない場合や「'node' is not recognized as an internal or external command」というエラーメッセージが表示される場合は、Node.jsがインストールされていないか、インストールが正しく行われていない可能性があります。

その場合は、まずNode.jsの公式サイト(https://nodejs.org/en/download/package-manager)から最新の安定版をダウンロードし、インストールを行います。

Node.jsのインストールが完了すると、npmも自動的にインストールされます。もし、npmがインストールされていない場合は、以下のコマンドを使用して手動でインストールできます。

npm install -g npm

これで、Cypressをインストールする準備が整いました。

プロジェクトの準備

Node.jsとnpmのインストールが完了したら、次にCypressを使用するプロジェクトの準備を行います。

まず、任意の場所に新しいプロジェクトフォルダを作成します。今回は「CypressProject」という名前のフォルダを作成し、その中に移動します。

mkdir CypressProject
cd CypressProject

次に、プロジェクトを初期化します。

初期化することで、プロジェクトフォルダにpackage.jsonというファイルが生成され、プロジェクトに関する基本設定が行われます。

npm init -yを使用すると、すべての設定をデフォルトで自動的に行うことができます。

npm init -y

これでプロジェクトの基本準備は完了です。

Cypressのインストール

Cypressはnpmパッケージとして提供されています。

これをインストールするには、以下のコマンドを使用します。

特にバージョンを指定しない場合、最新のバージョンがインストールされますが、プロジェクト間でバージョンの違いを避けるため、特定のバージョンを指定してインストールすることも可能です。

今回は、Cypressのバージョン13.5.0を指定してインストールします。

npm install cypress@13.5.0 --save-dev

インストールが正常に完了すると、node_modulesフォルダ内にCypressが追加され、package.jsonのdevDependenciesにもCypressのバージョンが記載されます。

2.Cypressの初期設定・テストケース作成・実行

Cypressを使用する前に初期設定を行います。初回の起動時に、必要なディレクトリと設定ファイルが自動的に生成されます。以下のコマンドを実行して、Cypressを起動しましょう。

npx cypress open

コマンドを実行すると、CypressのGUIが起動し、次に進むためのメニューが表示されます。

この画面で「E2E Testing」を選択し、ガイドに従って設定を進めます。

途中で「Continue」をクリックすると、Cypressが必要な設定ファイルをプロジェクトフォルダに追加します。

次に、テストを実行するブラウザを選択します。今回はChromeを選択し、「Start E2E Testing in Chrome」をクリックします。これにより、Chromeが新しいウィンドウで起動し、Cypressのテスト画面が表示されます。

ここで「Create new spec」を選択し、新しいテストケースを作成します。デフォルトの設定のまま進めることができますので、特に変更の必要はありません。

「Okay, run the spec」をクリックすると、Cypressがサンプルのテストを実行します。

このテストでは、cy.visit(url)という基本メソッドを使用して、指定されたURL(例:https://example.cypress.io)に正常に遷移できるかを確認します。テストが成功すると、テストの進行状況や結果が画面に表示されます。

次に、テストの失敗例を試してみましょう。プロジェクトフォルダ内の「cypress/e2e」ディレクトリに、先ほど作成したspecファイル(テストファイル)が保存されています。これをエディタで開き、テスト対象のURLの一部を削除するなどして、意図的にエラーを発生させます。

変更を保存し、再度テストを実行すると、エラーが発生したことが確認できます。

Cypressは、エラーが発生した部分のコードや原因を詳細に表示してくれるため、問題の特定が容易です。

基本的な操作は以上です。

これからは、作成したプロジェクトフォルダに新しいテストケースを追加し、プロジェクトに適したテストを実施していくことで、Cypressを使ったE2Eテストの自動化をさらに深めていくことができます。

押さえておきたいCypressのコマンド5選

E2Eテストツールとして人気の高いCypressですが、効果的にテストを行うには主要なコマンドを理解することが重要です。

本章では、Cypressで頻繁に使用される5つの基本的なコマンドを紹介します。

これらのコマンドを習得することで、より堅牢で信頼性の高いテストを作成できるようになるでしょう。

cy.visit()

cy.visit()は、指定したURLにブラウザを遷移させるコマンドです。テストの開始時に対象のWebページを読み込むために使用します。

describe('ログインページのテスト', () => {
  it('ログインページにアクセスできる', () => {
    // 指定したURLのログインページにアクセス
    cy.visit('https://example.com/login');
    
    // ページのタイトルが期待通りであることを確認
    cy.title().should('eq', 'ログイン - Example Site');
  });
});

ポイント

・cy.visit()は非同期で動作する(オプション)ため、

 ページの読み込みが完了するまで自動的に待機します。

・ベースURLをcypress.jsonで設定している場合は、相対パスを使用できます

 (例:cy.visit('/login'))。

cy.get()

cy.get()は、DOMから要素を選択するためのコマンドです。CSSセレクタを使用して要素を特定します。

describe('ログインフォームのテスト', () => {
  beforeEach(() => {
    // 各テストの前にログインページにアクセス
    cy.visit('/login');
  });
  it('ログインフォームが表示される', () => {
    // IDセレクタを使用してログインフォームが表示されていることを確認
    cy.get('#login-form').should('be.visible');
    
    // name属性を使用してユーザー名入力フィールドの存在を確認
    cy.get('input[name="username"]').should('exist');
    
    // name属性を使用してパスワード入力フィールドの存在を確認
    cy.get('input[name="password"]').should('exist');
    
    // type属性とテキスト内容を使用してログインボタンを確認
    cy.get('button[type="submit"]').contains('ログイン');
  });
});

ポイント

・複数の要素がマッチする場合、cy.get()は要素の配列を返します。

・要素が見つからない場合、デフォルトで4秒間リトライします。

cy.type()

cy.type()は、選択した入力フィールドにテキストを入力するコマンドです。

describe('ログイン機能のテスト', () => {
  beforeEach(() => {
    // 各テストの前にログインページにアクセス
    cy.visit('/login');
  });
  it('有効な認証情報でログインできる', () => {
    // ユーザー名フィールドにテキストを入力
    cy.get('input[name="username"]').type('testuser');
    
    // パスワードフィールドにテキストを入力
    cy.get('input[name="password"]').type('password123');
    
    // ログインボタンをクリック
    cy.get('button[type="submit"]').click();
    
    // ログイン後にダッシュボードページにリダイレクトされることを確認
    cy.url().should('include', '/dashboard');
  });
  it('特殊キーを使用できる', () => {
    // 特殊キー(バックスペース)を使用してテキストを入力
    cy.get('input[name="username"]').type('incorrect{backspace}{backspace}');
    
    // 入力結果を確認
    cy.get('input[name="username"]').should('have.value', 'incorre');
  });
});

ポイント

・{backspace}、 {enter}、 {esc}などの特殊キーも使用できます。

・{ delay: 100 }オプションを使用して、入力の遅延をシミュレートできます。

cy.click()

cy.click()は、選択した要素をクリックするコマンドです。ボタンやリンクの操作に使用します。

describe('ナビゲーションのテスト', () => {
  beforeEach(() => {
    // 各テストの前にホームページにアクセス
    cy.visit('/');
  });
  it('ナビゲーションメニューが機能する', () => {
    // 「製品」リンクをクリックし、URLを確認
    cy.get('nav').contains('製品').click();
    cy.url().should('include', '/products');
    
    // 「お問い合わせ」リンクをクリックし、URLを確認
    cy.get('nav').contains('お問い合わせ').click();
    cy.url().should('include', '/contact');
  });
  it('複数回クリックをテストできる', () => {
    // ボタンを3回連続でクリック
    cy.get('#counter-button').click().click().click();
    
    // クリックカウントが3であることを確認
    cy.get('#click-count').should('have.text', '3');
  });
});

ポイント

・要素が表示されていない場合、Cypressは自動的にスクロールしてから要素をクリックします。

・{ force: true }オプションを使用すると、要素が操作可能でない場合でもクリックを強制できます。

cy.should()

cy.should()は、アサーションを行うためのコマンドです。テストの期待値を確認するために使用します。

describe('ユーザー登録フォームのテスト', () => {
  beforeEach(() => {
    // 各テストの前に登録ページにアクセス
    cy.visit('/register');
  });
  it('バリデーションエラーを表示する', () => {
    // 送信ボタンをクリック(フォームが空の状態)
    cy.get('button[type="submit"]').click();
    
    // エラーメッセージが表示され、期待するテキストが含まれていることを確認
    cy.get('.error-message')
      .should('be.visible')
      .and('contain', 'ユーザー名は必須です')
      .and('contain', 'パスワードは8文字以上である必要があります');
  });
  it('成功メッセージを表示する', () => {
    // フォームに有効な情報を入力
    cy.get('input[name="username"]').type('newuser');
    cy.get('input[name="email"]').type('newuser@example.com');
    cy.get('input[name="password"]').type('strongpassword123');
    
    // 送信ボタンをクリック
    cy.get('button[type="submit"]').click();
    
    // 成功メッセージが表示され、期待するテキストであることを確認
    cy.get('.success-message')
      .should('be.visible')
      .and('have.text', '登録が完了しました!');
    
    // ダッシュボードページにリダイレクトされたことを確認
    cy.url().should('include', '/dashboard');
  });
});

ポイント

・should()は複数のアサーションを連鎖させることができます。

・カスタムアサーションを作成することも可能です。

・should()は自動的にリトライするため、非同期の操作でも安定したテストが可能です。

E2Eテストシナリオの例

E2Eテストシナリオは、ユーザーがアプリケーションを使用する中で経験する様々な操作フローを模倣し、その一連のプロセスが全体として期待通りに動作しているかを検証します。

これらのテストは、アプリケーションの主要機能の健全性を確認し、潜在的なバグや不具合を早期に発見するための重要な手段です。ここでは、いくつかの具体的なシナリオを例に挙げて説明します。

ログイン周りに関するテスト

ログイン機能は、ユーザーのアクセスを制御するために欠かせない機能であり、その信頼性はアプリケーション全体のセキュリティとユーザー体験に直結します。

ログインに関するE2Eテストでは、さまざまなケースを考慮して機能が期待通りに動作することを確認します。以下にいくつかの具体的なシナリオを紹介します。

正しいユーザー名とパスワードでのログイン

ユーザーが正しい認証情報(ユーザー名とパスワード)を入力した際に、アプリケーションが適切にユーザーを認証し、ダッシュボードやホーム画面などの保護された画面にリダイレクトすることを確認します。

また、ログイン後に正しいユーザー名が画面上に表示されるかも確認します。

不正な認証情報の入力

不正なユーザー名やパスワードを入力した場合、エラーメッセージが表示され、ユーザーが再試行できる状態でログイン画面に留まることを確認します。

このシナリオでは、エラーメッセージが適切であり、セキュリティ的な観点からもユーザー情報が漏れないように設計されているかを確認します。

パスワードを忘れた場合のリセット手順

ユーザーが「パスワードを忘れた」リンクをクリックし、登録されたメールアドレスを入力すると、リセット用のリンクが送信されることを確認します。

また、リンクをクリックした後、ユーザーが新しいパスワードを設定し、再びログインできるかどうかも確認します。

このシナリオは、セキュリティ上の脆弱性がないか、ユーザー体験がシームレスかどうかも検証します。

ソーシャルログイン機能の確認

GoogleやFacebookなどのソーシャルログインオプションを利用して、ユーザーが迅速かつ安全にログインできるかを確認します。

例えば、Googleアカウントを使用してログインを試みた場合に、認証プロセスが正常に完了し、ユーザーが期待通りの画面に遷移するかどうかを検証します。

特定の画面への遷移に関するテスト

ユーザーがアプリケーションを操作する中で、画面間を移動する操作は頻繁に行われます。これらの遷移がスムーズかつ期待通りに動作することは、ユーザーエクスペリエンスに直接影響を与えます。

特定の画面への遷移に関するテストでは、リンクやボタンが正しく機能し、必要な情報が適切にロードされるかを確認します。

ホーム画面からプロフィール画面への遷移

ユーザーがナビゲーションメニューやプロフィールアイコンをクリックしてプロフィール画面に移動できるかを確認します。

この際、プロフィール画面にユーザーの登録情報が正しく表示され、更新が可能であることも検証します。

ダッシュボードから設定画面への遷移

ダッシュボード画面で設定ボタンをクリックすると、ユーザーが設定画面にリダイレクトされることを確認します。

設定画面では、アカウント設定や通知設定などが適切に表示され、変更が反映されることも確認します。

商品一覧ページから商品詳細ページへの移動

商品一覧ページで特定の商品をクリックすると、該当商品の詳細情報が表示されるページに移動できるかを確認します。

詳細ページには、商品名、価格、説明、画像などが正確に表示されるかを検証します。

特定のフィルタを適用した後に検索結果画面に遷移する

ユーザーが検索機能を利用し、特定の条件でフィルタをかけた後に検索結果が表示される画面に移動できるかを確認します。

フィルタリングが正しく適用され、表示される結果がフィルタ条件に一致しているかを検証します。

CypressでE2Eテストを自動化する上での注意点

Cypressは強力なE2Eテストツールであり、開発者が複雑なユーザー操作を自動化して、アプリケーションの信頼性を確保するのに役立ちます。

しかし、その一方で、Cypressを使用する際にはいくつかの注意点も存在します。以下では、Cypressを活用する際に特に気を付けるべきポイントを紹介します。

サポートブラウザの制限

Cypressは主要なブラウザをサポートしていますが、すべてのブラウザで動作するわけではありません。

特に、Internet Explorerなどの旧ブラウザではサポートがされておらず、特定のブラウザ依存の機能がある場合、テストの結果が意図した通りにならない可能性があります。

また、Cypressのサポート対象外のブラウザに対してテストを行う必要がある場合は、別のツールとの併用を検討する必要があるでしょう。

非同期処理の扱い方

非同期処理は現代のWebアプリケーションにおいて非常に一般的です。

Cypressは非同期処理を自動的に待機する機能を持っていますが、複雑なシナリオでは適切な待機時間やコマンドチェーンの設計が必要になります。

誤ったタイミングでの検証や、未完了の処理が原因でテストが失敗することを防ぐために、各処理の終了を適切に確認するロジックを組み込むことが重要です。

パフォーマンス

Cypressは実際のブラウザ上でテストを実行するため、テストスクリプトの複雑さやテストケースの数が増えると、実行時間が長くなることがあります。

テストのパフォーマンスを最適化するためには、冗長なテストケースや不要な待機時間を排除し、可能であればテストの並列実行を検討することが必要です。

また、Cypressはテストの結果を動画として記録する機能を持っていますが、大量の動画データが生成されるとストレージの負荷が高くなるため、必要に応じて記録の設定を調整することも考慮する必要があります。

まとめ

この記事では、Cypressを用いたE2Eテストの基本概念から実際の自動化手順、さらにCypressを効率的に活用するための注意点まで、幅広く解説しました。

この記事を通じて、Cypressを活用したE2Eテストの基本から応用までの知識を得ることができたと思います。Cypressを効果的に使用し、アプリケーションの品質を高める一助となれば幸いです。