この記事はTSKaigi Advent Calendar 2024 22日目の記事です。
はじめに
こんにちは!TSKaigiクリエイティブチームの添田です!
2025年5月のTSKaigiの開催が待ち遠しくてワクワクが止まりません!
最近、TypeScriptとJestの組み合わせにすっかりハマっています。
皆さんにもその魅力を伝えたいと思います!😊
なぜテストが必要なの?
コードを書いていると、「動作確認はブラウザで十分じゃない?」と思うかもしれません。
でも、自動テストがあると以下のような場面で頼もしい存在になります!
- ✨ 新機能の追加:既存の機能が壊れていないかすぐ確認できる
- 🐛 バグ修正後:同じバグが再発していないかチェック可能
- 👥 チーム開発:他メンバーが修正したコードの動作も保証される
Jestって何がスゴイの?
JestはJavaScript向けの人気テストフレームワークです!
- 🚀 簡単な書き方:テストの記述がシンプル
- 👀 見やすい結果表示:エラー箇所が一目でわかる
- 💪 TypeScript対応:ts-jestを使えばTypeScriptコードもそのままテスト可能
下準備
以下のコマンドでTypeScriptとJestをインストールします。
npm install --save-dev jest typescript ts-jest @types/jest
実践
足し算関数のテスト
まず、シンプルな足し算関数を用意します。
export function sum(a: number, b: number): number {
return a + b;
}
次に、この関数のテストコードを作成します。
最初にテスト対象となるsum関数をimportします。
import { sum } from "./sum";
it関数はtest関数と同じ動作をしますが、好みに応じて使い分けが可能です。
当記事はit関数を使用しています。
it関数の第1引数は文字列でテストケースの名前を書きます。
英語はもちろん、日本語でも書くことができます。
第2引数はアロー関数を指定し、アロー関数の中にテストを書いていきます!
it("3と2を足すと5になる", () => {});
expect関数を使い、引数にテスト対象の実行結果を渡します。
このtoBeはMatcher関数と呼ばれているもので、期待値を渡すものです。
it("3と2を足すと5になる", () => {
expect(sum(3, 2)).toBe(5);
});
Matcher関数については、他にもあるので、
興味ある方は是非以下を参考にしてみてください。
テストを実行
npm test src/sum.test.ts
成功時:✅ 緑色のマーク
失敗時:❌ 赤色のマーク
見やすい出力で、どこが問題なのかすぐに分かりますね!
成功時
> jest-lesson@1.0.0 test
> jest src/sum.test.ts
PASS src/sum.test.ts
✓ 3と2を足すと5になる (1 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.102 s, estimated 2 s
失敗時
FAIL src/sum.test.ts
✕ 3と2を足すと5になる (2 ms)
● 3と2を足すと5になる
expect(received).toBe(expected) // Object.is equality
Expected: 8
Received: 5
2 |
3 | it("3と2を足すと5になる", () => {
> 4 | expect(sum(3, 2)).toBe(8);
| ^
5 | });
6 |
at Object.<anonymous> (src/sum.test.ts:4:23)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 1.116 s, estimated 2 s
このエラーメッセージでは、Expected: 8とReceived: 5が異なるため、テストの期待値が正しいか、または関数が正しい値を返しているかを確認しましょう。
expect(sum(3, 2)).toBe(8);
TypeScriptと組み合わせることで、テストコードそのものも型安全になります。
そのため、テストの記述時に型エラーを防ぐことができ、より信頼性の高いテストが書けます。
ショッピングリストのテストをしてみよう
/**
* 【演習】
* 1. `addItem`メソッドが、アイテムをリストに追加できることを確認するテストケース
* 2. `removeItem`メソッドが、アイテムをリストから削除できることを確認するテストケース
* 3. `removeItem`メソッドが、存在しないアイテムの削除を試みたときにエラーをスローすることを確認するテストケース
*/
export class ShoppingList {
public list: string[];
constructor() {
this.list = [];
}
addItem(item: string): void {
this.list.push(item);
}
removeItem(item: string): void {
const index = this.list.indexOf(item);
if (index === -1) {
throw new Error(`アイテム: ${item} は存在しません`);
}
this.list.splice(index, 1);
}
}
回答例
import { ShoppingList } from "./practice"
describe("演習問題", () => {
let shoppingList: ShoppingList;
beforeEach(() => {
// 各テストケースの実行前に新しいShoppingListインスタンスを作成します。
shoppingList = new ShoppingList();
});
describe("addItem", () => {
it("1. `addItem`メソッドが、アイテムをリストに追加できることを確認するテストケース", () => {
shoppingList.addItem("メロン");
expect(shoppingList.list).toHaveLength(1); // 配列や文字列のサイズを確認
expect(shoppingList.list[0]).toBe("メロン"); // 0番目の文字は「メロン」か確認
})
it("リストに複数アイテムを追加できる", () => { // 追加
shoppingList.addItem("リンゴ");
shoppingList.addItem("ミカン");
expect(shoppingList.list).toHaveLength(2); // 配列や文字列のサイズを確認
expect(shoppingList.list).toEqual(["リンゴ", "ミカン"]); // objectを比較するのでtoEqual
});
});
describe("removeItem", () => {
it("2. `removeItem`メソッドが、アイテムをリストから削除できることを確認するテストケース", () => {
shoppingList.addItem("メロン");
shoppingList.addItem("リンゴ");
shoppingList.removeItem("リンゴ");
expect(shoppingList.list).not.toContain("リンゴ"); // アイテムが配列内にないことを確認
expect(shoppingList.list).toHaveLength(1); // 配列や文字列のサイズを確認
expect(shoppingList.list[0]).toBe("メロン"); // 0番目の文字は「メロン」か確認
})
it("3. `removeItem`メソッドが、存在しないアイテムの削除を試みたときにエラーをスローすることを確認するテストケース", () => {
// エラーがスローされることを確認
expect(() => {
shoppingList.removeItem("リンゴ");
}).toThrow("アイテム: リンゴ は存在しません");
})
});
})
テストを書くときのコツ📝
- テストケースは具体的に書く
- 「〜の場合、〜になること」という形式で書くと分かりやすい
- 一つのテストでは一つの機能だけを確認する
- beforeEachを活用
- テストの前準備はbeforeEachでまとめると便利
- テストケース間の独立性が保てる
- エラーケースも忘れずに
- 正常系だけでなく、異常系のテストも大切
- ユーザーの予期せぬ操作にも対応できる
さらなる一歩へ!
Jestには他にもたくさんの機能があります
- 🎭 モック(Mock)を使ったテスト
- 📸 スナップショットテスト
- 📊 テストカバレッジの計測
まとめ
今回は、TypeScriptとJestを使った基本的なテストの書き方を学びました!
はじめは少し難しく感じるかもしれませんが、テストを書くことで
- 💗コードの品質が上がる
- 💗バグの早期発見ができる
- 💗安心してリファクタリングできる
といった素晴らしいメリットがあります。
ぜひ、みなさんも実践してみてください!
📅イベント情報📅
TSKaigi2025が2025年5月23日/24日に開催されます!🎪
日本最大級のTypeScriptカンファレンスで、前回は2000人以上の方が参加されました!👥
TypeScriptに興味のある方は、ぜひチェックしてください!✨
TSKaigi 2025 ティザーサイト:https://2025.tskaigi.org/
公式サイト:https://tskaigi.org/
X:https://x.com/tskaigi
参考にさせていただいた資料
Jest公式ドキュメント:https://jestjs.io/ja/
TypeScript公式ドキュメント:https://www.typescriptlang.org/
Udemy教材:https://www.udemy.com/course/ts-webapp-test/?couponCode=ST21MT121624