0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Jest入門:JavaScriptのテストフレームワーク

Posted at

Jestとは?

JestはFacebookが開発したJavaScriptのテスティングフレームワークで、Reactアプリケーションをはじめとする多くのJavaScriptプロジェクトで利用されています。設定が少なく、シンプルな構文でテストを書けることから、人気の高いテストツールです。

特徴

  • ✅ ゼロコンフィグで即利用可能
  • ✅ テストの高速実行(並列処理)
  • ✅ スナップショットテストによるUI検証
  • ✅ 柔軟なモック機能
  • ✅ TypeScript対応(ts-jestとの併用)

Jestのインストール方法

JavaScriptプロジェクトの場合

$ npm install --save-dev jest
            or
$ yarn add --dev jest

TypeScriptとの連携

TypeScriptを使っている場合、ts-jestを使って簡単に統合できます。

$ npm install --save-dev ts-jest @types/jest
$ npx ts-jest config:init

package.jsonの設定

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

テストしてみる

ここでは、sum.jsファイル内のsum関数をテストしてみる

sum.js
function sum(a, b) {
  return a + b;
}
module.exports = sum;
sum.test.js
const sum = require('./sum');

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

テストの実行

$ npm test

Jest基本構文(describe, test, expectの使い方)

Jestでは、テストコードを読みやすく整理し、目的ごとにグルーピングして書けます。

1. describe : テストのグルーピング

describe ブロックは、テストをグループ化して意味のある単位にまとめるのに使います。

describe('配列の操作', () => {
  test('配列に要素を追加できる', () => {
    const arr = [];
    arr.push(1);
    expect(arr).toHaveLength(1);
  });

  test('配列から要素を削除できる', () => {
    const arr = [1, 2];
    arr.pop();
    expect(arr).toEqual([1]);
  });
});

✔ メリット

  • テストの構造が明確になる
  • テストの出力に階層構造が反映され、読みやすくなる

2. testit : テストケースの定義

test('1 + 2 = 3になる', () => {
  expect(1 + 2).toBe(3);
});

test と it は完全に同じ動作をします。好みに応じて使い分けられます。

it('1 + 2 = 3になる', () => {
  expect(1 + 2).toBe(3);
});

it は「〇〇すべきだ(it should...)」というBDDスタイルで好まれる

3. expect : アサーション(期待値)

expect は、ある値がどうなるべきかを定義するテストの核心部分です。

expect(actual).matcher(expected);

主な matcher 一覧

Matcher 説明
toBe(value) 厳密な一致(===) expect(1 + 2).toBe(3)
toEqual(obj) オブジェクト/配列の再帰的一致 expect({a: 1}).toEqual({a: 1})
toContain(item) 配列や文字列に含まれる expect(['a', 'b']).toContain('a')
toHaveLength(n) .lengthが特定の値 expect([1, 2]).toHaveLength(2)
toBeTruthy() trueとして扱われる expect(value).toBeTruthy()
toBeFalsy() falseとして扱われる expect('').toBeFalsy()
toThrow() 例外がスローされる expect(() => fn()).toThrow()
resolves, rejects Promiseに対するアサーション await expect(Promise.resolve(1)).resolves.toBe(1)

4. 非同期テストの書き方

async/await を使う

test('データを非同期に取得', async () => {
  const data = await fetchData();
  expect(data).toBeDefined();
});

Promiseで書く

test('Promiseが成功する', () => {
  return expect(Promise.resolve(5)).resolves.toBe(5);
});

5. beforeEach / afterEach などのフック

テストごとの事前・事後処理に使います。

beforeEach(() => {
  // 各テストの前に実行
});

afterEach(() => {
  // 各テストの後に実行
});

また、1回だけ実行したい場合は beforeAll / afterAll を使います。

✅ 実例:すべての構文をまとめたサンプル

describe('User モジュール', () => {
  let users = [];

  beforeEach(() => {
    users = ['Taro', 'Hanako'];
  });

  test('ユーザーを追加できる', () => {
    users.push('Ichiro');
    expect(users).toContain('Ichiro');
  });

  test('ユーザーを削除できる', () => {
    users.pop();
    expect(users).not.toContain('Hanako');
  });
});

スナップショットテスト

ReactなどのUIコンポーネントの出力が変化していないかを検証できます。

import renderer from 'react-test-renderer';
import MyComponent from './MyComponent';

test('snapshot test', () => {
  const tree = renderer.create(<MyComponent />).toJSON();
  expect(tree).toMatchSnapshot();
});

モックの使い方

関数やモジュールの動作をモック(偽の動作)に置き換えて、依存を排除してテストできます。

  • 関数のモック

    const fetchData = jest.fn(() => 'mocked data');
    
    test('returns mocked data', () => {
      expect(fetchData()).toBe('mocked data');
    });
    
  • モジュールのモック

    jest.mock('./api');
    
    import { fetchUser } from './api';
    
    fetchUser.mockResolvedValue({ name: 'Taro' });
    
    test('mock API response', async () => {
      const user = await fetchUser();
      expect(user.name).toBe('Taro');
    });
    
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?