tdd について
helpmetest向けの、テスト駆動開発とテスト保守を支援するスキルです。コーディングエージェントに、シナリオの計画、先行テストの作成と検証、失敗の診断を促し、作業の前後にはユーザーへの説明を求めます。
主な機能
- 01テスト先行の機能開発・修正フロー
- 02タスクと機能アーティファクトの計画
- 03シナリオの優先度付け
- 04対話型のテスト探索と検証
- 05失敗の分類と修正ガイド
- 06テスト作業前後の状況説明
活用シーン
- 01テスト先行で機能やリファクタリングを開始
- 02既存機能のテストを追加
- 03失敗したテストを診断・修正
MCP 対応
helpmetestのMCPツールによる状態確認、アーティファクト検索、対話型実行、テスト検証をエージェントに案内します。MCPが使えない場合は `helpmetest ` を使います。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ help-me-test/ skills --skill tddインストール後、Claude Code で/tddを入力して読み込まれたか確認します。
同梱ファイルreferences/examples/wishlist-example.md
詳細
あなたについて:
.helpmetest/SOUL.mdが存在する場合は、読んでください。そこにあなたのキャラクターが定義されています。
MCP がない場合: MCP ツールの代わりに
helpmetest <command>を使用してください。
🔴 まずテストを書いてください。
コードを変更したら → テストを実行してください。 新機能を追加する場合 → コードを書く前にテストを書いてください。 テストが仕様です。テストが成功したら完了です。 テストがなければ、未完了です。
作業内容を説明する
テスト、成果物を作成したり、テストを実行したりする際は、必ずユーザーに伝えてください。 次のことを伝えます。
- 実行前: 何を、なぜ実行するのか(どのシナリオを対象とし、どのリスクを防ぐのか)
- 実行後: 何が起きたか(結果、成果物の内容、テストが失敗した理由)
- 次の手順: 次に何をするのか、どのような判断が必要になるのか
何も伝えないと、ユーザーは何をしたのか、なぜしたのかがわかりません。
テスト — 作成、生成、修正
まず現状を確認する(必ず実施)
何かをする前に、すでに存在するものを確認してください。
helpmetest_status()
helpmetest_search_artifacts({ query: "" })
helpmetest_search_artifacts({ type: "Tasks" })
- すでに失敗しているテストがある場合 → 新しいテストの作成ではなく、それを優先します
- 進行中のタスク成果物がある場合 → 最初からやり直さず、そこから再開します
- 機能の成果物がある場合 → 再調査せず、それを使います
ユースケース
「何かを作りたい」(TDD)
新機能、バグ修正、リファクタリングが対象です。テストを先に書き、何をもって「完了」とするかを定義します。
1. 作業を追跡するためのタスク成果物を作成します。
{
"id": "tasks-[feature-name]",
"type": "Tasks",
"content": {
"overview": "What this implements and why",
"tasks": [
{ "id": "1.0", "title": "Write all tests first", "status": "pending", "priority": "critical" },
{ "id": "2.0", "title": "Implement to make tests pass", "status": "pending" },
{ "id": "3.0", "title": "All green — review for gaps", "status": "pending" }
]
}
}
2. テストを1つも書く前に、すべてのシナリオを含む機能成果物を作成します。
{
"id": "feature-[name]",
"type": "Feature",
"content": {
"goal": "What this feature does",
"functional": [
{ "name": "User can do X", "given": "...", "when": "...", "then": "...", "tags": ["priority:critical"], "test_ids": [] }
],
"edge_cases": [],
"bugs": []
}
}
3. テストを1つも書く前に、カバレッジを計画します。機能ごとに、次の4種類にわたってシナリオを列挙します。
| 種類 | 常に? | 問いかけること |
|---|---|---|
| クリティカルパス | ✅ 常に | すべてが正常に動作しているとき、実際のユーザーは何をしますか? |
| エラーパス | ✅ 常に | 本番環境でこれが壊れる可能性が最も高い3つの原因は何ですか? |
| 境界条件 | データ/ロジックがある場合 | しきい値によって動作が変わるのはどこですか? |
| エッジケース | 必要に応じて | 開発者が思いつかず、QA エンジニアならテストすることは何ですか? |
各シナリオに、すぐに書く(重要度:高/最高)/リリース前に書く(重要度:中)/省略する(外観のみ、カバー済み、信頼性が低い)のいずれかを付けます。すべてをテストするのではなく、壊れたときに大きな問題になるものをテストしてください。
4. 実装を始める前に、正常系、エッジケース、エラーのすべてのテストを書きます。失敗するテストが仕様です。
5. 段階的に実装します。優先度が最も高い失敗中のテストを選んで成功させ、次のテストに進みます。
6. すべてのテストが成功し、見落としたエッジケースがないか確認したら完了です。
「既存の機能のテストを書く」
機能はすでに存在する(または、誰かが構築したばかり)状態です。あなたの役割はテストのみです。
1. Feature アーティファクトを読む — helpmetest_get_artifact({ id: "feature-X" })。存在しない場合は、把握している内容に基づいて最初に作成します。
2. テストを書く前に、対話形式で動作を確認する — helpmetest_run_interactive_command を使って、シナリオを手順どおりに実行します。実際の動作を確認してから書いたテストは、実際のセレクターを使い、実際のタイミングを反映します。説明だけをもとに書いたテストは推測です。
As <persona>
Go To <url>
# Execute each Given/When/Then step, observe what actually happens
3. 各テストを書く前に、次の問いへの答えを声に出して確認します。
「このテストが合格しても、機能が実際には壊れていた場合、顧客から報告を受けるまで、どんなユーザーの苦情を見逃すでしょうか?」
その答えを [Documentation] の PROTECTS: 行に記載します。これはテストがユーザーに対して約束する内容です。省略可能な定型文ではありません。一文で答えられない場合は、テストを書くのではなく、シナリオをさらに検討する必要があります。
4. priority:critical のシナリオから優先してテストを書き、次に high、medium の順に進めます。それぞれのテストでは、次の点を守ります。
- 意味のある手順を5つ以上含める
- 要素が表示されていることだけでなく、ビジネス上の結果(データが保存された、状態が変化したなど)を検証する
- 登録やメールアドレスのフィールドには
Create Fake Emailを使い、ハードコードはしない [Documentation]はPROTECTS: <検知するユーザーの苦情>で始める
5. 検証する — シナリオに紐付ける前に、各テストを fix-tests で検証します。機能が壊れていても合格するテストは書き直す必要があります。バリデーターが PASS と判定するまで完了ではありません。
6. テストを紐付ける — 検証に合格した後に限り、各テスト ID を Feature アーティファクトの scenario.test_ids に追加します。
7. 実行して修正する — 新しく書いたテストが失敗した場合は、以下の「壊れたテストを修正する」を参照してください。
「壊れたテストを修正する」/「テストが失敗する」
まず、失敗のパターンを把握します。
最近のコード変更を確認します。
git diff --stat HEAD
git log --oneline -5
変更されたファイルから、考えられる原因を特定します。
components/、pages/→ セレクターの変更auth/、session/→ 認証状態の問題api/、routes/→ バックエンドエラー、またはレスポンス形式の変更
次に、テスト履歴を確認します。helpmetest_status({ id: "test-id", testRunLimit: 10 })
分類します。
- コード変更後に継続して失敗する → セレクターまたは動作が変更された
- エラーが変わりながら PASS/FAIL を繰り返す → 分離の問題(状態の共有、テスト順序への依存)
- タイムアウト/要素が表示されない → タイミングの問題
- 認証/セッションエラー → 状態が正しく復元されていない
- テスト出力にバックエンドエラーがある → テストの問題ではなく、実際のバグ
対話形式で再現する — 修正前に必ず実施します。
失敗した手順を一つずつ実行します。
As <persona>
Go To <url>
# Execute each step, observe what actually happens at the point of failure
「要素が見つからない」場合:その種類の要素をすべて列挙し、別のセレクターを試します。 「値が違う」場合:実際に表示されている内容と、テストが期待する内容を確認します。 タイムアウトの場合:待機時間を長くし、要素が表示されるかどうかを確認します。
テストの問題か、アプリのバグかを判断します。
- テストの問題(セレクターの変更、タイミング、期待値の誤り)→ テストを修正し、保存する前に対話形式で修正を検証します
- アプリのバグ(機能が実際に壊れている)→
feature.bugs[]に記録し、Feature.status を "broken" または "partial" に更新します
UI の変更後に多くのテストが失敗した場合
一つずつ順に対応します。それぞれについて、次の手順を実施します。
- 失敗を分類する(通常はセレクターまたはタイミング)
- 対話形式で再現する
- 修正する
- 実行して確認する
推測で手当たり次第に修正しないでください。誤った修正を一つ加えるだけで、壊れたテストが二つになります。
リファクタリング後にテストが古くなった場合
- テスト一覧を取得します。
helpmetest_status() - 失敗したテストごとに、Feature アーティファクトのシナリオが意図した動作と一致しているか確認します
- コードが正とされる場合 → テストを更新します
- テストが正しく、リファクタリングによって動作が壊れた場合 → リグレッションを記録します
テストを書く
構成
As <persona> # auth state — always first
Go To <url>
# Given — establish precondition
<steps>
# When — perform the action
<steps>
# Then — verify the outcome
<assertions>
# Persistence check (if relevant)
Reload
<re-assert that state survived>
Documentation format
Every test must have [Documentation] with four explicit lines:
[Documentation]
... Given: <precondition — what state the system is in before the action>
... When: <action — what the user/system does>
... Then: <outcome — what is asserted, specifically>
... Risk: <what silent failure this catches — user complaint if this test were deleted>
Full example:
[Documentation]
... Given: registered user with valid account
... When: submits login form with wrong password
... Then: sees "Invalid email or password" error, remains on login page, is NOT authenticated
... Risk: silent login failure — attacker gets in, or user is confused with no feedback
Given/When/Then — what makes them good:
- ✅
Given: registered user with valid account— 具体的な前提条件 - ✅
When: submits login form with wrong password— 正確な操作 - ✅
Then: sees "Invalid email or password" error, remains on login page, is NOT authenticated— 具体的で、複数のアサーションが明記されています - ❌
Given: user is logged in | When: they do something | Then: it works— 曖昧で、テストが失敗したときに何が問題なのかわかりません
Language rules — the description must be readable by a product manager:
- ✅ ユーザーの操作と目に見える結果の観点で記述します
- ❌ CSS セレクター、XPath、DOM クラス名(
.keyword-line.current、#submit-btn、div[data-id])は絶対に記述しないでください - ❌ JavaScript の内部処理、変数名、デバッグ API(
replayDebug.currentKeyword、window.__state)は絶対に記述しないでください - ❌ Robot Framework の構文、キーワード名、技術的な実装の詳細は絶対に記述しないでください
- テスト本体にはセレクターを記述します。説明はプロダクトマネージャー向けに記述します。
Wrong:
Given: replay loaded with .banner-keywords visible
When: user clicks .banner-next and replayDebug.currentKeyword changes
Then: .keyword-line.current text matches window.replayDebug.currentKeyword.split(/ {2,}/)[0]
Right:
Given: a test replay is open and paused
When: user steps forward then backward through keywords using the navigation buttons
Then: the highlighted keyword in the banner matches the current playback position after each navigation
Risk — good examples:
- ✅
Risk: users completing checkout get charged without receiving an order confirmation - ✅
Risk: users typing wrong passwords are silently logged in or shown a blank screen - ✅
Risk: profile email changes silently fail — user sees stale email with no indication - ❌
Risk: the login form breaks— 曖昧すぎます。何が壊れ、誰が気づくのでしょうか? - ❌
Risk: the form doesn't submit— それはテストの内容であり、テストが防ぐリスクではありません
Inline comments
一目でわからない各ステップの上には、エンジニアではなくプロダクトマネージャー向けの # comment を必ず記述します。
コメントでは、ステップが必要な理由、ユーザーがどのような状態にあるか、またはテストで何を確認するかを説明します。キーワードの動作を説明するものではありません。
# User opens an existing test replay — this is the entry point for debugging failed tests
Go To https://helpmetest.example.com/test/some-test
# The banner shows the current keyword being replayed — it must stay in sync with what's actually executing
Click css=.banner-next
# After stepping forward, the highlighted keyword in the banner must change to match the new position
# If this fails, users see the wrong keyword highlighted while debugging — they investigate the wrong step
${label}= Get Text css=.keyword-line.current .keyword-text
Should Contain ${label} ${expected_keyword}
次の項目には必ずコメントを付けてください。
Javascriptの呼び出し — ユーザーから見えるどの状態を読み取る、または変更するのかを説明しますHoverまたはSleep— UI でこれが必要な理由を説明します(非表示要素を表示するためのホバー、アニメーションのためのスリープなど)- 複数ステップからなるアサーションのグループ — グループ全体で何を確認するのかを説明します
- 明らかなページ遷移ではないセットアップ手順
What makes a good test
✅ ビジネス上の成果(データの保存、フィルターの適用、注文の作成など)を検証します
✅ 機能が壊れていれば失敗します
✅ 意味のあるステップが5つ以上あります
✅ ボタンが存在するかだけでなく、状態の変化を確認します
❌ ページに移動して要素の数を数えるだけです
❌ 何が起きたか確認せずに何かをクリックします
❌ 機能が壊れていても成功します
Test naming
形式:User can <action> または <Feature> <behavior>
- ✅
User can update profile email - ✅
Cart total updates when quantity changes - ❌
MyApp Login Test - ❌
SiteName Checkout
Auth
Save As <StateName> を一度使用して認証状態を保存します。すべてのテストで As <StateName> を使って再利用し、テスト内で認証し直すことは絶対に避けてください。
Emails
Create Fake Email を使用し、[email protected] をハードコードすることは絶対に避けてください。メールアドレスをハードコードすると、2回目の実行で問題が発生します。
${email}= Create Fake Email
Fill Text input[name=email] ${email}
${code}= Get Email Verification Code ${email}
Localhost
ローカルサーバーをテストする場合は、まずプロキシを設定します。
helpmetest_proxy({ action: "start", domain: "dev.local", sourcePort: 3000 })
テストを書く前に、正常に動作することを確認してください。詳細は proxy スキルを参照してください。
Tags
priority:critical|high|medium|lowfeature:[feature-name]type:e2e|smoke|regression
Done means
- ✅ すべてのテストが成功している
- ✅
priority:criticalのすべてのシナリオにtest_idsがある - ✅ すべてのテストの
[Documentation]にGiven:、When:、Then:、Risk:の行がある - ✅ すべてのテストがリンクされる前に
/fix-testsを通過している - ✅ バグが
feature.bugs[]に記録されている - ✅
Feature.statusが更新されている(working/broken/partial) - ✅ Tasks アーティファクトがすべて完了している
Final summary format
「N tests created, M passing.」で終わらせないでください。次の形式で終わらせます。
## What you can now trust works
- <user-facing statement> (test: <id>)
- <user-facing statement> (test: <id>)
## What's still unprotected
- <what could silently break with no test catching it>
## Bugs found
- <bug description> — documented in feature.bugs[]
最初のセクションをユーザー向けの言葉で書けない場合、テストはまだ完了していません。