AngularのテスティングフレームワークにJestを利用する

AngularのテスティングフレームワークにJestを利用する

AngularのテスティングフレームワークはJasmine + Karmaがデフォルトで用意されている。便利な半面実行が遅く、効率よくフィードバックを得ながらテストを書くにはリズムが悪い。

解決策として、世界で今最も支持されているであろうJestを使用すれば、Angularのユニットテストの実行は格段に早くなる。

この記事ではAngularアプリケーションにJestを適用する方法を紹介したいと思う。

Jestとは?

JestはFacebookが開発しているJavaScriptのテスティングフレームワーク。

Jest · 🃏快適なJavaScriptのテスト

ユニットテストの実行速度が早いことに加えて、スナップショットテストや強力なモック機能など使い勝手が良く、最近では一番使われているテスティングフレームワークです。

Jasmineと同じく expect(a).toBe(true) といったBDDスタイルのアサーションなので、導入ハードルは比較的低い。

Jestへの変更

Angular CLIでテスティングフレームワークをJestに置き換えるnpmパッケージ(Angular Schematics)が公開されているので、これを使う。

https://github.com/briebug/jest-schematic

はじめにnpmパッケージをグローバルにインストールする。

$ npm install -g @briebug/jest-schematic

次にAngularプロジェクトにターミナルで移動して以下のコマンドを実行。

$ ng g @briebug/jest-schematic:add

実行すると不要なファイルは削除され、Jestなどの必要なパッケージのインストールと以下のファイルが生成される。

  • jest.config.js
  • src/setup-jest.ts
  • src/test-config.helper.ts

次に関連ファイルの修正を行う。

src/tsconfig.spec.json

types"jasmine" から "jest" に変更する

{
  "compilerOptions": {
    "outDir": "../out-tsc/spec",
    "types": [
      "jest", // jasmine -> jest に変更
      "node"
    ],
    "module": "commonjs"
  },
}

src/setup-jest.ts

2行目以降を削除して以下に書き換える。

import 'jest-preset-angular';
import './jest-global-mocks';

src/jest-global-mocks.ts を新規作成して以下の内容を記述する。

/* global mocks for jsdom */
const mock = () => {
  let storage: { [key: string]: string } = {};
  return {
    getItem: (key: string) => (key in storage ? storage[key] : null),
    setItem: (key: string, value: string) => (storage[key] = value || ''),
    removeItem: (key: string) => delete storage[key],
    clear: () => (storage = {})
  };
};

Object.defineProperty(window, 'localStorage', { value: mock() });
Object.defineProperty(window, 'sessionStorage', { value: mock() });
Object.defineProperty(window, 'getComputedStyle', {
  value: () => ['-webkit-appearance'],
});

Object.defineProperty(window, 'CSS', {value: null});
Object.defineProperty(document, 'doctype', {
  value: '<!DOCTYPE html>'
});
Object.defineProperty(window, 'getComputedStyle', {
  value: () => {
    return {
      display: 'none',
      appearance: ['-webkit-appearance']
    };
  }
});
/**
 * ISSUE: https://github.com/angular/material2/issues/7101
 * Workaround for JSDOM missing transform property
 */
Object.defineProperty(document.body.style, 'transform', {
  value: () => {
    return {
      enumerable: true,
      configurable: true,
    };
  },
});

/* output shorter and more meaningful Zone error stack traces */
// Error.stackTraceLimit = 2;

ここではMock用の設定をまとめている。

合わせて @types/jest もインストールしておく。

$ npm i -D @types/jest

基本はこれで完了。

テストの実行

テストの実行はコマンドが書き換えられているので、 npm test を実行すればいい。

$ npm test

また上記は単発の実行で、 npm run test:watch でwatchモードで実行できる。自分は package.json を書き換えて npm test でwatchするようにしている。

{
  "scripts": {
    ...
    "test": "jest --watch",
    ...
  },
}

テストを走らせる場合は大体watchしながら走らせるので、test:watch のほうは消してしまっていいと思う。

Jestの設定

jest-schematicの中では以下のJest presetを利用してJestの設定を行っているため、目を通しておくと良い。

https://github.com/thymikee/jest-preset-angular

五十川 洋平(Yohei Isokawa)

五十川 洋平(Yohei Isokawa)

フロントエンドエンジニア/面白法人カヤックなどのWeb制作会社に勤務したのち、故郷の新潟に戻り独立。JSフレームワークAngularやFirebase、Google Cloud Platformを使ったWebアプリ開発が得意。Udemyでプログラミング解説の講師や、ドローンを使った映像制作も行っています。

プロフィール