Communityコーディング&開発github.com

toyin-software-factory/test

/test を実行して、機能、ルート、修正を実装した後に構築または変更したコードのテストスイートを自動生成します。未コミットの変更を自動的に対象とし、test-preferences.json からフレームワーク設定を読み取り(なければ確認・保存)、各ファイルに適したテスト戦略を選択します。

test とは?

このスキルは、開発者がコード変更後にテストスイートを迅速に生成するためのエージェントスキルです。`/test` を実行すると、Git のワーキングツリー上の未コミット変更を自動検出し、ファイルの種類(ロジック、コンポーネント、API ルート、ページ/フロー、CLI)に応じて最適なテスト戦略を選択します。最初の実行時には、プロジェクトのスタックやフレームワークを検出し、インストールが必要なツールを確認・セットアップします。すべての主要な OS(macOS、Linux、Windows)と Claude Code、Cursor、Codex などのエージェントプラットフォームで動作します。テストファイルと`test-preferences.json` のみを作成・管理し、アプリケーションコードやエージェントコンテキストファイルは変更しません。テストフレームワークには Vitest、Jest、Playwright、Cypress、pytest、Go テストなどをサポートし、モノレポ構成にも対応します。

対応✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/toyin-software-factory/factory-template/tree/HEAD/.claude/skills/test

Installed? Explore more コーディング&開発 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

出力スタイル(平易な言葉、ダッシュなし、ハイフンなし)

このスキルが生成するすべてのもの(ファイルやメッセージを含む)は、平易でシンプルな言葉で記述します。読者に対しては あなた と呼びかけ、同僚のように温かく直接的に接し、各ステップを実行してもスキップしてもよい推奨事項として提示し、命令はしません。実際の意味を持つ技術用語は保持し、それぞれを平易な言葉で説明します。句読点としてダッシュやハイフンは使用しません:em ダッシュ、en ダッシュ、ハイフンでつなげた複合語も使いません。read-only ではなく read only と記述します。簡単な言葉で表現するか、文を言い換えてください。コード、ファイルパス、コマンドフラグ、他のスキルがマッチングに使用する値はハイフンを保持します。短い文、カンマ、括弧を使用します。明確さが巧妙さに勝ります。

このスキルの機能

役割:コードにふさわしいテストスイートを書くシニアテストエンジニア。カバレッジ数値のためではなく、呼び出し元が依存するものや実際に誰かを壊すであろうものをテストします。ファイルの内容を読み取ってファイルごとに戦略を選択します。スライスが実際に実現することを意図していなかった足場をロックインするテストは拒否します。

対象:このブランチで変更されたがまだコミットされていないコード。各変更ファイルは分類され(純粋ロジック、コンポーネント、API ルート、ページ/フロー)、適切な戦略でテストされます。メインスレッドがテスト自体を記述します(読み取り専用の scout が大規模なセットのための重いファイル読み取りを行う場合があります)。統括仕様がある場合、テストはその受け入れ基準にトレースします(ステップ 7 と 8)。

アプリケーションコードは書きません。AGENTS.md/CLAUDE.md コンテキストファイルは更新しません(/sync が担当します)。

尋ねる vs 実行する

  • test-preferences.json が存在し、ツールがインストールされ、未コミットのソースファイルが存在する場合は、尋ねずに実行します:直接テスト作成に進みます。
  • 毎回必ず 1 つだけ尋ねます(環境設定があっても):テストスイートを実行するか、手動の指示を返すか(ステップ 7.5)。実行ごとの選択で、保存はしません。
  • それ以外では、以下の場合のみ尋ねます:test-preferences.json がない(フレームワーク、ページ/フローが変更された場合のみ E2E アドオン)、選択したツールがインストールされていない(確認)、未コミットの変更がない(ステップ 3)、ファイルが 15 個を超える(ステップ 1b)。
  • スコープの質問はありません。Git ワーキングツリーがスコープを定義します。

成果物の所有権

  • テストファイル(*.test.ts、*.spec.ts、test_*.py、*_test.go など):このスキルが作成します
  • test-preferences.json(プロジェクトルート):このスキルが作成・管理します

移植性(任意の OS、任意のエージェント)

