【備忘録】Reactのユニットテストライブラリを比較する

# はじめに
この記事は React のユニットテストライブラリを選定するにあたって調査した内容をメモした備忘録になります。

# Reactのユニットテストライブラリを比較する

## 目的
機能追加や改修などの影響によって発生する予期せぬ不具合を検知するため、React コンポーネントのユニットテストを行う。

## 要件
- TypeScript に対応していること。
- React コンポーネントのテストができること。

## 結論
**Jest** + **React Testing Library** が良さそう。

## 調査
### 前提
Reactのユニットテストで検索すると、以下のライブラリについての記事がよく出てくる。
- Jest
- React Testing Library
- Enzyme

いずれも、TypeScript に対応している。

### **Jest** とは

- オールインワン / ゼロコンフィグな JavaScript テスティングフレームワークのこと。
- React というよりも、JavaScript をテストするためのフレームワークである。
- Jest を導入するだけで以下の機能が使えるようになる。
例として記載しているものは、その機能を単体で利用するために用いられるライブラリの一例である。
  - テストランナー（例 **mocha, jasmine**）
  - アサーション（例 **chai, jasmine**）
  - モック（例 **sinon, testdouble**）
  - カバレッジ（例 **istanbul**）

### **Enzyme** とは
- **React** でのユニットテストを助けてくれるテストユーティリティツールのこと。
- 元々 Airbnb が開発していた。
- Enzyme は TDD(Test-Driven Development) で求められるようなロジックのテストに向いている。
- Shallow Rendering という、親子コンポーネントを無視した特定コンポーネントだけのレンダリングができ、テストが書きやすい。
- Airbnb によって開発されていたが、今は enzymejs という組織に所有権を譲渡している。
- AirbnbはEnzyme への貢献を続けることを表明しているが、組織内での React Testing Library の使用が増加しているらしい。

### **React Testing Library** とは
- Enzyme と同様に、UI コンポーネントのユニットテストを助けてくれるテストユーティリティツールである。
- Reactだけでなく、Vue や Angular, Svelte といった他のフロントエンドフレームワークや、Cypress や TestCafe といった E2E テストツールとも組み合わせて利用することができる。
- React Testing Library は BDD(Behavior-Driven Development) で求められるような、ユーザーの行動を元にしたテストに向いている。

### React公式ドキュメントより
- React は Jest と React Testing Library を[推奨ツールとしている](https://ja.reactjs.org/docs/testing.html#tools)。
- 元々、React は EnzymeとReact Testing Library の両方について言及していたらしいが、現在は Enzyme についての記述はない。

### NPMより
- npm trends のダウンロード数を比較すると、2020/09 ごろに React Testing Library が優勢になっている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2160256/72288dbb-7b9c-2572-dbdf-51aed3d42767.png)


### テストコードの比較
#### Enzyme
- Enzyme は React のメジャーバージョンごとに、`enzyme-adapter-react-**`というライブラリを提供しており、テストを行う際にはその設定を行う必要がある。(L. 7)
- 2022年12月現在、React17 に対応したアダプターはまだリリースされていない。

```jsx:enzyme-sample.test.jsx
import React from "react";
import Adapter from "enzyme-adapter-react-16";
import { shallow } from "enzyme";
import App from "../src/App";
import { configure } from "enzyme";

configure({ adapter: new Adapter() });

describe("Hello enzyme", () => {
  test("have title", () => {
    const wrapper = shallow(<App />);
    expect(wrapper.text().includes('Hello CodeSandbox')).toBe(true);
  });
});
```

#### React Testing Library

- メソッド名もわかりやすく、TestCafe に近いものを感じる。

```jsx:rtl-sample.test.jsx
import React from "react";
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import App from "../src/App";

test("loads and displays greeting", async () => {
  render(<App />);
  expect(screen.getByText("Hello CodeSandbox")).toBeInTheDocument();
});
```

## 所感

- 公式が推しているので Jest と React Testing Library の組み合わせが有力そう。
- Enzyme の Shallow Rendering は魅力的だが、Jest のモックで代用できるので必須ではない。
- ユーザーの行動を元にしたテストのほうが、よりわかりやすく意味のあるテストが書けるので、テストが書きやすいと考えられる。
- コンポーネントのロジックをテストする際は、Jest で十分だと思われる。
例) 表示位置の座標計算、バリデーション、etc…
- Vue などの他のフロントエンドフレームワークに移った際や、E2E を書く際にも利用できるのは大きなメリットであると思う。
- Airbnb が React Testing Library に流れていることからも、将来性は React Testing Library の方がありそう。

# おわりに
備忘録的な記事になりますが、少しでも誰かのお役に立てると幸いです。
間違いを見つけた場合や、もっとこうするとわかりやすいなどのご意見があれば、
ぜひコメントしていただけると嬉しいです。