Skills Plugins MCP Prompt Model 博客 我的中心

tdd-workflow

新機能の作成、バグ修正、コードのリファクタリング時にこのスキルを使用します。ユニット、統合、E2Eテストを含む80%以上のカバレッジでテスト駆動開発を強制します。

DeepseekModel 官方收录技能 质量 优秀 · 90 v1.0.0

获取

https://deepseekmodel.com/api/download.php?id=affaan-m-ecc-docs-ja-jp-skills-tdd-workflow-skill-md&format=skill
下载 .skill 标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用
.skill 文件中 system_prompt 字段的实际内容。
name tdd-workflow description 新機能の作成、バグ修正、コードのリファクタリング時にこのスキルを使用します。ユニット、統合、E2Eテストを含む80%以上のカバレッジでテスト駆動開発を強制します。 テスト駆動開発ワークフロー このスキルは、すべてのコード開発が包括的なテストカバレッジを備えたTDDの原則に従うことを保証します。 有効化するタイミング 新機能や機能の作成 バグや問題の修正 既存コードのリファクタリング APIエンドポイントの追加 新しいコンポーネントの作成 コア原則 1. コードの前にテスト 常にテストを最初に書き、次にテストに合格するコードを実装します。 2. カバレッジ要件 最低80%のカバレッジ(ユニット + 統合 + E2E) すべてのエッジケースをカバー エラーシナリオのテスト 境界条件の検証 3. テストタイプ ユニットテスト 個々の関数とユーティリティ コンポーネントロジック 純粋関数 ヘルパーとユーティリティ 統合テスト APIエンドポイント データベース操作 サービス間相互作用 外部API呼び出し E2Eテスト (Playwright) クリティカルなユーザーフロー 完全なワークフロー ブラウザ自動化 UI相互作用 TDDワークフローステップ ステップ1:ユーザージャーニーを書く [役割]として、[行動]をしたい、それによって[利益]を得られるようにするため 例: ユーザーとして、セマンティックに市場を検索したい、 それによって正確なキーワードなしでも関連する市場を見つけられるようにするため。 ステップ2:テストケースを生成 各ユーザージャーニーについて、包括的なテストケースを作成: describe ( 'Semantic Search' , () => { it ( 'returns relevant markets for query' , async () => { // テスト実装 }) it ( 'handles empty query gracefully' , async () => { // エッジケースのテスト }) it ( 'falls back to substring search when Redis unavailable' , async () => { // フォールバック動作のテスト }) it ( 'sorts results by similarity score' , async () => { // ソートロジックのテスト }) }) ステップ3:テストを実行(失敗するはず) npm test # テストは失敗するはず - まだ実装していない ステップ4:コードを実装 テストに合格する最小限のコードを書く: // テストにガイドされた実装 export async function searchMarkets ( query : string ) { // 実装はここ } ステップ5:テストを再実行 npm test # テストは今度は成功するはず ステップ6:リファクタリング テストをグリーンに保ちながらコード品質を向上: 重複を削除 命名を改善 パフォーマンスを最適化 可読性を向上 ステップ7:カバレッジを確認 npm run test :coverage # 80%以上のカバレッジを達成したことを確認 テストパターン ユニットテストパターン (Jest/Vitest) import { render, screen, fireEvent } from '@testing-library/react' import { Button } from './Button' describe ( 'Button Component' , () => { it ( 'renders with correct text' , () => { render ( < Button > Click me </ Button > ) expect (screen. getByText ( 'Click me' )). toBeInTheDocument () }) it ( 'calls onClick when clicked' , () => { const handleClick = jest. fn () render ( < Button onClick = {handleClick} > Click </ Button > ) fireEvent. click (screen. getByRole ( 'button' )) expect (handleClick). toHaveBeenCalledTimes ( 1 ) }) it ( 'is disabled when disabled prop is true' , () => { render ( < Button disabled > Click </ Button > ) expect (screen. getByRole ( 'button' )). toBeDisabled () }) }) API統合テストパターン import { NextRequest } from 'next/server' import { GET } from './route' describe ( 'GET /api/markets' , () => { it ( 'returns markets successfully' , async () => { const request = new NextRequest ( 'http://localhost/api/markets' ) const response = await GET (request) const data = await response. json () expect (response. status ). toBe ( 200 ) expect (data. success ). toBe ( true ) expect ( Array . isArray (data. data )). toBe ( true ) }) it ( 'validates query parameters' , async () => { const request = new NextRequest ( 'http://localhost/api/markets?limit=invalid' ) const response = await GET (request) expect (response. status ). toBe ( 400 ) }) it ( 'handles database errors gracefully' , async () => { // データベース障害をモック const request = new NextRequest ( 'http://localhost/api/markets' ) // エラー処理のテスト }) }) E2Eテストパターン (Playwright) import { test, expect } from '@playwright/test' test ( 'user can search and filter markets' , async ({ page }) => { // 市場ページに移動 await page. goto ( '/' ) await page. click ( 'a[href="/markets"]' ) // ページが読み込まれたことを確認 await expect (page. locator ( 'h1' )). toContainText ( 'Markets' ) // 市場を検索 await page. fill ( 'input[placeholder="Search markets"]' , 'election' ) // デバウンスと結果を待つ await page. waitForTimeout ( 600 ) // 検索結果が表示されることを確認 const results = page. locator ( '[data-testid="market-card"]' ) await expect (results). toHaveCount ( 5 , { timeout : 5000 }) // 結果に検索語が含まれることを確認 const firstResult = results. first () await expect (firstResult). toContainText ( 'election' , { ignoreCase : true }) // ステータスでフィルタリング await page. click ( 'button:has-text("Active")' ) // フィルタリングされた結果を確認 await expect (results). toHaveCount ( 3 ) }) test ( 'user can create a new market' , async ({ page }) => { // 最初にログイン await page. goto ( '/creator-dashboard' ) // 市場作成フォームに入力 await page. fill ( 'input[name="name"]' , 'Test Market' ) await page. fill ( 'textarea[name="description"]' , 'Test description' ) await page. fill ( 'input[name="endDate"]' , '2025-12-31' ) // フォームを送信 await page. click ( 'button[type="submit"]' ) // 成功メッセージを確認 await expect (page. locator ( 'text=Market created successfully' )). toBeVisible () // 市場ページへのリダイレクトを確認 await expect (page). toHaveURL ( /\/markets\/test-market/ ) }) テストファイル構成 src/ ├── components/ │ ├── Button/ │ │ ├── Button.tsx │ │ ├── Button.test.tsx # ユニットテスト │ │ └── Button.stories.tsx # Storybook │ └── MarketCard/ │ ├── MarketCard.tsx │ └── MarketCard.test.tsx ├── app/ │ └── api/ │ └── markets/ │ ├── route.ts │ └── route.test.ts # 統合テスト └── e2e/ ├── markets.spec.ts # E2Eテスト ├── trading.spec.ts └── auth.spec.ts 外部サービスのモック Supabaseモック jest. mock ( '@/lib/supabase' , () => ({ supabase : { from : jest. fn ( () => ({ select : jest. fn ( () => ({ eq : jest. fn ( () => Promise . resolve ({ data : [{ id : 1 , name : 'Test Market' }], error : null })) })) })) } })) Redisモック jest. mock ( '@/lib/redis' , () => ({ searchMarketsByVector : jest. fn ( () => Promise . resolve ([ { slug : 'test-market' , similarity_score : 0.95 } ])), checkRedisHealth : jest. fn ( () => Promise . resolve ({ connected : true })) })) OpenAIモック jest. mock ( '@/lib/openai' , () => ({ generateEmbedding : jest. fn ( () => Promise . resolve ( new Array ( 1536 ). fill ( 0.1 ) // 1536次元埋め込みをモック )) })) テストカバレッジ検証 カバレッジレポートを実行 npm run test :coverage カバレッジ閾値 { "jest" : { "coverageThresholds" : { "global" : { "branches" : 80 , "functions" : 80 , "lines" : 80 , "statements" : 80 } } } } 避けるべき一般的なテストの誤り FAIL: 誤り:実装の詳細をテスト // 内部状態をテストしない expect (component. state . count ). toBe ( 5 ) PASS: 正解:ユーザーに見える動作をテスト // ユーザーが見るものをテスト expect (screen. getByText ( 'Count: 5' )). toBeInTheDocument () FAIL: 誤り:脆弱なセレクタ // 簡単に壊れる await page. click ( '.css-class-xyz' ) PASS: 正解:セマンティックセレクタ // 変更に強い await page. click ( 'button:has-text("Submit")' ) await page. click ( '[data-testid="submit-button"]' ) FAIL: 誤り:テストの分離なし // テストが互いに依存 test ( 'creates user' , () => { /* ... */ }) test ( 'updates same user' , () => { /* 前のテストに依存 */ }) PASS: 正解:独立したテスト // 各テストが独自のデータをセットアップ test ( 'creates user' , () => { const user = createTestUser () // テストロジック }) test ( 'updates user' , () => { const user = createTestUser () // 更新ロジック }) 継続的テスト 開発中のウォッチモード npm test -- --watch # ファイル変更時に自動的にテストが実行される プリコミットフック # すべてのコミット前に実行 npm test && npm run lint CI/CD統合 # GitHub Actions - name: Run Tests run: npm test -- --coverage - name: Upload Coverage uses: codecov/codecov-action@v3 ベストプラクティス テストを最初に書く - 常にTDD テストごとに1つのアサート - 単一の動作に焦点 説明的なテスト名 - テスト内容を説明 Arrange-Act-Assert - 明確なテスト構造 外部依存関係をモック - ユニットテストを分離 エッジケースをテスト - null、undefined、空、大きい値 エラーパスをテスト - ハッピーパスだけでなく テストを高速に保つ - ユニットテスト各50ms未満 テスト後にクリーンアップ - 副作用なし カバレッジレポートをレビュー - ギャップを特定 成功指標 80%以上のコードカバレッジを達成 すべてのテストが成功(グリーン) スキップまたは無効化されたテストなし 高速なテスト実行(ユニットテストは30秒未満) E2Eテストがクリティカルなユーザーフローをカバー テストが本番前にバグを検出 覚えておいてください :テストはオプションではありません。テストは自信を持ってリファクタリングし、迅速に開発し、本番の信頼性を可能にする安全網です。
Agent 识别该技能的关键词,点击任意一个即可复制。

该技能未提供触发词。

下载的 .skill 包内含以下字段。
字段 说明
format格式标识(skill/v1)
skill_id技能唯一 ID
name技能名称
version版本号
description技能描述
category所属分类(数组)
trigger_words触发词列表
tags标签列表
source来源标识
source_url来源链接(本页地址)
exported_at导出时间(每次下载生成)
system_prompt系统提示词正文
model_config模型参数:provider / model / temperature / max_tokens / top_p
examples示例
install_guide各平台导入说明(Coze / Dify / Claude / 自定义框架)
同一份技能可按不同平台格式导出。
.skill 标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用 下载
.skillpro 增强格式,额外含脚本 / 工具 / 依赖 / 钩子占位 下载
.json 纯 JSON 导出,只含 system_prompt 与模型参数 下载
Coze 带 frontmatter 的 Markdown,Coze 平台导入用 下载
Dify Dify DSL,创建应用后直接导入 下载

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。