第51章:カバレッジの正しい距離感📈

🎯この章のゴール
- 「カバレッジ=点数」じゃなくて、「テストの穴を見つける地図」として使えるようになる🗺️💕
- どこを優先して埋めるべきかを、落ち着いて判断できるようになる🧠✨
- Vitestでカバレッジを出して、HTMLレポートで穴を特定→テスト追加まで一気にできるようになる💪📈
📚まず知る:カバレッジって何を測ってるの?🤔
カバレッジはだいたいこの4つが出ます👇(Vitestのしきい値設定でも、この4種が中心だよ) (Vitest)
- Lines:行が通った?🧵
- Statements:文が通った?(だいたいLinesと近い)🧾
- Functions:関数が呼ばれた?☎️
- Branches:if/else や switch の分岐が両方通った?🌿🌿
ここで超大事ポイント💥 「Linesが高い=安心」じゃないです😵💫 特に Branches が低いときは「条件の片側しかテストしてない」ことが多くて、バグの温床になりがち⚠️
🧪手を動かす:まずカバレッジを“出せる状態”にする🚀
1) カバレッジ用パッケージ(v8)を入れる📦
Vitestのカバレッジは v8がデフォルトで、必要なら対応パッケージを入れます✨ (Vitest)
npm i -D @vitest/coverage-v8
(Vitest側が実行時にインストールを促してくれるケースもあるよ👍) (Vitest)
2) コマンドでレポートを出す🖨️
まずはシンプルにCLIでOK!
npx vitest run --coverage
公式ガイドでも vitest run --coverage の形が紹介されています✅ (Vitest)
3) HTMLレポートを開く🌈
デフォルトの出力先は ./coverage です📁 (Vitest)
なので、次を開くと視覚的にめちゃ分かりやすい😍
coverage/index.html
🧪ミニ題材:分岐があるロジックで“地図の読み方”を覚える🗺️✨
仕様(テストで保証したい約束)📜
送料を計算するよ📦
- 合計が 5000円以上なら送料無料🎉
- それ未満なら送料 500円
- ただし会員(member)なら 300円 に割引💕
実装(わざと穴が出やすい形)🧩
// src/shipping/calcShippingFee.ts
export function calcShippingFee(totalYen: number, member: boolean): number {
if (totalYen >= 5000) return 0
if (member) return 300
return 500
}
テスト(最初は“穴を残す”)🕳️
// src/shipping/calcShippingFee.test.ts
import { describe, it, expect } from "vitest"
import { calcShippingFee } from "./calcShippingFee"
describe("calcShippingFee", () => {
it("5000円以上なら送料無料", () => {
expect(calcShippingFee(5000, false)).toBe(0)
})
it("5000円未満で非会員なら500円", () => {
expect(calcShippingFee(4999, false)).toBe(500)
})
})
この状態で --coverage すると…
たぶん member=true の分岐が赤い(未カバー)になります😈✨
つまり「会員割引ルートが未検証」って地図が教えてくれる!
穴を埋めるテスト追加🪄
it("5000円未満で会員なら300円", () => {
expect(calcShippingFee(4999, true)).toBe(300)
})
これで Branches が上がって、安心度が一段上がるはず💗
📈カバレッジの“正しい距離感”ルール7つ🧭✨
ルール1:カバレッジは「点数」じゃなく「発見装置」🔍
- 低い場所=「テストがない」だけじゃなく **“仕様が曖昧な場所”**だったりする😳
- だから、数字に焦るより「ここ何が起きるべき?」を言語化すると強い💪
ルール2:優先度は「壊れたら痛い順」💥➡️🩹
おすすめ優先順位👇
- お金・権限・状態遷移・分岐が多い(=バグると痛い)💸🔐
- 変換・検証・境界(外から来るデータを守る所)🧱
- ただのgetter/setterや薄いラッパー(痛くない)🫧
ルール3:「Lines高いのに不安」は“Branches”を見る🌿
- if/else の片側しか通してないと、Linesはそれなりに出ちゃうことがある💦
- ルールが絡むロジックは Branches を意識すると一気に強くなる🔥
ルール4:カバレッジの対象を“適切に絞る”🎯

Vitestは、デフォルトだと「テスト実行中にimportされたファイル」中心でレポートに出ます。
未importのファイルも含めたいなら coverage.include を指定するのが定番✨ (Vitest)
// vitest.config.ts
import { defineConfig } from "vitest/config"
export default defineConfig({
test: {
coverage: {
include: ["src/**/*.{ts,tsx}"],
exclude: ["**/*.d.ts"],
},
},
})
ルール5:レポート形式は「HTML+text」がおすすめ🖥️🧾
Vitestの coverage.reporter は複数指定できて、デフォルトでも text と html を含みます📊 (Vitest)
HTMLは“赤い行がクリックで見える”ので、初心者ほど強い味方💕
ルール6:「しきい値」は“ゆるく始めて、守りを固める”🛡️
Vitestは **しきい値(thresholds)**を設定できます。 しかも面白くて、%だけじゃなく「未カバー行数の上限(マイナス指定)」もできる! (Vitest)
// vitest.config.ts
import { defineConfig } from "vitest/config"
export default defineConfig({
test: {
coverage: {
thresholds: {
// まずは“最低限の守り”から
branches: 60,
functions: 70,
// 未カバー行が増えすぎないように(例:10行まで)
lines: -10,
},
},
},
})
さらに、ファイルパターンごとのしきい値も設定できます✨ (Vitest)
ルール7:「無理な100%」は事故るので、最後の手段だけ用意🧯
どうしても通らない分岐(例:本番だけの防御コード)に対して、v8系では c8 ignore コメントが使われることがあります。 (GitHub)
/* c8 ignore next */
if (process.env.NODE_ENV === "production") {
// 本番だけのガード
}
でもね…これは強い薬💊 **「テストで保証できるなら保証する」**が基本で、ignoreは最終手段にしよ〜!🥺✨
🤖AIの使い方(この章向けテンプレ)💬✨
1) “穴の説明”をAIにさせる🧠
- 「このカバレッジ結果で、未検証になってる仕様の可能性を3つ挙げて」
- 「Branchesが低い原因を、ifの条件ごとに言語化して」
2) “追加テストの最小セット”を作らせる🧪
- 「今のテストに追加するなら、最小で何ケース?理由つきで」
- 「境界値候補だけ列挙して(実装はいらない)」
3) 断る訓練もする🙅♀️
- 「その追加テストは“実装の写し”になってない?なってたら直して」
✅チェックリスト(合格ライン)🎓💕
- HTMLカバレッジレポートを開いて、赤い行を説明できる🖥️
- Branchesの穴を見つけて、追加テストで埋められる🌿
- 「壊れたら痛い場所」から優先できる💥
- しきい値を“ゆるく”設定して、増悪を防げる🛡️ (Vitest)
- ignoreコメントを乱用しない(使うなら理由を説明できる)🧯 (GitHub)
🧪提出物(ミニ課題)📮✨
-
自分のプロジェクトで
vitest run --coverageを実行📈 (Vitest) -
赤い行を 3つ選んで、
- 「本来保証したい仕様」
- 「追加するテスト案(最小)」 をメモ📝💕
-
実際にテストを追加して、Branchesが上がったスクショ(または数値メモ)📸✨
次の章(第52章)は「遅い/不安定(フレーク)を潰す手順🐢💥」だよね? 第51章で“地図を読める”ようになったから、次は“ずっと回る状態に整える”って流れで最高だよ〜!🫶🧪✨