KAKEHASHI Tech Blog

カケハシのEngineer Teamによるブログです。

Angular テストフレームワーク を jasmine/karma から Jest に移行しました

概要

薬局運営のデータ分析サービスである Musubi Insight のフロントエンド開発をしております米山と申します。

Musubi Insight のフロントエンドは Angular で開発されており、テストフレームワークには jasmine/karma を利用していました。

この度、jasmine/karma から Jest に移行しましたので、移行の記録を書いていきます。

移行理由

jasmine/karma は Angular のデフォルトのテストフレームワークです。

しかし、JavaScript のテストフレームワークとして、jasmine/karma の利用人口が減少傾向にあることが気になっていました。

(state of js 2021 より)

という理由が1点。

さらに、データ分析サービスである Musubi Insight では、巨大な JSON データを扱うことがよくあります。

そこで、Jest の持つスナップショットテストの機能は魅力的でした。

以上の理由から、Jest への移行を決断しました。

移行手順

以下、Jest への移行手順を1つずつ書いていきます。

環境設定

まずは、Jest を動かすための基本設定です。

必要なパッケージをインストールし、設定ファイルを作成してきます。

$ npm i -D jest @types/jest jest-preset-angular

$ touch jest.config.js src/setup-jest.ts

jest.config.js は以下のように記載。

module.exports = {
  preset: 'jest-preset-angular',
  setupFilesAfterEnv: ['<rootDir>/src/setup-jest.ts'],
  globalSetup: 'jest-preset-angular/global-setup',
  testMatch: ['<rootDir>/src/**/*.spec.ts'], // テスト実行対象のファイルを含めるようにしてください
};

setup-jest.ts は以下の1行を記載。

import 'jest-preset-angular/setup-jest';

不要になったパッケージを削除し、古い設定ファイルを削除します。 パッケージの一覧はご自身のプロジェクトが利用していたものを列挙してください。

$ npm uninstall jasmine-core karma karma-chrome-launcher karma-coverage-istanbul-reporter karma-jasmine karma-mocha-reporter @types/jasmine @types/jasminewd2

$ rm karma.conf.js src/test.ts

パス解決

TypeScript で paths 設定をしている場合、Jest config に Paths mapping 設定を追加します。

もし、tsconfig で以下のような設定をしているなら、

// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@App/*": ["src/*"],
      "lib/*": ["common/*"]
    }
  }
}

jest.config.js には、以下の行を追加します。

// jest.config.js
module.exports = {
  // [...]
  moduleNameMapper: {
    '^@App/(.*)$': '<rootDir>/src/$1',
    '^lib/(.*)$': '<rootDir>/common/$1',
  },
}

テストコード 自動修正

テストコードの修正です。

Jest 公式のマイグレーションガイドがあります。

以下のコマンドを発行することで、自動的にある程度のテストコードが Jest のものに置き換わります。

$ npx jest-codemods

いくつか質問事項があるので、自身の環境に合わせて回答していきます。

スクリーンショット 2022-04-12 18.21.07.png (37.5 kB)

テストコード 手動修正

jest-codemods で修正されなかった箇所は手動で対応していきます。

まずは型修正。

jasmine.Spyjest.Mockjest.SpyInstance に書き換えます。

また、モックの返り値指定も一部手動修正が必要でした。Jest での書き方は以下の通り。

// 空オブジェクトの Observable 設定する場合
mockFn.mockReturnValue(of({}))

// 空オブジェクトの Observable を返す場合
mockFn.mockImplementation(() => of({}));

// ハンドルされるエラーを返す場合
mockFn.mockImplementation(() => throwError(() => new Error()));

// ハンドルされないエラーを返す場合
mockFn.mockImplementation(() => {
  throw Error('');
});

また、タイムアウトの設定も自前で修正しました。

jasmine での設定は以下の通り。

describe('', () => {
  let interval;
  beforeEach(() => {
    interval = jasmine.DEFAULT_TIMEOUT_INTERVAL;
    jasmine.DEFAULT_TIMEOUT_INTERVAL = 60_000; // 60秒に延長
  });
  afterEach(() => {
    // 復元
    jasmine.DEFAULT_TIMEOUT_INTERVAL = interval;
  });

Jest では、beforeEach の第2引数や、it(あるいは test)の第3引数として設定可能です。

describe('', () => {
  beforeEach(() => {}, 60_000); // 最長60秒まで待つ

  it('', () => {}, 100_000); // このテストは100秒

jasmine の書き方によっては、他にも手動で書き換えるべき箇所があるかもしれません。

ESLint 設定

ESLint を Jest に対応させます。

npm install --save-dev jest-eslint-plugin

.eslintrc.json の設定も、以下のように修正。

{
  "env": {
    "jest/globals": true
  },
  "extends": [
    // ...
    "plugin:jest/recommended",
    "plugin:jest/style",
  ],
  "plugins": [
    // ...
    "jest"
  ],
  // ...

これで、Jest のコードフォーマットをある程度統一することができます。

plugin:jest/recommendedplugin:jest/style への対応のためのコード修正については、ここでは割愛します。

VSCode

筆者は VSCode を利用して開発を行っており、今回 Jest のための VSCode 拡張を2つインストールしました。

おしまい

以上、Angular プロジェクトの jasmine/karma を Jest に移行した記録でした。

何かの参考になれば幸いです。

参考記事

Jest 移行に関して、参考にさせていただいた記事。