ReactTesting-libraryを用いてReactにテストコードを実装する方法（備忘録）

## はじめに
インターン先でReactを用いてアプリ開発を行っていた際に、目視や手作業での確認だけだと本当に不具合があるかが分からず不安だったので、そこからテストコードについて学び始めました。そのため、まだまだひよっこもいいとこなので、至らぬ点や間違い等ございましたらコメントでご指摘頂けるとありがたいです🙇‍♂️


## testing-libraryとは？
testing-libraryはReactコンポーネントのテストを効果的にしかも簡単に書くことができるJavaScriptテストツールです。
ただtesting-library自体はReactに限定したものでなくVueなどの他のフレームワークにも用いることが出来ます。主にクリックイベント等の実行、レンダリングした内容からの要素取得などが可能であり、ユーザーが実際にコンポーネントを使用する際の振る舞いを簡単にシミュレートすることが可能です。
## 実際に書いてみよう！
今回は一番シンプルで簡単なコンポーネントにある特定の文字列が入っているかのテストを行います。




```react:Sample.jsx
const Sample = () => {
  return (
    <>
      <h1>Hello world!</h1>
      <p>test</p>
    </>
  );
};
export default Sample

```
今回はHello Worldと表示されるコンポーネントを作成したのでこれを用いてテストを行いましょう！

まずはtest用のファイルの作成です。拡張子の`test.js`をつけて下記のようなファイルを作成します。(コードの内容は後ほど詳しく説明します)

```react:sample.test.js
import { render,screen } from "@testing-library/react";
import Sample from "./Sample.jsx"

describe("test Title",()=>{
    it("should render correctly",()=>{
        render(<Sample/>);
        expect(screen.getByText("Hello world!")).toBeInTheDocument()
    })
})

```
まずは今回必要な要素をimportします。今回使う要素は**render**と**screen**です。
各種役割は後述いたします。
この際テストを行うコンポーネントのインポートをお忘れなく！


```react:sample.test.js
import { render,screen } from "@testing-library/react";
import Sample from "./Sample.jsx"
```  
次にどのようなテストを行うかを**describe関数**に書いていきます。
describe関数は第一引数に内容の説明、第二引数にコールバック関数を書きます。

ここで気をつけて欲しいのはあくまでdescribe関数はテストケースをグループ化しているのであり、実際のテストケース自体は**it関数**を用いて実行されます。
it関数もdescribe関数と類似しており、第一引数にテストの説明、第二引数にコールバック関数を用います。
```react:sample.test.js
    //テスト内容のグループ化
describe("test Title", () => {
  it("should render correctly", () => {
    //テスト内容の記述
  });
});
```  

次に`render関数`を呼びます。引数としてテストしたいコンポーネントを渡します。
render関数は、Reactコンポーネントのレンダリングをシュミレートするために使用されます。これにより、コンポーネントがレンダリングされ、テストを行うことができます。

```react:sample.test.js
describe("test Title",()=>{
    it("should render correctly",()=>{
        render(<Sample/>);//引数としてテストしたいコンポーネントを渡す
    })
})
```  
次に要素の取得を行います。その際に**screen**を用いることで簡単にコンポーネントのDOM要素にアクセスすることができます。（DOM操作で言うところのdocumentみたいな）
またどの要素を取得したいかを記述します。取得方法は色々ありますが、今回は``getByText()``を用いて取得を行います。(これもイメージで言うとgetElementByIdみたいな感じだと思ってます)

この関数はテキストによって要素を取得できる関数です。何種類か書き方があり今回のように``getByText("Hello world!")``の場合一語一句間違えてはいけません。ただ、ドキュメント内に特定の文字列が含まれているかを判定したい時があると思います。その時はgetByText(/Hello world/)とスラッシュで囲ってあげると判定することが出来ます。

これらのことを踏まえて、要素を取得する処理を書くと下記のようになります。

```react:sample.test.js
screen.getByText("Hello world!")
```  

これでようやく要素を取得できました。あともう少しです！
ただ、これでは要素を取得したとしても正しいか正しくないかの判定ができません。
テストを行うためにはどういう状態が正しいといえるかを記述しなければいけません。
そこで用いるのが``expect()``関数です。
expect関数は結果を評価する際に使用されます。引数として要素を渡します。

ここで、先ほど取得した要素を渡すと下記のようになります。

```react:sample.test.js
expect(screen.getByText("Hello world!"))
```  
ただこれだけだと、要素があるという判定はできますがDOMにあるかが確証が持てません。
そのため、``toBeInTheDocument()``を用いて判定いたします。
よって下記のようになります。

```react:sample.test.js
expect(screen.getByText("Hello world!")).toBeInTheDocument()
```  
さあ、それではこれらを全て合わせると冒頭に示したコードになります。どうでしょうか？最初に見た時よりはかなり意味が掴めるのではないでしょうか？

```react:sample.test.js
import { render,screen } from "@testing-library/react";
import Sample from "./Sample.jsx"

describe("test Title",()=>{
    it("should render correctly",()=>{
        render(<Sample/>);
        expect(screen.getByText("Hello world!")).toBeInTheDocument()
    })
})
```

## 最後に
こんな長文かつ稚拙の文章に付き合っていただきありがとうございます！
今度はuserEventも含めたもう少し高度なテストのやり方の記事も書きたいと思います！

### 参考記事
* [お世話になったUdemy講座](https://www.udemy.com/course/reacthooksreduxtoolkit/)
* [個人的に一番わかりやすかった記事](https://reffect.co.jp/react/react-test)
* [公式ドキュメント](https://testing-library.com/docs/react-testing-library/intro)