macOS、Linux、Windows 上の任意の Agent Skills クライアント:

  • git のみが必要な CLI で、すべての環境で同一です。git の行はそのまま実行してください。その他のシェルスニペットは POSIX リファレンスであり、リテラルスクリプトではありません:find、grep、sed、cat、test/[ ]、xargs、mkdir -p、node -e が存在するとは想定しないでください。エージェントのクロスプラットフォームファイルツール(読み取り、検索/glob、書き込み)を使用し、シェルの if/変数/リダイレクトではなく、自分で分岐ロジックを適用してください。
  • バンドルファイル:このスキルのフォルダからの相対パスで参照されます。メインスレッドがフォルダを絶対パスに解決し、書き込み時(ステップ 8)にバンドルファイル自体を読み取ります:agent-prompt.md と writing-guide.md。
  • インタラクティブな質問をサポートしていない場合?複数選択の質問は、同じオプションをプレーンテキストで尋ねてください。

以下の Ask ブロックでは、各オプションは "ラベル": "説明" の形式です。エージェントのピッカー(Claude Code では AskUserQuestion)またはプレーンテキストでレンダリングしてください。

実行

プリフライト(メインスレッド)

1. Git からスコープを決定する(これを最初に行い、空の場合は質問する意味がない)

変更されたがコミットされていないファイル(クロスプラットフォーム git):

  • 追跡対象(ステージング済み + 未ステージング)、削除を除外:git diff --name-only --diff-filter=ACMR HEAD
  • 未追跡で無視されていないもの:git ls-files --others --exclude-standard
  • まだコミットがない場合(git diff HEAD がエラーになる):git diff --name-only --diff-filter=ACMR --cached を使用。

結合し、重複を削除し、テスト不可能なファイルを除外します:

  • テストファイル:*.test.*、*.spec.*、test_*.py、*_test.go、__tests__/、e2e/、tests/、cypress/ 配下のもの
  • 設定ファイル:*.config.*、.*rc、tsconfig*、*.json(ロジックが JSON に存在する場合を除く)、Dockerfile、CI yaml
  • ロックファイル:.lock、生成物/ビルド出力(dist/、build/、.next/、coverage/)
  • スタイルシート:*.css、*.scss、*.module.css、型のみの宣言:*.d.ts
  • ドキュメントとマークダウン、仕様書、design.md、test-preferences.json

残りがスコープです。空の場合はステップ 3 に進みます。それ以外の場合は続行します。

1b. 各スコープファイルを分類する

パスとファイル名のみから安価に分類します。真に曖昧な場合は logic とタグ付けし、書き込み時にファイルを読み取ったときに再度タグ付けします。書き込みステップのために各ファイルのクラスを記録します。

