KAKEHASHI Tech Blog

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

テスト用にtsconfig.jsonを分けてみた

「株式会社カケハシ x TypeScript Advent Calendar 2021」18日目の記事です。 https://qiita.com/advent-calendar/2021/kkhs-ts

プラットフォームチームのエンジニアさだです。

私たちの環境ではテストコードもTypeScriptで書いていて、jest + ts-jestを利用しています。 色々な事情があって、プロダクトコード用のtsconfigとは別にテスト用のtsconfigを作らなきゃいけない場合ってありますよね。 そんな方にお伝えしたいのがこちら💁

https://kulshekhar.github.io/ts-jest/docs/getting-started/options/tsconfig

// jest.config.js
module.exports = {
  // [...]
  globals: {
    'ts-jest': {
      tsconfig: 'tsconfig.test.json',
    },
  },
}

ts-jestのオプションでtsconfig.jsonのパスを指定できます。

最善ではないけれど、テストコードでtsconfigをユルくしたい

AWS CDKのスタックを新規作成し既存リポジトリに追加したときのことです。 スタックを新規作成するので、当然テストコードも新規作成します。 cdk init するとサンプルのテストコードも自動生成してくれるので、まずこのテストがパスすることを確認しようとしたわけです。

するとどうでしょう、次のようなエラーが発生し、テストが失敗したのです。

TypeError: Class constructor Stack cannot be invoked without 'new'

調べてみるとこのエラーはJavaScirptへtranspileするときのターゲットバージョンが問題とのこと。 いやいや、ちゃんとtsconfig.jsonには “target”: “ES2018” と書いてありますよ。

ts-nodeのドキュメント(冒頭のリンク先)によると、自動的に探して読み込んでくれると書いてありますが、もし見つからなかったら ES2015 にするとも書いてあります。 どうやらこれなのかな。 (正確には、このエラーが出るのはtargetが ES5 の場合なので、ts-jestのドキュメントに書いてあることもちょっと違うような……。)

そこでプロダクトコード用に使っている既存のtsconfig.jsonのパスをtsconfigオプションとして指定してあげました。すると先ほどのエラーは解消したものの、ESLintのエラーが大量に出るわ出るわ。 個別にシューティングしていくのはちょっと骨が折れるので、 compilerOptions をユルくしてあげてその場はしのぐことにしました。

このような経緯からプロダクトコード用とは別にテスト用のtsconfig.jsonを作成することにしたわけです。 あまりオススメしませんが、私たちの環境ではcompilerOptionsを以下のようにしました。

{
  "compilerOptions": {
    "target": "ES2018",
    "module": "commonjs",
    "lib": ["esnext"],
    "alwaysStrict": true,
    "declaration": true,
    "experimentalDecorators": true,
    "inlineSourceMap": true,
    "inlineSources": true,
    "noFallthroughCasesInSwitch": false,
    "noImplicitAny": false,     // "TS7018: Object literal's property '*' implicitly has an 'any' type." が出たので無効化
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noUnusedLocals": false,
    "noUnusedParameters": true,
    "strict": true,
    "strictNullChecks": false,  // "TS2345: Type 'undefined' is not assignable to type 'string'" が出たので false無効化
    "strictPropertyInitialization": false,
    "typeRoots": ["./node_modules/@types"]
  }
}

もし今回のような方法を採らなかった場合、テストコードはES5で実行されることになるので、ないよりマシという考えのもと、テスト用にtsconfig.jsonを作成してみました。 本来はプロダクトコードとテストコードでconfigに差分はないほうが好ましいでしょうから、無効化したconfigを戻せるようちょっとずつLintエラーの改修を加えていきたいと思います。

まとめ

ts-jestでテスト用tsconfig.jsonの設定方法を紹介しました。 プロダクトコード用のtsconfigとは少し変えて、快適なテスト駆動開発をお楽しみください。