Jest + enzymeでフロントエンドテストと戦った(Part1)


はじめに

ここ最近フロントエンド開発で、テスト書きまくったのでその知見を残しておきたいだけの記事です。
あと僕が長文書けないので3つくらいに分けてまとめていきます。

インストール

$ npm install --save-dev jest
$ npm install --save-dev enzyme jest-enzyme

実行

package.jsonに下記を追加 -> yarn testで実行する。

{
  "scripts": {
    "test": "jest"
  }
}

これからjestの記法をレベルに応じて列挙して行こうかなと思います。

レベル1(基本的文法)

まずは基本の基本。下記に簡単なテストを書きました。

describe('足し算', () => {
  it('2 + 3 = 5', () => {
    const result = 2 + 3
    expect(result).toBe(5)
  });
});

足し算の結果があってるかをテストしました。
Jestでは describeit を使いテストケースを記載していきます。
個人的にはdescribeは大きいまとまりを作って、itはそのdescribeに沿ったより具体的なテストケースを記載すると思っています(この部分は人それぞれで使い方が違うと思います)。

expectでテストが合ってるかを判定します。
describe,it,expectはどのテストを書くにしても必ず出てきます。

レベル2(マッチャー)

Matcher(マッチャー)といわれるものがありまして、これは等価性を判定するテストです。
先ほどのレベル1で出てきたテストもマッチャーテストです(足し算の結果が予測した値と同じか否か)。

toBe(5)の部分です。
逆に「ではない」と意味合いを込めてテストしたい場合は、notを使用します。

describe('足し算', () => {
  it('2 + 3 = 5', () => {
    const result = 2 + 3
    expect(result).not.toBe(6)
  });
});

他にもtoBeEqualというマッチャーもあって、これはオブジェクトまたは配列を評価する際に使用します。

it('object assign', () => {
  const object = {one: 1};
  object['two'] = 2;
  expect(object).toEqual({one: 1, two: 2});
});

あとは
expect(value)において、valueが

  • toBeNull ... nullの時に一致する
  • toBeUndefined ... undefinedの時に一致する
  • toBeDefined ... undefined以外に一致する
  • toBeTruthy ... trueの時に一致する
  • toBeFalsy ... falseの時に一致する

となります。いわゆる特定の値かどうかを知りたい場合にこういうヘルパーメソッドを使います。

レベル3(イベント)

徐々にフロントエンドっぽくなってきますが、Webサイトにアクセスしたらユーザーは何かしらのアクションを起こします。例えばボタンクリックしたり、ログインしてマイページに遷移したり、まあキリがないくらいいろんな行動があります。そういうユーザーアクションが正しく動作してるかをテストします。

ここでよく使われるメソッドは

  • toHaveBeenCalled
  • simulate

です。

例えば下記のようなボタンに対して

export const Sample: React.FC = () => {
  return <Button onClick={onClickEvent}>button</Button>
}

に対して、このボタンがちゃんとクリックされるとイベントが発火されるかを確かめます。

describe('click event', () => {
  it('Button', () => {
    const wrapper = shallow(<Sample />)
    wrapper.find(Button).simulate('click')
    expect(onClickEvent).toHaveBeenCalled()
  })
})

shallowというのは簡単に言うとコンポーネントをテスト上で表示するメソッドです。
コンポーネントからButtonタグを探して(find)、そのボタンをクリックするシミュレートをかけます。(ここがユーザの動作アクション)
で、最終的にクリックしたら、ButtonのonClick属性が機能しているかをexpect(onClickEvent).toHaveBeenCalled()で評価しています。

toHaveBeenCalledには他にも似たようなメソッドがあって、toHaveBeenCalledTimes(メソッド等が何回呼ばれたかを判定する)やtoHaveBeenCalledWith(メソッドで呼ばれた結果は何かを判定する)といったメソッドもあります。

その他

先ほども出てきましたが、テストでは下記のような書き方が頻繁に出てきます。
頻繁に出てくるような書き方を各itごとに書くのは面倒なのでこの部分も効率化できます(具体的にはbeforeEachというのがあって、itが呼ばれる前に実行してくれます)

const wrapper = shallow(<Sample />)
wrapper.find(Button).simulate('click')

この記事はここまで。
次回の記事でお会いしましょう。