0Pricing
React Academy · レッスン

React Testing LibraryによるIntegration Testing

テスト内でコンポーネントをrenderし、イベントを発生させ、実装ではなく表示結果を検証します。

「React Testing LibraryによるIntegration Testing」はCoddyKit上の無料React Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはReact Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 React Academyコースには全4レッスンが含まれています。

React Testing Libraryとは

React Testing Library(RTL)は、ユーザーの視点からテストすることを推奨します。コンポーネントを描画し、ユーザーと同じように操作して、実装の詳細ではなく表示される結果をアサートします。

セットアップ

RTLはCreate React AppとViteのReactテンプレートに含まれています。手動でセットアップする場合は、@testing-library/reactと@testing-library/jest-domをインストールします。

// package.json
// "@testing-library/react": "^14.0.0",
// "@testing-library/jest-dom": "^6.0.0"

// setupTests.ts
import '@testing-library/jest-dom';

コンポーネントの描画

render()は仮想DOMにコンポーネントをマウントします。描画された出力を対象とするクエリ関数を返します。

import { render, screen } from '@testing-library/react';
import { Button } from './Button';

test('renders button label', () => {
  render(<Button label="Submit" onClick={() => {}} />);
  expect(screen.getByText('Submit')).toBeInTheDocument();
});

要素の検索

クエリは次の順序で優先します:getByRole > getByLabelText > getByPlaceholderText > getByText。Roleクエリはアクセシビリティのセマンティクスに一致します。

// Best: query by role
const button = screen.getByRole('button', { name: /submit/i });

// Good: query by label (for form inputs)
const input = screen.getByLabelText('Email address');

// Acceptable: query by text
const heading = screen.getByText('Welcome');

イベントの発火

@testing-library/user-eventのuserEvent(推奨)またはfireEvent(基本)を使用します。userEventは、フォーカスやぼかしを含む実際のブラウザー操作をシミュレートします。

import userEvent from '@testing-library/user-event';

test('types into input', async () => {
  const user = userEvent.setup();
  render(<SearchBar />);
  const input = screen.getByRole('textbox');
  await user.type(input, 'react');
  expect(input).toHaveValue('react');
});

フォーム送信のテスト

フォームを描画し、userEvent.typeで入力欄に値を入力し、送信ボタンをクリックして、結果(成功メッセージ、ページ遷移、またはコールバックの呼び出し)をアサートします。

test('submits the login form', async () => {
  const onLogin = jest.fn();
  const user = userEvent.setup();
  render(<LoginForm onLogin={onLogin} />);

  await user.type(screen.getByLabelText('Email'), 'test@example.com');
  await user.type(screen.getByLabelText('Password'), 'password123');
  await user.click(screen.getByRole('button', { name: /log in/i }));

  expect(onLogin).toHaveBeenCalledWith({ email: 'test@example.com', password: 'password123' });
});

表示状態のアサート

toBeInTheDocument()、toBeVisible()、toHaveValue()などのjest-domのmatcherを使うと、アサーションを読みやすく記述できます。

expect(screen.getByText('Error: required')).toBeInTheDocument();
expect(screen.getByRole('dialog')).toBeVisible();
expect(screen.getByRole('textbox')).toHaveValue('hello');
expect(screen.queryByText('Loading...')).not.toBeInTheDocument();

条件付き描画のテスト

要素が描画されていないことをアサートするには、存在しない場合にnullを返すqueryByを使用します。存在することを期待する場合はgetByを使用します。

test('shows error message when validation fails', async () => {
  const user = userEvent.setup();
  render(<SignUpForm />);
  await user.click(screen.getByRole('button', { name: /submit/i }));
  expect(screen.getByText('Email is required')).toBeInTheDocument();
});

Providerでラップする

多くのコンポーネントにはContextまたはrouterが必要です。renderの呼び出し内でProviderを使ってラップするか、カスタムのrenderWithProvidersヘルパーを作成します。

function renderWithProviders(ui: React.ReactElement) {
  return render(
    <QueryClientProvider client={new QueryClient()}>
      <MemoryRouter>
        {ui}
      </MemoryRouter>
    </QueryClientProvider>
  );
}

test('shows user data', () => {
  renderWithProviders(<UserProfile />);
});

状態変更のテスト

コンポーネントを操作した後、新しい状態がUIに反映されていることをアサートします。userEventを使用すると、RTLはほとんどの操作を自動的にactでラップします。

test('counter increments', async () => {
  const user = userEvent.setup();
  render(<Counter />);
  expect(screen.getByText('Count: 0')).toBeInTheDocument();
  await user.click(screen.getByRole('button', { name: /increment/i }));
  expect(screen.getByText('Count: 1')).toBeInTheDocument();
});

Screenデバッグヘルパー

screen.debug()を呼び出すと、現在描画されているHTMLをコンソールに出力できます。クエリが失敗し、実際に何が描画されているか確認したい場合に便利です。

test('debugging a failing query', () => {
  render(<MyComponent />);
  screen.debug(); // prints rendered HTML
  screen.getByRole('button', { name: /save/i }); // then inspect output
});

クイックチェック

React Testing Libraryでボタンをテストするとき、どのクエリを優先すべきですか?

まとめ

RTLではコンポーネントを描画し、ロールベースのクエリとuserEventで操作します。必要なProviderでコンポーネントをラップし、読みやすいアサーションにはjest-domのmatcherを使用します。存在しないことをアサートする場合はqueryByを優先します。

よくある質問

「React Testing LibraryによるIntegration Testing」レッスンは無料ですか?

はい。「React Testing LibraryによるIntegration Testing」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、React Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 React Academyコースには全4レッスンが含まれています。

「React Testing LibraryによるIntegration Testing」で何を学びますか?

テスト内でコンポーネントをrenderし、イベントを発生させ、実装ではなく表示結果を検証します。 ブラウザで直接実行するハンズオンコードでReact Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

React Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのReact Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「React Testing LibraryによるIntegration Testing」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このReact Academyレッスンでコードを書いて実行できますか?

はい。すべてのReact Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. React Testing LibraryによるIntegration Testing
  2. MSWによる非同期UIとAPI呼び出しのテスト
  3. React向けPlaywright入門
  4. フォームとユーザーフローのE2Eテスト
← React Academyに戻る