Cypressを使ってReactアプリケーションでエンドツーエンドテストを書く方法

フロントエンド開発では、視覚的に魅力的で機能的なクライアント向けのアプリを構築することが求められます。しかし、落とし穴があります。これらのアプリケーションは、ユーザーにシームレスなエクスペリエンスを提供する必要があります。

アプリケーションの機能を検証するには単体テストと統合テストが不可欠ですが、一般的なユーザーの操作を完全に捉えることができない場合があります。ユーザーの操作を真にシミュレートするには、実際のユーザーの操作を再現するエンドツーエンドテストを実行する必要があります。これにより、アプリケーションが最初から最後まで意図したとおりに動作することを確認できます。

Cypressを使ってエンドツーエンドテストを始める

フロントエンドアプリケーションのエンドツーエンドテストの主な目的は、ビジネスロジックの実装の詳細ではなく、結果を検証することです。

ログインフォームを例にとってみましょう。理想的には、ログイン画面が想定通りに表示され、想定通りの動作をするかどうかをテストします。基本的に、技術的な詳細は重要ではありません。最終的な目標は、ユーザーの立場に立って、ユーザーのエクスペリエンス全体を評価することです。

Cypressは、人気のJavaScriptフレームワークの一部と互換性のある、優れた自動化テストフレームワークです。ブラウザ内で直接テストを実行する機能と、包括的なテスト機能スイートにより、テストをシームレスかつ効率的に行うことができます。また、以下を含むさまざまなテストアプローチをサポートしています。

  • 単体テスト
  • エンドツーエンドテスト
  • 統合テスト

Reactアプリケーションのエンドツーエンドテストを書くには、以下のユーザーストーリーを検討してください。

  • ユーザーは、対応する送信ボタンを持つ入力フィールドを見ることができます。
  • ユーザーは、入力フィールドに検索クエリを入力することができます。
  • ユーザーは、送信ボタンをクリックすると、入力フィールドのすぐ下にアイテムのリストが表示されるはずです。

これらのユーザーストーリーに従うことで、ユーザーが製品を検索できるシンプルなReactアプリケーションを構築することができます。このアプリは、DummyJSON APIから製品データを取得し、ページにレンダリングします。

このプロジェクトのコードは、GitHubリポジトリにあります。

Reactプロジェクトの設定

まず、Viteを使ってReactプロジェクトを作成するか、create-react-appコマンドを使って基本的なReactアプリケーションを設定します。インストールプロセスが完了したら、プロジェクトに開発依存関係としてCypressパッケージをインストールします。

npm install cypress --save-dev

次に、このスクリプトを追加してpackage.jsonファイルを更新します。

"test": "npx cypress open"

関数コンポーネントの作成

srcディレクトリで、componentsという名前のフォルダを作成します。このフォルダの中に、新しいproducts.jsxファイルを追加し、以下のコードを含めます。

import React, { useState, useEffect } from 'react';
import "./style.component.css"
export default function Products(prop) {
const [products, setProducts] = useState([]);
const [error, setError] = useState(null);
const { searchInput } = prop;
return (
<div className="product-catalogue">
{error ? (
<p>Product not found</p>
) : (
<div className="product-list">
{products.slice(0, 6).map((product) => (
<div className="product" key={product.id}>
<h2>Title: {product.title}</h2>
<p>Price: ${product.price}</p>
</div>
))}
</div>
)}
</div>
);
}

関数コンポーネントの中で、提供された検索クエリに基づいて製品データを取得する非同期関数を呼び出すuseEffectフックを定義します。