パス/ファイル名のシグナルクラステスト戦略
*.tsx/*.jsx/*.vue/*.svelte(ルート/ページパス配下ではない)componentコンポーネントテスト(レンダリング+操作+DOM/ARIA アサーション)
app/**/page.*、pages/**(pages/api 以外)、*Screen.*、*View.*page/flowE2E 候補+部品のコンポーネントテスト
app/**/route.*、pages/api/**、*.controller.*、*.handler.*、*.resolver.*、actions.*api/server統合テスト(ハンドラを呼び出し、境界でモック)
プレーンな .ts/.js/.py/.go/.rs、ユーティリティ、フック、サービス、ドメインロジックlogicユニットテスト(入力→出力、エッジケース、エラー)
cli.*、bin/**、*.command.*、cmd/**cliコマンドを呼び出す統合テスト

E2E_RELEVANT = yes:いずれかのファイルが page/flow の場合、それ以外は no。

大きな差分ガード:15 個を超えるソースファイルがある場合、1 回で全てを記述しようとしないでください。クラスで優先順位を付け(ロジックと api/server を最初に、最もリスクが高く、安価に十分テストできる)、以下のように尋ねます:

Ask: "<N> 個の変更ファイルは一度に扱うには多すぎます。どのように集中すべきですか?"(ヘッダー:"Scope size")
- "Logic & API first(推奨)": "今は <count> 個のロジック/API ファイルをテストします。残りは未カバーとして記録します"
- "Test everything in batches": "すべての <N> ファイルを複数回に分けてカバーします。遅いですが完全です"
- "Let me narrow it": "最も重要なファイルまたはディレクトリを指定します"

モノレポ解決:各スコープファイルの最も近い親 package.json を見つけます(上にたどる)。異なるルートの場合:ルートごとにグループ化します(独自のフレームワーク、パッケージマネージャー、テストディレクトリを持ち、グループごとにインストールと記述を行います)。1 つの共有ルート(一般的なケース):単一プロジェクトです。書き込みステップのために各ファイルの packageRoot を記録します。


2. 環境設定を読み込む

プロジェクトルートの test-preferences.json を読み取ります(ファイルツールで;「見つかりません」=環境設定なし)。ファイルの存在ではなく、tool の名前が設定されているかどうかで分岐します:

  • tool が設定されている(一般的な書き込みパス):tool、additionalTools、e2eTool、testDir、filePattern、packageManager を読み込み、ステップ 5 にスキップします。
  • tool が null で gate が設定されている(GATE_ONLY):このプロジェクトは以前の意図的な選択により、テストランナーなしでゲートします。テストスイートを書かず、ランナーをインストールせず、再度尋ねず、modes/setup.md を読みません。プロジェクトの型チェック/リンターゲートを実行し、停止して報告します:「このプロジェクトは <gate> でゲートしています。型チェックゲートを実行しました。動作確認には /check verify を使用してください。」
  • ファイルがない(NO_PREFS、初回実行):modes/setup.md を読み、そのステップ 4(スタック検出とフレームワークの質問)を実行し、ここでステップ 5(インストール確認)に戻り、そのステップ 6(環境設定の保存)を実行し、次にステップ 7 に進みます。書き込み実行時に modes/setup.md を読まないでください。
  • 不正な形式(tool も gate もないファイル、または解析不能な JSON):その旨を伝え、NO_PREFS として扱い、セットアップを再度実行して上書きします。

3. 未コミットの変更がない

空のスコープ:フレームワークの質問をスキップし、エンジニアに伝え、代替案を提供します:

Ask: "未コミットのソース変更が見つかりませんでした。何をテストすべきですか?"(ヘッダー:"No changes")
- "The last commit": "HEAD~1..HEAD の差分を取り、そのコミットが変更したものをテストします"
- "Specific files": "指定したファイルまたはディレクトリをテストします"
- "Nothing right now": "停止します。変更後に /test を実行してください"
  • 最後のコミット:スコープ = git diff --name-only --diff-filter=ACMR HEAD~1 HEAD、ステップ 1b を再度実行します。
  • 特定のファイル:指定されたファイルを分類し、続行します。
  • 何もしない:正常に停止します。

5. インストール確認

選択されたユニットツール、E2E ツール(ある場合)、アドオン(ある場合)をファイルツールで確認します:

  • JS/TS:node_modules/<pkg> 配下、または package.json の devDependencies にありますか?
  • Python:pyproject.toml/requirements.txt にありますか(または Python が利用可能な場合は pip show <tool>)?
  • Go:go.sum に stretchr/testify がありますか?

すべて存在する → ステップ 6。いずれか欠けている → 最初に確認します:

Ask: "<欠けているツール> がインストールされていません。今インストールしますか?"(ヘッダー:"Install")
- "Yes, install and continue": "検出されたパッケージマネージャーでインストールを実行し、テストを記述します"
- "No, write runnable stubs": "インストールをスキップし、自分でツールをインストールした後に実行できるテストを記述します"

Yes:検出されたパッケージマネージャーでインストールします。ここでは <pkgmgr> と表示されます(検出された npm / yarn / pnpm / bun;Python/Go の場合は言語のマネージャーを使用します):

<pkgmgr> add -D vitest                                            # ユニット
<pkgmgr> add -D @testing-library/<framework> @testing-library/user-event @testing-library/jest-dom  # アドオン
<pkgmgr> add -D @playwright/test && <pkgmgr> exec playwright install  # E2E(Playwright)
<pkgmgr> add -D cypress                                          # E2E(Cypress)
pip install pytest pytest-mock                                    # Python
go get <testify module path>                                      # Go

「No」:INSTALL=deferred を記録し、完全なテストを記述し、実行コマンドは「インストール後に実行」として報告します。


7. 軽量なポインタを収集する(ここでは重いファイルを読まない)

パスと安価なシグナルのみ。重い読み取りは書き込み時に行います(あなた自身、またはオフロードする場合は scout が行います)。仕様書、design.md、ソースファイルをここで完全に読まないでください。

ファイルツールを使用:

  • docs/specs/ 配下で最も最近変更された 3 つのスペックパスをリストします(パスのみ)。
  • 統括仕様を特定します:これらのファイルが実装するフィーチャーディレクトリ docs/specs/NNNN-<feature>/(または単一ファイル docs/specs/NNNN-<feature>.md)で、ブランチ/フィーチャー名または触れた表面でマッチングします(docs/scope/ エントリがあればそれを指します)。そのパスと、その隣に verify.md があるかどうかを記録します(docs/specs/NNNN-<feature>/verify.md)。この契約がテストがトレースするものです。3 つの最近のパスのうちに含まれていない場合があります。統括仕様が存在する場合は TRACE_TO_CONTRACT = yes を設定し、それ以外は no を設定します。
  • design.md がプロジェクトルートに存在するかどうかを記録します。スコープに component または page/flow ファイルがある場合のみそのパスを使用し、それ以外は none を使用します。
  • AGENTS.md(標準;存在しない場合は CLAUDE.md)をプロジェクトコンテキストとして読み取ります(短く安価)。また、ビルドアプローチを 1 行で記録します:チームが選択したスライス整形アプローチで、スコープヘッダー(またはルート AGENTS.md)に記録されています。例:薄いエンドツーエンドパス、最も薄い使用可能なコアループ、プレースホルダー上の UI ファーストシェル、フェーズごとの完全なユーザージャーニー。ロジックを分岐させるわけではありませんが、書き込み時の判断(ステップ 8、ルール a)を調整します。
  • package.json を読み取り、scripts.test を記録します。test スクリプトが存在する場合は RUN_COMMAND = <pkgmgr> test(npm の場合は <pkgmgr> run test)。存在しない場合のみ、生の呼び出し(例:<pkgmgr> exec vitest run)を使用します。

7.5 テストスイートを実行するかどうかを尋ねる(常に)

Ask: "<N> 個の変更ファイルに対してテストが記述されます。記述後にスイートを実行しますか?"(ヘッダー:"Run tests?")
- "Yes, run and fix to green": "スイートを実行し、テストの誤りを修正し、テストが捕捉した実際のバグを報告します"
- "Skip, just write them": "テストを記述し、手動での実行と確認手順を提供します"

RUN_AFTER = yes | no を設定し、書き込み時に適用します。

8. スイートを記述する(メインスレッド)

メインスレッドがテスト自体を記述します。ライターを起動しないでください。このスキルのフォルダを絶対パスに解決し、agent-prompt.md と writing-guide.md を今すぐ(書き込み時にのみ)読み取ります:agent-prompt.md は操作テンプレート、writing-guide.md は戦略、ツールルール、反復ループ、レポート形式であり、これに従います。テスト対象の変更ファイルを読み取ることが唯一の高コスト部分です。大規模または不慣れなセットの場合、読み取りのみを読み取り専用の scout サブエージェントに最も安価なモデル(Claude Code では haiku、セッションモデルを継承しない)でオフロードし、コンパクトなマップを返させ、それから記述します。

適用する入力(収集したラベル付き値):

  1. ユニットツール、E2E ツール、追加ツール、INSTALL 状態;testDir、filePattern、パッケージマネージャー、スタック/フレームワーク、packageRoot;分類されたスコープ(各ファイルパスとそのクラス:logic / component / page flow / api server / cli);RUN_COMMAND、RUN_AFTER;プロジェクトコンテキストとビルドアプローチの行;最近の 3 つのスペックパスまたは none(テスト対象に関連する場合のみ読み取り);design.md パスまたは none;TRACE_TO_CONTRACT、統括仕様パス、verify.md パス(存在しない場合はそれぞれ none)。
  2. 適用する 2 つのルール:(a) ビルドアプローチを使用して、このスライスにとってどの振る舞いが耐久性のある実際のものか(それらを安定したアサーションとしてロックインする)を調整し、対して、スライスが設計上偽装する意図的な足場(計画がまだ構築していない実際の実装、例えばデータをスタブするシェル上の実際のバックエンド期待など)はアサーションしないでください。(b) TRACE_TO_CONTRACT = yes の場合、受け入れ基準(存在する場合は verify.md から、すでに解決された AC-N タグ付きチェックリストを優先し、それ以外は仕様の ## Requirements から)を読み取り、耐久性のあるものをロックインします:安定したアサーションとして固定できる各基準に対する自動テスト、各テストはそれがカバーする AC-N でタグ付けされます(例:covers: AC-3 コメント、またはテストタイトルに AC-3 を含める)。自動化できない基準(ビジュアル/手動/環境依存、例:「メールが実際に届く」)を決して偽装しないでください。NOT_COVERED に記録します:AC-N, <自動化できない理由> → /check verify 手動ステップに委ねる。

モノレポ(ステップ 1b からの複数のパッケージルート):各ルートのスイートを順番に記述し、そのルートのファイル、ツール、パッケージマネージャーにスコープします(大規模な場合は各ルートのファイル読み取りを独自の scout にオフロードします)。単一ルート(一般的なケース)

…

[翻訳のために一部省略]

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

関連スキル