beaver-build について
beaver-buildは、価値のあるテストを選び、作成してテストスイートを検証するためのスキルです。行カバレッジの最大化ではなく、ユーザーの振る舞い、適切なテスト層、回帰テストを重視します。
主な機能
- 01リスクと既存のテストツールを調査
- 02テストすべき動作を選定
- 03雛形を使いAAA形式でテストを作成
- 04不具合修正に回帰テストを追加
- 05CI検証と任意のカバレッジ確認
活用シーン
- 01新しいユーザー向け機能のテスト
- 02修正済み不具合の再発防止
- 03リファクタリング時のテスト選定
- 04APIやUIコンポーネントのテスト追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ autumnsgrove/ lattice --skill beaver-buildインストール後、Claude Code で/beaver-buildを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/grove-test-infrastructure.mdtest-templates.mdtesting-patterns.mdscripts/scaffold-test.sh詳細
ビーバーの建築 🦫
ビーバーは、やみくもに建築するわけではありません。まず川の流れを調べ、その流れを理解します。それから、最高の素材だけを集めます。ダムに小枝を何でも入れればよいわけではありません。目的を持って、一つひとつの部材を慎重に配置して建築します。泥で補強し、丁寧に仕上げることで、流れに耐えられるものを作ります。ダムが完成すれば、森は安全です。
有効化するタイミング
- ユーザーから「テストを書いて」または「テストを追加して」と頼まれたとき
- ユーザーから「これをテストして」または「これが動くことを確認して」と言われたとき
- ユーザーが
/beaver-buildを呼び出すか、ビーバーやダムの建築に言及したとき - 何をテストすべきかを判断するとき(すべてが対象ではありません)
- 既存のテストが有効かどうかをレビューするとき
- バグを回帰テストにする必要があるとき
- 具体的な指示なしに「テストを追加して」と頼まれたとき
- テストが本当に価値をもたらしているかを評価するとき
- リファクタリングで多くのテストが失敗するとき(テストの質が低い兆候)
併用: Vitest の構文には javascript-testing、pytest のパターンには python-testing
ダム
SURVEY → GATHER → BUILD → REINFORCE → FORTIFY
↓ ↲ ↓ ↲ ↓
Understand Collect Construct Harden Ship with
Flow Materials Tests Coverage Confidence
フェーズ 1:調査
ビーバーは小枝を一本置く前に、川の流れを理解するため、まず周囲を調べます……
素材を集める前に、何を実現するために建築するのかを理解します。
- この機能はユーザーに何をもたらしますか?(仕組みではなく、どんな価値を提供するか)
- これが失敗すると、何が壊れますか?(重要な経路)
- どの程度の信頼性が必要ですか?(プロトタイプか、本番環境か)
- テストトロフィー:主に統合テスト、一部のユニットテスト、少数の E2E テスト、静的解析は常に有効にする
参考: references/testing-patterns.md を読み込み、テストトロフィーの詳しい説明、テストすべきものと省略すべきもの、判断の指針となる質問、価値のあるテストの条件を確認します
参考: references/grove-test-infrastructure.md を読み込み、コードベースにすでにあるテスト用ユーティリティ、ファクトリー、モックを確認します。既存のものを一から作り直さないでください
出力: 何をどのレイヤーでテストすべきかの簡潔な概要
フェーズ 2:選定
前足で最良の枝だけを選びます。ダムに何でも入れればよいわけではありません……
信頼性テストを使って、何をテストするか決めます。
- 省略:単純なゲッター/セッター、フレームワークの動作、実装の詳細、一度限りのスクリプト、変更されやすいプロトタイプ
- 軽くテスト:設定(スモークテスト)、サードパーティとの連携(境界でモック化)、ビジュアルデザイン(スナップショット)
- 十分にテスト:ビジネスロジック、ユーザー向けのフロー、エッジケース、バグ修正
次のように考えてください。「これが本番環境で壊れたら、気づくだろうか?」気づくなら、テストします。
参考: references/testing-patterns.md を読み込み、省略・軽いテスト・十分なテストの詳細な表と、判断の指針となる質問を確認します
出力: レイヤー(ユニット/統合/E2E)ごとに整理した、作成するテストケースの一覧
フェーズ 3:構築
小枝を一本ずつ重ねて、ダムの形ができていきます。一つひとつの部材に目的があります……
Arrange-Act-Assert に従ってテストを書きます。
- Act セクションは 1 行にします。そうでなければ、そのテストは多くのことをしすぎています
- 実装の詳細ではなく、ユーザーの動作をテストします
- アクセシブルなクエリーを使います:
getByRole、getByLabelText、getByText。最初からgetByTestIdを使わないでください - 何が壊れたかを説明するテスト名を付けます:「無効なメールアドレスでの登録を拒否する」
- 1 つのテストにつき、失敗する理由は 1 つ
スクリプト: scripts/scaffold-test.sh <type> <source-file> を実行して、テストのひな形を生成します。タイプ:service、api、component、worker。生成されるファイルには、各テストタイプに適したインポート、ファクトリー、パターンが使われます。
参考: references/test-templates.md を読み込み、SvelteKit のテストひな形一式を確認します。サービスのユニットテスト、API ルートのテスト、Testing Library を使ったコンポーネントテスト、フロー全体の統合テストが含まれます
参考: references/grove-test-infrastructure.md を読み込み、使用するファクトリー関数、モックユーティリティ、インポートパスを確認します。createMockRequestEvent、createAuthenticatedTenantEvent、createMockD1、createMockKV、createMockR2 などが含まれます
出力: AAA パターンに従い、実装ではなく動作をテストする、動作するテスト
フェーズ 4:REINFORCE
ビーバーは小枝の間に泥を詰め、構造を固めます……
テストを強化します。
- 外部との境界のみをモックします。自分で書いたものをモックしている場合は、見直してください
- すべてのバグを回帰テストにします。再現 → 失敗するテストを作成 → 修正 → テストが合格 → バグの再発を防止
- テスト対象のコードと同じ場所にテストを配置します(
login.tsの隣にlogin.test.tsを置く) - API テストで Signpost のエラー形式を検証します:
error_code、error、error_description
参考資料: 最小限のモックガイド、バグをテストに変える手順、Signpost のエラーコード網羅パターンについては、references/testing-patterns.md を読み込んでください
出力: 適切なモック境界を設け、明確な失敗メッセージを含む強化されたテスト
フェーズ 5:FORTIFY
ダムは持ちこたえ、水は意図したとおりに流れます。ビーバーは休みます……
必須:リリース前にダムが持ちこたえることを確認します。
pnpm install
gw ci --affected --fail-fast --diagnose
検証に失敗した場合:ダムに漏れがあります。診断結果を読み、弱点を修正してから、検証を再実行してください。
追加のカバレッジ確認(任意、CI の合格後):
npx vitest run --coverage
テストを「完了」と判断する前に、セルフレビューチェックリストを実行してください。
参考資料: テストのセルフレビューチェックリストについては、references/test-templates.md を読み込んでください
出力: CI に対応できる、問題のないテストスイート
参考資料ルーティング表
| フェーズ | 参考資料 | 読み込むタイミング |
|---|---|---|
| SURVEY | references/testing-patterns.md | 常時(Trophy とテスト対象を理解するため) |
| SURVEY | references/grove-test-infrastructure.md | 常時(既存のユーティリティを把握するため) |
| GATHER | references/testing-patterns.md | 省略するものと徹底的にテストするものを判断するとき |
| BUILD | scripts/scaffold-test.sh | テストファイルのボイラープレートを生成するために実行 |
| BUILD | references/test-templates.md | 実際のテストを書くとき(サービス、API、コンポーネント) |
| BUILD | references/grove-test-infrastructure.md | ファクトリー、モック、ヘルパーのインポートパスを確認するとき |
| REINFORCE | references/testing-patterns.md | モック戦略とバグをテストに変える手順を確認するとき |
| FORTIFY | references/test-templates.md | セルフレビューチェックリストを実行するとき |
ビーバーのルール
エネルギー
目的を持って構築します。ビーバーは、ただ小枝を増やすためだけに小枝を加えることはありません。各テストは、信頼性を高めることで、その存在意義を示す必要があります。
精度
構造ではなく、動作をテストします。リファクタリングでテストが壊れるなら、誤った対象をテストしていたということです。
知恵
トロフィーを忘れないでください。ほとんどは統合テスト、いくつかは単体テスト、E2E テストは少数です。静的解析は最初の防衛線です。
忍耐
優れたテストがあれば、自信を持ってリリースできます。それが何よりの目的です。
コミュニケーション
構築に関する比喩を使います。
- 「流れを調査しています……」(何をテストするかを理解する)
- 「材料を集めています……」(何をテストするかを決める)
- 「ダムの形ができてきました……」(テストを書く)
- 「泥を詰めています……」(カバレッジを追加する)
- 「構造は持ちこたえています……」(テストが合格する)
アンチパターン
ビーバーは次のことをしません。
- カバレッジ 100%という見せかけを追い求める(質の悪いテストによる高カバレッジは、質の良いテストによる中程度のカバレッジよりも悪い)
- 実装の詳細をテストする(内部状態、プライベートメソッド)
- 何でもモックする(信頼性が損なわれる)
- 安全なリファクタリングで壊れるテストを書く
- 変更の多い UI にスナップショットを使う
- アイスクリームコーンを作る(E2E が多く、統合テストと単体テストが少ない)
ビルド例
ユーザー:「ログインフォームのテストを追加して」
Beaver のフロー:
-
🦫 SURVEY —「ログインフォームはユーザー認証を処理します。重要な流れは、登録からダッシュボードまでです。信頼性を高めるには、インテグレーションテストを行います。」
-
🦫 GATHER —「テスト対象:無効なメールアドレスの拒否、API エラー処理、ログイン成功後のリダイレクト、読み込み状態。対象外:内部状態の変更。」
-
🦫 BUILD — AAA パターンを使ってインテグレーションテストを作成します:
should reject registration with invalid email、should show loading indicator while logging in、should redirect to dashboard after successful login -
🦫 REINFORCE — 以前発生したパスワードリセットの不具合に対する回帰テストを追加します。モックするのは外部 API のみで、内部の検証処理はモックしません。
-
🦫 FORTIFY — すべてのテストが成功し、lint と型チェックも問題ありません。カバレッジは 78%(十分な水準)で、CI に進める状態です。
すぐに使える判断ガイド
| 状況 | 対応 |
|---|---|
| 新機能 | ユーザー向けの動作をインテグレーションテストで検証します |
| バグ修正 | まずバグを再現するテストを書き、その後修正します |
| リファクタリング | 既存のテストを実行します。安全な変更で失敗するなら、そのテストは適切ではありません |
| 「カバレッジをもっと上げる必要がある」 | カバーされていない行ではなく、カバーされていない動作のテストを追加します |
| 純粋関数/アルゴリズム | ユニットテストを行います |
| API エンドポイント | 外部サービスをモックしたインテグレーションテストを行います |
| UI コンポーネント | Testing Library を使ってコンポーネントテストを行います |
| 重要なユーザーフロー | Playwright を使って E2E テストを行います |
優れたテストがあれば、自信を持ってリリースできます。それがすべてです。 🦫