React と Jest で Unit test を始めよう

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ReactJestUnit test を始めよう

保守性の高いコードが書けていますか?

ReactComponent構成 ~ Unit test までの流れを書いています。
Unit testがあると、保守しながら長くメンテナンスしていけるコードになるので、
開発の助力になればと思います。

本題の前に

React とは

オープンソースのJavaScriptフレームワークであり、
フロント系では、3大フレームワークと言われ、先進的な機能が多く人気があります。

Jest とは

JavaScriptUnit testのためのツールです。
React, Jestは、Facebookが開発を進めています

わかる事

  • Atomic Component のディレクトリ構成 (atoms)
  • atomsComponentUnit test

触れないこと

  • React, Jest の基本的な構文

Atomic Component のディレクトリ構成

Unit testする場合、このようなディレクトリ構成が見通し良いのでおすすめです。

$ tree
atoms/
└── MyButton
    ├── index.test.tsx
    └── index.tsx

アンチパターンではありませんが 下記の様なディレクトリ構成の場合

  • MyButtonmyButton でファイル名に統一性がない
  • MyButton.story.tsx などを追加したい場合さらに増える (*storybook)
  • 全体の見通しが悪い
$ tree
atoms/
├── myButton.test.tsx
└── MyButton.tsx

Vueで開発する際も、この構成で開発しています

ComponentUnit test

Componentの概要

props で ボタンのテキストをうけとる
click 時はhandleClickで、処理を呼び出す

と なんの変哲もないcomponentです

// index.tsx

import React from 'react'

interface Props {
  txt: string
  handleClick: () => void
}

export type ButtonProps = Props

export const MyButton: React.FC<Props> = ({ txt, handleClick }) => (
  <>
    <button onClick={ handleClick }>
      { txt }
    </button>
  </>
)

Unit testの概要

ボタンテキストが正しく表示されているか確認
handleClickの確認

// index.test.tsx

import React from 'react'
import { MyButton, MyButtonProps } from '.'
import { mount } from 'enzyme'

describe('MyButton', () => {
  it('ボタンテキストが正しく表示されているか確認', () => {
    const props: ButtonProps = {
      txt: 'MyButtonTxt',
      handleClick: () => {}
    }

    // propsを受け取り mount テスト対象component生成
    const wrapper = mount(<Button {...props} />)

    // { txt }にpropsで受け取った値が表示されているか確認
    expect(wrapper.text()).toBe(props.txt)
  })

  it('clickイベントの確認', () => {
    const props: ButtonProps = {
      txt: 'MyButtonTxt',
      handleClick: jest.fn
    }

    // handleClickの監視
    const spyHandleClick = jest.spyOn(props, 'handleClick')

    // propsを受け取り mount テスト対象component生成
    const wrapper = mount(<Button {...props} />)

    // clickイベント実行
    wrapper.find('button').simulate('click')

    // spyHandleClickが実行されたか確認
    expect(spyHandleClick).toHaveBeenCalled()
  })
})

まとめ

Atomic Component の構成にすることのメリット

  • テストがしやすい
  • ディレクトリの見通しが良い
  • 再利用性が高い

Atomic Component の構成にすることのデメリット

  • 1ファイル全て書く方式よりは、ファイル数が増える

1ファイルの行数が長いとUnit testの際に苦労する場合が多いです。
実際の開発では、機能追加が発生すると思います。
その際バグを含まない用に、Unit testをしっかり導入していきましょう。