Skip to main content

第03章:“小さく刻む”基本(1テスト=1約束)🔪

仕様を小テストに分解

🎯この章のゴール

  • 仕様(やりたいこと)を 小さなテストに分解できるようになる💪😊
  • 1テスト=1つの約束(ふるまい) を守れるようになる📌
  • 進める順番は 正常 → 境界 → 異常 が基本って体で覚える🚦✨

📚まず大事な考え方:「テストは“約束”を書く」📘💖

画像を挿入予定

テストって「動くか確認」だけじゃなくて、もっとシンプルに言うと…

✅「この関数は、こういう時こうなるよ」っていう 約束 を書くもの

だから 1本のテストに約束を詰め込みすぎると…

  • 失敗したとき「どの約束を破ったの?」が分からない😵‍💫
  • テスト名が長文になって崩壊しやすい📛
  • ちょっと仕様追加しただけでまとめて壊れる💥

小さく刻むと、逆にこうなるよ👇✨

  • どこが壊れたか一瞬で分かる👀⚡
  • 追加仕様も「1〜2本テスト追加」で済みやすい➕🧪
  • AIに手伝わせても、ズレに気づきやすい🤖🔍

🧠「小さく刻む」ための3ステップ(超実用)🔪✨

✅ステップ1:仕様を“約束の短文”にする📝

仕様をそのままテストにしないで、まず 短い約束に分解するよ💡

例:「入力が6桁の数字ならtrue」 → 約束にするとこんな感じ👇

  1. 6桁の数字なら true ✅
  2. 前後の空白があってもOK(無視する)✅(境界っぽい)
  3. 数字じゃなければ false ✅(異常)

✅ステップ2:1テスト=1約束にする🧪

  • 1つのテスト名に 約束を1個だけ入れる✨
  • 1テストの中で「AもBもCも」って確認しすぎない🙅‍♀️💦

✅ステップ3:順番は「正常→境界→異常」🚦

  • 正常:まず “気持ちよく通る道” を作る🌱
  • 境界:端っこ(空白、0、最大/最小、ちょうど)を固める🧱
  • 異常:ダメな入力の扱いを仕様にする🚫

🧪手を動かす:仕様文→テスト3本に分割(例題)💻✨

🎯お題:6桁数値チェック関数

**仕様(この章ではこう決めるよ)**👇

  • 入力の 前後の空白は無視trimしてOK)🧼
  • trimした結果が ちょうど6桁の数字なら true
  • それ以外は false

※TypeScriptは npm だと現在 5.9 系が最新(例:5.9.3)だよ📦✨ (npmjs.com) ※Vitestは 4.0.17 が最新だよ🧪✨ (npmjs.com)


① まず「3つの約束」をテスト名にする📝💖

import { describe, it, expect } from "vitest";
import { isSixDigitNumber } from "./isSixDigitNumber";

describe("isSixDigitNumber", () => {
it("6桁の数字なら true を返す", () => {
expect(isSixDigitNumber("123456")).toBe(true);
});

it("前後に空白があっても 6桁の数字なら true を返す(空白は無視)", () => {
expect(isSixDigitNumber(" 123456 ")).toBe(true);
});

it("数字以外が混ざるなら false を返す", () => {
expect(isSixDigitNumber("12a456")).toBe(false);
});
});

🎉ここが超重要: この時点で 実装はまだ書かない(or ダミーでOK)🙆‍♀️ まずは 仕様を小テストに落とすのが勝ち


② Red を作る(まず落とす)🚦🔴

実装ファイルを作って、とりあえず「失敗させる」よ!

export function isSixDigitNumber(_input: string): boolean {
throw new Error("Not implemented");
}

テストを実行して、ちゃんと赤くなるのを確認👀🔴 (赤くならない=テストが動いてない可能性🧯)


③ Green(最小で通す)🚦🟢

ここで大事なのは「賢く作らない」こと!😆 3本通る最小を作るよ👇

export function isSixDigitNumber(input: string): boolean {
const s = input.trim();
return /^\d{6}$/.test(s);
}

✅これで3本通るはず🎉

  • trim() で前後空白を無視🧼
  • 正規表現で「6桁の数字だけ」を約束に合わせて判定🎯

④ ちょいリファクタ(読みやすく)🧹✨

この段階で、無理にリファクタしなくてOK🙆‍♀️ でも「読みやすさ」を少し上げるなら、意図の名前を付けるのはアリ💖

const SIX_DIGITS = /^\d{6}$/;

export function isSixDigitNumber(input: string): boolean {
const trimmed = input.trim();
return SIX_DIGITS.test(trimmed);
}

🤖AIの使い方(この章はここが強い!)✨

✅使う目的は「刻み方を小さくする」🔪

AIに丸投げすると、テストがデカくなりがち😵‍💫 この章は “分解”だけ手伝わせるのが正解だよ💡

💬おすすめプロンプト(コピペOK)📋🤖

「仕様を最小のテストに分解」専用👇

次の仕様を、TDD向けに「正常→境界→異常」の順で
まず3本だけの最小テストに分解してください。
各テストは「1テスト=1約束」になっているかもチェックして、
テスト名も提案してください。

仕様:
- (ここに仕様を書く)

✅AI回答の採点ポイント(超大事)🧑‍🏫✨

  • 1本に約束を詰め込んでない?📦❌
  • 「境界」がちゃんと“端っこ”になってる?🧱
  • 「異常」が“1種類だけ”になってる?(最初は1個でOK)🚫

✅チェックリスト(できたら合格)🎓💮

  • テスト3本が 正常→境界→異常 の順になってる🚦
  • 各テストが 1つの約束だけを検証してる📌
  • テスト名を読めば仕様が分かる📝✨
  • 失敗したら「どの約束が壊れたか」すぐ分かる👀⚡

💥ありがちな失敗あるある(先に潰す)🧯😆

❌失敗1:1テストで全部チェックしちゃう

「正常も境界も異常も同じテスト内で」 → 落ちた時に地獄😇💥 ✅直し方:約束ごとに分ける

❌失敗2:最初から境界・異常を盛りすぎる

「無効入力20個!」みたいな🤣 ✅直し方:異常はまず 1種類だけでOK。増やすのは後で➕🧪

❌失敗3:テスト名が“実装説明”になる

「trimしてregexして…」みたいな👀💦 ✅直し方:テスト名は 利用者目線(何が起きる?)にする💖


🧩ミニ演習(自分で刻む練習)🎀🧪

次の仕様を、まず **テスト3本(正常→境界→異常)**にしてみてね😊✨ (答えは自分で作ってOK!「約束の短文」→「テスト名」→「expect」まで)

お題A:パスワード判定🔐

  • 8文字以上ならOK
  • 前後空白は無視
  • それ以外はNG

お題B:送料計算🚚

  • 合計が 3000円以上なら送料0
  • ちょうど3000円も0
  • それ未満は送料500

🔜次章チラ見せ(第4章)👀✨

次は「TDDが向く場所・向かない場所🎯」! “全部テストしようとして燃える🔥”のを防ぐ回だよ😆🧯


必要なら、この第3章の内容を **提出物つき(どこまでできたら合格か)**とか、**演習の模範解答(テスト名の改善案つき)**でもっと教材っぽく整えるよ📘💕