0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

個人開発で E2E カバレッジを CI 強制する仕組み — pnpm e2e:coverage-check で漏れを構造的に潰す

0
Posted at

この記事は約 5 分で読めます。

筆者プロフィール: ソフトウェアエンジニア。「知った気にならない。いつまでも学び続ける」を信条に、業務と個人開発の両輪で技術を磨いています。AI 駆動開発で複数の個人開発アプリを構築・運用中。
👉 ポートフォリオ: 筆者ホームページ

「新規 page / route を作ったのに、E2E spec を書き忘れて半年後に気づく」 — これを 構造的に防ぐ仕組み を整理します。運用中の SaaS 「たすきば Knowledge Relay」 で実装している pnpm e2e:coverage-check パターンです。

サービスの機能紹介・画面イメージ・コンセプトは公式プロダクトページをご覧ください。
👉 たすきば Knowledge Relay — 公式プロダクトページ

なぜ E2E カバレッジを文書管理するか

たすきばは E2E (End-to-End) テストを Playwright で書いています。カバレッジは、「どの page / API が E2E で覆われているか」docs/test/E2E_COVERAGE.md に明文化します。

| ファイル | E2E spec | 状態 |
|---|---|---|
| src/app/(dashboard)/projects/page.tsx | e2e/projects/list.spec.ts | ✓ |
| src/app/api/projects/route.ts | e2e/api/projects.spec.ts | ✓ |
目的 内容
書き忘れ防止 新規 page / route 追加時の漏れを構造的に防ぐ
状態の可視化 どのファイルがテスト無しか即座に分かる
CI 強制 漏れを CI で検知できる

1. pnpm e2e:coverage-check の仕組み

スクリプト scripts/e2e-coverage-check.ts の挙動:

1. src/app/**/page.tsx と src/app/api/**/route.ts を glob で全列挙
2. docs/test/E2E_COVERAGE.md の表をパース
3. 列挙したファイルが表にあるか確認
4. ないファイルがあれば エラーで exit 1
async function main() {
  const pages = await glob('src/app/**/page.tsx');
  const routes = await glob('src/app/api/**/route.ts');
  const allFiles = [...pages, ...routes];

  const coverageDoc = await fs.readFile('docs/test/E2E_COVERAGE.md', 'utf-8');
  const documentedFiles = parseTable(coverageDoc).map(row => row.filePath);

  const missing = allFiles.filter(f => !documentedFiles.includes(f));
  if (missing.length > 0) {
    console.error('E2E coverage missing for:');
    missing.forEach(f => console.error(`  - ${f}`));
    process.exit(1);
  }
}

CI でこのスクリプトが走り、未記載があれば PR が red になります。


2. 追記漏れで痛い目に遭った実例

PR #372 で実体験した事故。

# ローカルで build + test 全 PASS
pnpm lint        # ✓
pnpm tsc         # ✓
pnpm test        # ✓
pnpm build       # ✓

# PR push → CI 走行
pnpm e2e:coverage-check  # ✗ 新規 page を文書に追記していない

# CI red

PR がブロックされ、追記してから再 push して通すまで 半日 lost

当時、私は「lint / tsc / test / build の 4 点セットさえ通せば OK」と思っていました。それは間違い。E2E カバレッジチェックは別 CI ガード。


3. ローカル実行を必須化する運用

docs/test/E2E_COVERAGE.md を必ず更新するルール:

1. 新規 page.tsx / route.ts を作る
2. E2E spec を書く (または書く予定をメモ)
3. docs/test/E2E_COVERAGE.md の表に追記
4. commit 前に pnpm e2e:coverage-check をローカル実行
5. 通ったら commit

Step 4 が重要。CI 待ちで PR が落ちるのは、開発リズムを大きく崩します。


4. CLAUDE.md にも明記

たすきばの CLAUDE.md (Claude Code 運用ガイド) には、コミット前チェックリストとして E2E カバレッジを明記。

## コミット前チェック (毎回必須)

1. 横展開チェック — 同一パターンを検索し漏れなく対応
2. 退行チェック
   - 単体テスト (`pnpm test`)
   - E2E カバレッジ横展開: 新規 page.tsx / route.ts を追加したら
     docs/test/E2E_COVERAGE.md に追記。`pnpm e2e:coverage-check` で gap 検出可
3. デプロイチェック — `pnpm lint``pnpm tsc``pnpm test``pnpm e2e:coverage-check``pnpm build`

毎回必須にすることで、機械的に漏れを潰します


5. E2E spec が書けない時の「保留」ステータス

新規 page / route を作ったが、「E2E spec を書く時間がない」「まだ実装が固まっていない」場合もあります。

そんなときは、docs/test/E2E_COVERAGE.md「保留」ステータス で記載します。

| ファイル | E2E spec | 状態 |
|---|---|---|
| src/app/(dashboard)/new-feature/page.tsx | - | 🚧 保留 (T-XX) |
効果 内容
カバレッジチェック pass リストに存在するため通る
可視化 「保留中」が明示される
後追い 後から拾い上げて E2E を書ける

完全に書かないより、保留として記録するほうが長期的に追跡可能


6. なぜここまで仕組み化するか

E2E カバレッジを文書化 + CI 強制までする理由:

理由 内容
自分自身が忘れる 「この page は E2E 書いたっけ?」が頻発
将来チーム化への投資 文書があれば新メンバーが穴を即把握できる
リグレッション早期検知 後から「気づかなかった」リスクを減らせる

人間の記憶に頼らずに済む ことが、個人開発の継続性を保つ鍵です。


おわりに

仕組み 効果
docs/test/E2E_COVERAGE.md で全 page/route を文書化 カバレッジが一覧化
pnpm e2e:coverage-check で CI 強制 追記漏れを構造的に検知
保留ステータスでも記載 完全 0 を避ける
コミット前チェックリストに含める 機械的に漏れを潰す

個人開発で品質を維持するために、人間の意思に頼らない仕組み が大切です。

本記事の E2E カバレッジ運用は、運用中の SaaS 「たすきば Knowledge Relay」 で実装しています。
👉 たすきば Knowledge Relay — 公式プロダクトページ

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?