React × TypeScript環境にJestを導入してみて

こちらは「ウィルゲートAdvent Calendar 2019」12日目の記事です。 昨日のアドベントカレンダー記事はこちらです。
こんにちは!フロントエンドエンジニアの小澤(@rikipedia_uw)です。今回はReact×TypeScriptで作られた新規開発中のサービスにJestを導入した話をします。

Jestとは?

Facebook社がOSSとして開発を進めているJavaScriptのテストフレームワークで、JavaScriptでテストを実行するために必要な

  • テストランナー
  • アサーション
  • テストモック・テストダブル

がコミコミで入っています。

それぞれ単体の機能を提供するライブラリにはテストランナーの機能を提供するKarmaや、アサーションの機能を提供するChaiなどがありますが、複数のライブラリを組み合わせて使うのはしばしば困難に見舞われます。 その点で一通り揃っているJestは使いやすいといえます。

そのほかにも、スナップショットテスト機能もありReact(こちらもFacebook謹製)との親和性も高いのが特徴です。

github.com jestjs.io

React × TypeScript環境でJestを使う場合の設定

まずはnpm経由で必要なライブラリをインストールします。

$ npm install --save-dev jest @types/jest ts-jest

ts-jestはJest用のTypeScriptプリプロセッサです。このライブラリをインストールすることにより、Jestは実行時にTypeScriptをトランスパイルすることができ、ソースマップの出力もしてくれます。

babelを使っているなら追加で必要なライブラリをインストールします。

$ babel-jest @babel/core @babel/preset-env

インストールしたライブラリをpackage.jsondevDependenciesに追加しましょう。

package.json
"devDependencies": {
    ...
    "@babel/core": "^7.6.4",
    "@babel/preset-env": "^7.6.3",
    "babel-jest": "^24.9.0",
    "jest": "^24.9.0",
    "ts-jest": "^24.1.0",
    ...
} 

次にJestの設定をします。jest.config.jsに書いてもいいですが、私はpackage.jsonに書いてしまうのが好きです。

package.json
"jest": {
    "transform": {
      "^.+\\.(js|jsx|mjs)$": "babel-jest",
      "^.+\\.(ts|tsx)$": "ts-jest",
    },
    "transformIgnorePatterns": [
      "/node_modules/(?!(xxxx.*?\\.js$))"
    ],
    "testRegex": "(/test/.*|\\.(test|spec))\\.(ts|tsx|js)$",
    "testPathIgnorePatterns": [
      "/node_modules/"
    ],
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js",
      "json"
    ],
    "moduleNameMapper": {
      "@(components|helper|redux|config|modules|style)?/(.*)": "<rootDir>/src/$1/$2",
      "\\.(css|less|scss|sss|styl)$": "<rootDir>/node_modules/jest-css-modules"
    },
    "testURL": "https://example.koko.jp"
  }

それぞれの設定項目について説明します。

transform

正規表現で指定した拡張子のファイルをトランスパイルする設定です。ts-jest.tsまたは.tsxのファイルに対してトランスパイルが実行されます。 babelでトランスパイルされたJSファイルがある場合は babel-jest をインストールすることでbabelへのサポートを有効にできます。

transformIgnorePatterns

正規表現で指定したファイルをトランスパイル対象から除外します。基本的にはnode_modules配下のファイル群を指定するのが無難でしょう。

testRegex

テスト対象ファイルのパターンです。

testPathIgnorePatterns

テスト対象から除外するパターンです。こちらも基本的にはnode_modules配下のファイル群を指定するのが無難です。

moduleFileExtensions

テスト対象の拡張子を指定します。React × TypeScript環境なら.ts/.tsxを指定しましょう。

moduleNameMapper

テストファイルから省略パスでインポートするためのエイリアスを設定します。 後に後述するtsconfig.jsonでのエイリアスと合わせるのが無難です。

sample.ts
// ルートディレクトリからの絶対パスで書かなければならない
import Component from '/src/components/Component'

// エイリアスを設定することで省略して書ける
import Component from '@components/Component'

これでJestが実行できるようになりました。test/xxxx.ts にテストコードを書くと、Jestがテストファイルを実行してくれるようになります。 実際のテストの様子は、私が過去にJestについて話した資料もあるので載せておきます。

speakerdeck.com

終わりに

今回はReact × TypeScript環境にJestを導入する方法をご紹介しました。テストコードの書き方についてはJest公式ドキュメントの方が詳しいので、そちらご覧ください。

明日のアドベントカレンダーは @michimasa さんの「エンジニアの成長させるために必要なこと」です。乞うご期待!