ユニットテストしたい(jest)
$ npx jest
$ npx jest --watch
jestはJavaScript用のユニットテストフレームワークです。
ゼロコンフィグに近い設定で使い始められます。
注釈
新しくTypeScriptのGASプロジェクトを始める場合は、
vitestのほうがTypeScriptにネイティブ対応していて設定も少なく済むためオススメです。
インストールしたい
$ npm install --save-dev jest
jest本体をdevDependenciesとして追加します。
スクリプト設定したい(package.json)
{
"name": "...",
"scripts": {
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"...": "..."
}
}
$ npm test
$ npm run test:watch
$ npm run test:coverage
testは1回実行、test:watchはウォッチモード、test:coverageはカバレッジ計測付きで実行します。
設定したい(jest.config.js)
1/** @type {import('jest').Config} */
2module.exports = {
3 testEnvironment: "node",
4 testMatch: ["**/__tests__/**/*.test.js"],
5 setupFilesAfterEnv: ["<rootDir>/__tests__/setup.js"],
6 collectCoverageFrom: [
7 "src/**/*.js",
8 "!**/node_modules/**",
9 "!**/coverage/**",
10 ],
11};
testEnvironmentは、テストを実行する環境の指定です。
GASにはブラウザDOMがないため、nodeを指定します。
testMatchで対象となるユニットテスト用のファイルを設定します。
指定を忘れると、テスト以外のファイル(setup.jsなど)まで
テストファイルとして扱われてエラーになることがあるので注意してください。
setupFilesAfterEnvで、Jest実行時に共通して読み込むファイルを設定できます。
collectCoverageFromでカバレッジ測定の対象とするファイルを指定します。
GASのグローバルをモックしたい(__tests__/setup.js)
1// GASのグローバルオブジェクトをモックする
2global.Logger = {
3 log: jest.fn(),
4 clear: jest.fn(),
5};
DriveAppやSpreadsheetApp、LoggerのようなGASのグローバル変数は、
Node.js環境(jestの実行環境)には存在しません。
テストを実行する前に、setupFilesAfterEnvで指定したファイルの中で、
必要な分だけjest.fn()でモックしておく必要があります。
ユニットテストしたい
1const { Counter } = require("../src/counter");
2
3describe("Counter", () => {
4 describe("constructor", () => {
5 test("should create counter with default settings", () => {
6 const counter = new Counter();
7 expect(counter.getValue()).toBe(0);
8 });
9 });
10
11 describe("increment", () => {
12 let counter;
13
14 beforeEach(() => {
15 counter = new Counter();
16 });
17
18 test("should increment the value", () => {
19 expect(counter.increment()).toBe(1);
20 });
21 });
22});
describeでテスト対象をグループ化し、testで個々のテストケースを書きます。
describeは入れ子にできるので、以下のような構造を意識して作成するとよいです。
テストするクラス名
テストするメソッド1
正常系テストたち
異常系テストたち
テストするメソッド2
正常系テストたち
異常系テストたち
beforeEachで、各テストの実行前に共通のセットアップ処理を行えます。
ヒント
テストケースを自分で考えるのは大変です。 最近はClaudeに、アップロードしたソースコードを読み込んでもらい、 それに対するユニットテストを作ってもらうようにしています。
TypeScriptに対応したい(ts-jest)
$ npm install --save-dev ts-jest @types/jest
.tsファイルをそのままテストできるようにするts-jestと、
describe・test・expectなどの型定義を提供する@types/jestを追加します。
1const { createDefaultPreset } = require("ts-jest");
2
3const tsJestTransformCfg = createDefaultPreset().transform;
4
5/** @type {import('jest').Config} */
6module.exports = {
7 testEnvironment: "node",
8 transform: {
9 ...tsJestTransformCfg,
10 },
11 testMatch: ["**/__tests__/**/*.test.ts"],
12 setupFilesAfterEnv: ["<rootDir>/__tests__/setup.ts"],
13 collectCoverageFrom: [
14 "src/**/*.ts",
15 "!**/node_modules/**",
16 "!**/coverage/**",
17 ],
18};
transformは、.tsファイルをテスト実行前にコンパイルする設定です。
ts-jestが提供するcreateDefaultPreset()を使うのが現在の推奨方法です。
testMatch・setupFilesAfterEnv・collectCoverageFromの拡張子を.tsに変えるだけで、
JS版の設定とほぼ同じ形になります。
注意
ts-jestの設定方法はpreset: "ts-jest"と書く古い書き方をよく見かけますが、
最近のバージョンでは非推奨になっています。
createDefaultPreset()を使う書き方に変わっているので、
古い記事のサンプルをそのまま使うと警告が出ることがあります。
ヒント
tsconfig.jsonのtypesを明示的に絞っている場合、
"jest"を含めておかないとdescribeやtest、expectが型エラーになります。
またsetupFilesAfterEnv内でglobal(Node.jsのグローバルオブジェクト)を使う場合は、
"node"も忘れずに含めてください("types": ["jest", "node"])。