useEffect(() => {const fetchProducts = async () => {if (searchInput) {const apiUrl = https://dummyjson.com/products/category/${searchInput};try {const response = await fetch(apiUrl);if (!response.ok) {throw new Error('Error fetching products');}const json = await response.json();setProducts(json.products);setError(null);} catch (error) {setError(error.message);}}};fetchProducts();}, [searchInput]);

App.jsxファイルの更新

次に、以下のコードでApp.jsxファイルを更新します。

import React, { useState,useRef } from 'react'
import './App.css'
import Products from './components/Products'
function App() {
const [searchInput, setSearchInput] = useState('')
const searchInputRef = useRef('');
const handleSubmit = (e) => {
setSearchInput(searchInputRef.current.value);
}
return (
<div>
<h1>Cypress Testing Library tutorial</h1>
<label htmlFor="input">Input</label>
<input
id="text"
type="text"
ref={searchInputRef}
/>
<button type="button" onClick={handleSubmit}>Submit</button>
<Products data-testid="products-component" searchInput={searchInput} />
</div>
)
}
export default App

開発サーバーを起動しましょう。

npm run dev

素晴らしい!ダミーJSON APIから特定の製品データを取得できるはずです。

テスト環境の設定

まず、ターミナルでテストスクリプトコマンドを実行します。

npm run test

このコマンドはCypressクライアントを起動して開きます。E2E Testingボタンをクリックしてください。

次に、ContinueをクリックしてCypress設定ファイルを追加します。

このプロセスが完了すると、プロジェクトに新しいCypressテストディレクトリが表示されます。さらに、Cypressのクライアントは自動的にcypress.config.jsファイルを追加します。このファイルを更新して、テスト環境、動作、設定のさまざまな側面をさらにカスタマイズできます。

Cypressを使ってエンドツーエンドテストを書く

最初のテストを書くには、テストを実行するブラウザを選択する必要があります。Cypressクライアントで利用可能なブラウザから希望のオプションを選択します。

Cypressは、選択したブラウザの簡略版を起動し、テストを実行するための制御された環境を作成します。

Create new specオプションを選択してテストファイルを作成します。

コードエディタに移動し、cypress/e2e/App.spec.cy.jsファイルを開き、そのファイルの内容を以下のコードで更新します。

describe('App Tests', () => {
beforeEach(() => {
cy.visit('http://127.0.0.1:5173/');
});
it('Renders input field and submit button', () => {
cy.get('#text').should('exist').should('be.visible');
cy.get('#btn').should('exist').should('be.visible').contains('Submit');
});
it('Enters a search query', () => {
const searchQuery = 'laptops';
cy.get('#text').type(searchQuery);
});
});

上記で強調表示したユーザーストーリーに戻ると、この特定のテストスイートは2つの側面を確認します。

  • ブラウザがページにインプットフィールドとサブミットボタンを表示していること。
  • ユーザーが検索クエリを入力できること。

JestやSupertestなどの他のJavaScriptテストツールと同様に、Cypressは宣言的な構文と言語を使用してテストケースを定義します。

テストを実行するには、Cypressで管理されている簡略版のブラウザに戻り、実行する特定のテストファイルを選択します。

Cypressはテストを実行し、テストプレイグラウンドの左側のペインに結果を表示します。

アプリケーションプロセスのシミュレーション

ユーザーの操作全体をテストする(この特定のユースケースでは)、アプリケーションがユーザーの入力を受け取り、必要なデータを取得し、最後にブラウザページにデータを表示できることを確認する必要があります。

わかりやすくするために、e2eフォルダー内に別のテストスイートを収容する新しいテストファイルを作成できます。または、特定のテストケースを探索するすべてのテストスイートを1つのテストファイルに含めることもできます。

e2eフォルダーに新しいProducts.spec.cy.jsファイルを作成します。このファイルに、以下のコードを含めます。

describe('Products Tests', () => {
it(' fetches and displays the data', () => {
const searchQuery = 'laptops';
cy.visit('http://127.0.0.1:5173');
cy.get('#text').type(searchQuery);
cy.get('#btn').contains('Submit').click();
cy.get('.product').should('have.length.greaterThan', 0);
cy.get('.product').first().should('contain', 'Title');
cy.get('.product').first().should('contain', 'Price: $');
});
});

このテストスイートは、ユーザーが特定の検索項目を送信すると、アプリがブラウザページでデータを取得して表示することを確認します。

これを行うには、検索入力を入力し、送信ボタンをクリックし、製品の読み込みを待って、製品アイテムの存在を確認し、タイトルや価格などの詳細を確認するプロセスをシミュレートします。本質的に、ユーザーの視点から全体的なエクスペリエンスをキャプチャして検証します。

エラーと応答のシミュレーション

Cypressのテスト内でさまざまなエラーシナリオと応答をシミュレートすることもできます。

e2eディレクトリに新しいError.spec.cy.jsファイルを作成し、以下のコードを含めます。

describe('Error Handling Tests', () => {
it('Displays error message for incorrect search query', () => {
cy.intercept('GET', /https:\/\/dummyjson\.com\/products\/category\/.*/, {
statusCode: 404, // Not Found
body: 'Product not found'
}).as('fetchProducts');
cy.visit('http://127.0.0.1:5173');
const incorrectSearchQuery = 'rocket';
cy.get('#text').type(incorrectSearchQuery);
cy.get('#btn').click();
cy.wait('@fetchProducts');
cy.contains('Product not found').should('be.visible');
});
});

このテストスイートは、ユーザーが間違った検索クエリを入力するとエラーメッセージが表示されることを確認します。

テストケースに合格するには、Cypressのintercept関数を使用してネットワークをスタブし、ネットワーク要求エラーをシミュレートします。次に、入力フィールドに間違った検索クエリを入力し、フェッチプロセスを開始すると、エラーメッセージ「Product not found」がページに表示されることを確認します。

この結果は、エラー処理メカニズムが期待通りに機能していることを示しています。

テスト駆動開発でのCypressの使用

テストは基本的な開発要件ですが、時間のかかるプロセスにもなりえます。しかし、Cypressを組み込むことで、テストケースが一緒に実行される様子を目にするという大きな満足感を得ることができます。

Cypressは、アプリケーションにテスト駆動開発を実装するための優れたツールです。包括的なテスト機能スイートを提供するだけでなく、さまざまなテスト戦略もサポートしています。Cypressを最大限に活用するには、公式ドキュメントを調べて、さらに多くのテスト機能を発見してください。