🦾

Angularプロジェクトにtesting-libraryとjestを入れてみた

2024/06/08に公開

会社のAngular v17 のプロジェクトにtesting-library/angularjestでテスト環境を構築しようとしたら、思いの外時間がかかったので備忘録。

ライブラリの整理

Angularの標準搭載のテストライブラリのKarmaは必要なくなるので削除する。

npm remove karma\
  karma-chrome-launcher\
  karma-coverage-istanbul-reporter\
  karma-jasmine\
  karma-jasmine-html-reporter

testing-libraryとjestをインストールしていく。
多いからまずはjest系から

npm i -D @angular-builders/jest @types/jest jest jest-preset-angular
  • @angular-builders/jest
    JestをKarmaの代わりに使用してng testコマンドを実行できるようにするAngular用のJestビルダー。
  • @types/jest
    describeitexpectなどjestの型情報を定義する
  • jest-preset-angular
    jest-preset-angularはJestの設定をAngularプロジェクトに適したものにカスタマイズしてくれる。

次にtesting-library系をインストール

npm i -D @testing-library/angular @testing-library/jest-dom @testing-library/user-event
  • @testing-library/angular
    コンポーネントをレンダリングして、特定の要素を抽出して操作(インタラクション)することができるテストライブラリ。要素をクリックしたりキーボード入力したりやらと、ユーザーが実際にWebアプリケーションを操作するのと同じ感覚でテストを書くことができる。
  • @testing-library/jest-dom
    jest標準のマッチャーにDOMの状態を検証するカスタムマッチャーを追加する
  • @testing-library/user-event
    testing-library標準で搭載されているfireEventよりも高機能らしい。方面で勧められていたので採用。

今までの関数単位等の単体テストでは、実際の使われ方を想定して書きにくかった。
testing-libraryでより正確なテストが書けるようになると期待。

テスト環境ファイルのセットアップ

次にjestをangularで実行するための環境ファイルを設定する。

tsconfig.spec.json

テスト実行用のtsconfig。tsconfigで足りないものやtsconfigを上書きしたいことを書く。

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./dist/out-tsc/spec",
    "baseUrl": "src",
    "types": ["node", "jest", "@testing-library/jest-dom"]
  },
  "include": ["**/*.spec.ts", "**/*.d.ts"]
}
  • types
    テストで使用する型定義ファイルを指定
  • include
    TypeScriptコンパイラが処理するファイルのパターン

jest.config.ts

import type { Config } from 'jest';

// node_module内のESM形式のパッケージ
const esmPackages = [
  '@angular/*',
  '@testing-library/angular',
  '@ngrx/*',
];

const config: Config = {
  globals: {
    tsconfig: '<rootDir>/tsconfig.spec.json',
  },
  preset: 'jest-preset-angular',
  setupFilesAfterEnv: ['<rootDir>/src/setup-jest.ts'],
  moduleDirectories: ['node_modules', '<rootDir>'],
  moduleNameMapper: {
    rxjs: require.resolve('rxjs'),
    swiper_angular: require.resolve('swiper'),

    '^src/(.*)$': '<rootDir>/src/$1',
    '^app/(.*)$': '<rootDir>/src/app/$1',
    ...
  },
  transformIgnorePatterns: [`node_modules/(?!(${esmPackages.join('|')})/)`],
};

export default config;
  • tsconfig
    テスト実行用のtsconfig.spec.jsonを指定する
  • setupFilesAfterEnv
    テスト環境が設定された後に実行されるスクリプト
  • moduleNameMapper
    特定のモジュール名を解決する方法をカスタマイズするのに必要。
    Jestはデフォルトだと相対パスでないと読み取れないぽいので、ここで教えてあげる必要がある。
    また、tsconfigのcompileOptionで独自のpathを設定している場合、jestがそのpathを追えるように教えてあげる。
  • transformIgnorePatterns
    トランスパイルしないファイルを指定する。
    JestはデフォルトでESM形式ををサポートしていないため、テスト環境でも動くようにESM形式のパッケージはトランスパイルする必要があるらしい。

setup-jest.ts

テストを実行する前に一度だけ実行され、テスト環境を構築するらしい。
プロジェクト特有の拡張機能等あれば、ここにimportする。

ファイル名は特に決まっていない模様。

import 'jest-preset-angular/setup-jest';
import '@testing-library/jest-dom';
import '@testing-library/user-event';

package.json

jestを実行する環境の準備はできたので、テスト実行コマンドをAngular標準のng testからjestに変える。

{
  "scripts": {
    "test": "jest"
  }
}

Discussion