40
44

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【翻訳】Jestの使い方

Last updated at Posted at 2017-03-03

この記事はJestのドキュメントを和訳したものです。また、定期的に更新される予定です。

はじめに

Painless JavaScript Testing

Jestのホームページでは、次の3点をJestの特徴としています。

  1. Easy Setup
  2. Instant Feedback
  3. Snapshot Testing

自分なりにまとめると、JestはJavaScriptで記述された様々なコードを簡単にテストでき、テスト実行時には前回の保存から変更があったものだけをチェックするように最適化されていて、時系列に沿った状態の変遷まで可視化することができる、ということでしょうか。ぜひマスターしたいものです。

目次

  1. Getting Started
  2. Snapshot Testing
  3. Testing React Apps

1. Getting Started

以下のリンクの和訳が中心となっています。
https://facebook.github.io/jest/docs/getting-started.html

npmを利用してインストールを行います。

$ npm install --save-dev jest

上述の--save-devオプションを利用することで、テストを行うプロジェクトにあるpackage.jsonにJestがリストアップされます。

それでは、二つの数字の和を求めるように設計された関数をテストしてみます。以下のようにsum.jsを作成します。

sum.js
function sum(a, b) {
  return a + b;
}
module.exports = sum;

module.exportsとは、コードが記述されているファイルをmoduleとして扱い、exportsしたオブジェクトをrequireキーワードを利用して呼び出すことができるようにするための記述です。

それでは、sum.test.jsという名前のファイルを作成し、テストコードを書いてみましょう。

sum.test.js
const sum = require('./sum');

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
})

上記のテストコードを実行するために、package.jsonに以下の設定を追加してください。

package.json
"scripts": {
  "test": "jest"
}

それでは、登録したコマンドを実行してみましょう。

$ npm test

PASS ./sum.test.js
✔︎ adds 1 + 2 to equal 3(5ms)

このようにして、テストコードを作成し、実行することができます。

個人的な感想ですが、テストコードがすごく読みやすいですね。'expect sum of 1 and 2 is expected to be 3'のように、英語の文法そのものになるように設計されているみたいです。

2. Snapshot Testing

以下のリンクの翻訳が主となっています。
https://facebook.github.io/jest/docs/snapshot-testing.html

2.1 Snapshot Testingとは?

スナップショットテストとは、作成したUIが予期せずに変化してしまわないか確認するための優れたツールのことを指します。

Jestを利用してスナップショットテストを行う

典型的なスナップショットテストでは、レンダリングされたUIのスクリーンショットを撮り、テストコードで指定したイメージと比較して、同様であるかどうか確かめるといったことが行われます。

Reactコンポーネントのテストにおいても同様のアプローチを取ることができそうです。UIをグラフィカルにレンダリングする代わりに、テスト用のレンダラーをReactのコンポーネントツリーを対象にシリアライズ可能な形式で出力します。これにより、逐一アプリケーション全体を組み立てる必要がなくなり、リソースを消費しないテストが可能になります。

以下のようにして、Linkコンポーネントをテストしてみましょう。
なお、コンポーネント自体のコードは次のリンクにあります。

import React from "react";
import Link from "../Link.react";
import renderer from "react-test-renderer";

it('renders correctly', () => {
  const tree = renderer.create(
    <Link page="http://www.facebook.com">Facebook</Link>
  ).toJSON();
  expect(tree).toMatchSnapshot();
});

最初にこのテストコードを実行した時に、Jestは以下のようなsnapshot fileを生成します。

exports[`Link renders correctly 1`] = `
<a
  className="normal"
  href="http://www.facebook.com"
  onMouseEnter={[Function]}
  onMouseLeave={[Function]}>
  Facebook
</a>

スナップショットはコードの変更に伴って生成されるでしょう。Jestではpretty-formatを利用し、人間が読みやすい形式でコードのレビューを示してくれます。はじめのスナップショットテスト以降、テストそのものは、その一つ手前のテストとのシンプルな比較となります。それらが合致した場合、テストは成功とみなされます。もしも合致しなかった場合は、テストランナーが修正すべきバグを通知してくれるか、スナップショットが更新される必要があることを教えてくれます。

Updating Snapshots

バグが発見された場合に、スナップショットテストが失敗するのは明らかです。そのような場合は、ふたたびテストが通るように修正してください。

テストが成功するスナップショットそのものの更新を行いたい場合は、以下のコマンドを実行してください。

$ jest --updateSnapshot

3. Testing React Apps

Facebookでは、ReactのテストにJestを利用しています。

個人的に一番知りたいのがReactのテストの方法でした。気合いを入れて書きます。
また、ここでは既存のReactアプリケーションをテストする場合について書きます。

Setup

既存のアプリケーションがある場合は、テストコードを動かすために幾つかのパッケージをインストールする必要があります。以下のコマンドを実行してください。

$ npm install --save-dev jest babel-jest babel-preset-es2015 babel-preset-react react-test-renderer

コマンドを実行後、package.jsonに正しくパッケージがインストールされていることを確認してください。  
確認ができましたか?テストをする準備は万全です。

React ComponentのSnapshot Testing

ハイパーリンクをレンダリングするLinkコンポーネントのスナップショットテストを作成しましょう。

Link.react.js
import React from 'react';

const STATUS = {
  NORMAL: 'normal',
  HOVERED: 'hovered',
};

export default class Link extends React.Component {

  constructor(props) {
    super(props);

    this._onMouseEnter = this._onMouseEnter.bind(this);
    this._onMouseLeave = this._onMouseLeave.bind(this);

    this.state = {
      class: STATUS.NORMAL,
    };
  }

  _onMouseEnter() {
    this.setState({class: STATUS.HOVERED});
  }

  _onMouseLeave() {
    this.setState({class: STATUS.NORMAL});
  }

  render() {
    return (
      <a
        className={this.state.class}
        href={this.props.page || '#'}
        onMouseEnter={this._onMouseEnter}
        onMouseLeave={this._onMouseLeave}>
        {this.props.children}
      </a>
    );
  }

それでは、テストコードを書いていきましょう。

Link.react-test.js
import React from 'react';
import Link from '../Link.react';
import renderer from 'react-test-renderer';

test('Link changes the class when hovered', () => {
  const component = renderer.create(
    <Link page="http://www.facebook.com">Facebook</Link>
  );
  let tree = component.toJSON();
  expect(tree).toMatchSnapshot();

  // manually trigger the callback
  tree.props.onMouseEnter();
  // re-rendering
  tree = component.toJSON();
  expect(tree).toMatchSnapshot();

  // manually trigger the callback
  tree.props.onMouseLeave();
  // re-rendering
  tree = component.toJSON();
  expect(tree).toMatchSnapshot();
});

npm testを実行すれば、以下のような内容のファイルを生成します。

Link.react-test.js
import React from 'react';
import Link from '../Link.react';
import renderer from 'react-test-renderer';

test('Link changes the class when hovered', () => {
  const component = renderer.create(
    <Link page="http://www.facebook.com">Facebook</Link>
  );
  let tree = component.toJSON();
  expect(tree).toMatchSnapshot();

  // manually trigger the callback
  tree.props.onMouseEnter();
  // re-rendering
  tree = component.toJSON();
  expect(tree).toMatchSnapshot();

  // manually trigger the callback
  tree.props.onMouseLeave();
  // re-rendering
  tree = component.toJSON();
  expect(tree).toMatchSnapshot();

次回テストを実行した際には、出力されたスナップショットは、以前作成されたスナップショットと比較されます。

jest -uを実行することで、スナップショットを上書きすることができます。

40
44
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
44

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?