Jestの環境設定と使いこなし術(サーバサイド向け)

Jest はいま人気のFacebook製のJavaScript用テストフレームワークです。本記事では、Jestを完全に理解した私がJestの環境設定や便利な使い方について紹介します。なお、本記事はJestをサーバサイドアプリケーションで使用する前提で書いていますが、多くはフロントエンドアプリケーションでも共通して利用できるものと思います。

対象読者

  • Jestを使ったことがあり、基本的なことは分かっている

Configuration

https://jestjs.io/docs/ja/configuration

こちらはあるプロジェクトのpackage.jsonです。まずはConfigの内容について紹介します。

{
  "devDependencies": {
    "eslint": "6.6.0",
    "eslint-plugin-jest": "23.0.3",
    "jest": "24.9.0",
    "jest-failure-reporter": "1.0.1",
    "ts-jest": "24.1.0",
    "typescript": "3.7.2"
  }
  "scripts": {
    "test": "jest --runInBand",
  },
  "jest": {
    "preset": "ts-jest",
    "testEnvironment": "node",
    "rootDir": "./src",
    "globalSetup": "<rootDir>/tests/setup.ts",
    "globalTeardown": "<rootDir>/tests/teardown.ts",
    "notify": true,
    "reporters": ["default", "jest-failure-reporter"],
  },
}
  • preset: Configのベースとなる設定です。テストコードをTypeScriptで書くので ts-jest を指定します。
  • testEnvironment: テスト環境です。ブラウザ環境ではなくNode環境なので node を指定します。
  • rootDir: プロジェクトのルートディレクトリを指定します。TypeScriptで書いたコードを対象とするので ./src を指定します。
  • globalSetup: テストの起動時に実行されるモジュールです。DBのセットアップなどに利用します。
  • globalTeardown: テストの終了時に実行されるモジュールです。DBのクリーンアップなどに利用します。ただし強制終了すると実行されません。
  • notify: テストのステータスをOSの通知機能に通知してくれます。--watch オプションでバックグラウンドで実行している場合に便利です。
  • reporters: テスト結果の出力をカスタマイズするモジュールです。配列で指定することで重ねがけすることができます。 jest-failure-reporter は自作のreporterで、Rspecのようにテスト終了時に失敗したテストの一覧と個別に実行するコマンドを出力します。他にも GitHubに結果を表示するreporter などもあるので、CI環境ではcliの --reporters オプションでreporterを切り替えると便利そうです。

cli

https://jestjs.io/docs/ja/cli

  • --runInBand: Jestはデフォルトで並列でテストを実行するのですが、並列で実行できない場合はこれを指定します。
  • -o: gitの情報から変更があったファイルを検出し、関連するテストのみを実行します。
  • --watch: ウォッチモードで実行します。ファイルに変更があったとき、関連するテストを自動で実行します。

ある程度テストが書けた段階で -o で実行し失敗するテストを特定し、細かい修正をする段階では --watch で結果を逐次確認しながら進めると効率が良いです。

vscode-jest

https://github.com/jest-community/vscode-jest

VSCodeのExtensionです。自動で --watch を実行してくれて、テストコードにインラインでテストの結果を表示したり、めちゃくちゃ強力なのですが、デフォルトではテストが並列で実行される(Jestの標準の動きで、Configで書き換えることができない)ため、並列で実行されても問題がないようにテストを書く必要があります。

runInBandをconfigで指定したい

https://github.com/jest-community/vscode-jest/issues/399

これに対する回答

https://github.com/facebook/jest/issues/3215#issuecomment-289608118

なぜそうまで頑なに拒むのか。

ちなみに私のプロジェクトではTypeORMというORマッパーのライブラリを利用しているのですが、TypeORMではテストスイートごとにDBをトランザクション・ロールバックするような機能はなく、テストを並列で実行可能にするにはテストスイート間でデータの整合性に気を使わなければならないという事情があり、いまのところ並列実行は諦めています。

TypeORMでテストスイートごとにトランザクション・ロールバックするようにできていない

https://github.com/typeorm/typeorm/issues/503

トランザクション・ロールバックするようにしようとしているライブラリもある

https://github.com/entrostat/typeorm-test-transactions

将来的にも期待はできなさそうです。

このように、このExtensionの機能の大半は利用できていないのですが、他にも、テストコードにインラインでDebugボタンが追加される機能があり、これを押すだけで該当テストがDebug実行できるのはとても便利です。

eslint-plugin-jest

https://github.com/jest-community/eslint-plugin-jest

Jestのテストコードをチェックしてくれるeslintのプラグインです。テストコードにまでlintするかどうかは賛否あると思いますが、テストコードの品質もメンテする上では重要なのである程度やっておいたほうがいいかなと思います。

awesome-jest

https://github.com/jest-community/awesome-jest

JestのPackage集です。なにか必要になったらここを探すとあるかもしれません。Packageの作り方の参考にもなります。

まとめ

Jestはテストに必要な機能がオールインされていてすぐに実践的に使い始められるのもすごいのですが、機能単位で拡張のインターフェイスが開いていて、そこに多くの人たちがカスタム機能を追加でいるようになっているアーキテクチャも素晴らしいと思いました。