Best for
- Use this skill when writing new features, fixing bugs, or refactoring code.
affaan-m/ECC/docs/zh-TW/skills/tdd-workflow/SKILL.md
Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage including unit, integration, and E2E tests.
Decision brief
此技能確保所有程式碼開發遵循 TDD 原則,並具有完整的測試覆蓋率。
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/affaan-m/ECC --skill "docs/zh-TW/skills/tdd-workflow"Inspect the Agent Skill "tdd-workflow" from https://github.com/affaan-m/ECC/blob/4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38/docs/zh-TW/skills/tdd-workflow/SKILL.md at commit 4e973d3eaf92d97f8d2e2d8abb39d8bdc8711b38. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
撰寫新功能或功能性程式碼
最低 80% 覆蓋率(單元 + 整合 + E2E)
Review the “1. 測試先於程式碼” section in the pinned source before continuing.
最低 80% 覆蓋率(單元 + 整合 + E2E)
個別函式和工具
Permission review
The documentation asks the agent to run terminal commands or scripts.
npm testThe documentation asks the agent to run terminal commands or scripts.
npm testThe documentation includes network, browsing, or remote request actions.
const request = new NextRequest('http://localhost/api/markets')The documentation includes network, browsing, or remote request actions.
const request = new NextRequest('http://localhost/api/markets?limit=invalid')Evidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 67/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 234,327 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
此技能確保所有程式碼開發遵循 TDD 原則,並具有完整的測試覆蓋率。
總是先寫測試,然後實作程式碼使測試通過。
身為 [角色],我想要 [動作],以便 [好處]
範例:
身為使用者,我想要語意搜尋市場,
以便即使沒有精確關鍵字也能找到相關市場。
為每個使用者旅程建立完整的測試案例:
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 () => {
// 測試排序邏輯
})
})
npm test
# 測試應該失敗 - 我們還沒實作
撰寫最少的程式碼使測試通過:
// 由測試引導的實作
export async function searchMarkets(query: string) {
// 實作在此
}
npm test
# 測試現在應該通過
在保持測試通過的同時改善程式碼品質:
npm run test:coverage
# 驗證達到 80%+ 覆蓋率
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()
})
})
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 () => {
// Mock 資料庫失敗
const request = new NextRequest('http://localhost/api/markets')
// 測試錯誤處理
})
})
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')
// 等待 debounce 和結果
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
jest.mock('@/lib/supabase', () => ({
supabase: {
from: jest.fn(() => ({
select: jest.fn(() => ({
eq: jest.fn(() => Promise.resolve({
data: [{ id: 1, name: 'Test Market' }],
error: null
}))
}))
}))
}
}))
jest.mock('@/lib/redis', () => ({
searchMarketsByVector: jest.fn(() => Promise.resolve([
{ slug: 'test-market', similarity_score: 0.95 }
])),
checkRedisHealth: jest.fn(() => Promise.resolve({ connected: true }))
}))
jest.mock('@/lib/openai', () => ({
generateEmbedding: jest.fn(() => Promise.resolve(
new Array(1536).fill(0.1) // Mock 1536 維嵌入向量
))
}))
npm run test:coverage
{
"jest": {
"coverageThresholds": {
"global": {
"branches": 80,
"functions": 80,
"lines": 80,
"statements": 80
}
}
}
}
// 不要測試內部狀態
expect(component.state.count).toBe(5)
// 測試使用者看到的內容
expect(screen.getByText('Count: 5')).toBeInTheDocument()
// 容易壞掉
await page.click('.css-class-xyz')
// 對變更有彈性
await page.click('button:has-text("Submit")')
await page.click('[data-testid="submit-button"]')
// 測試互相依賴
test('creates user', () => { /* ... */ })
test('updates same user', () => { /* 依賴前一個測試 */ })
// 每個測試設置自己的資料
test('creates user', () => {
const user = createTestUser()
// 測試邏輯
})
test('updates user', () => {
const user = createTestUser()
// 更新邏輯
})
npm test -- --watch
# 檔案變更時自動執行測試
# 每次 commit 前執行
npm test && npm run lint
# GitHub Actions
- name: Run Tests
run: npm test -- --coverage
- name: Upload Coverage
uses: codecov/codecov-action@v3
記住:測試不是可選的。它們是實現自信重構、快速開發和生產可靠性的安全網。
Alternatives
affaan-m/ECC
Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage including unit, integration, and E2E tests.
affaan-m/ECC
Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage including unit, integration, and E2E tests.
affaan-m/ECC
Use this skill when writing new features, fixing bugs, or refactoring code. Enforces test-driven development with 80%+ coverage including unit, integration, and E2E tests.
affaan-m/ECC
Use it for testing and engineering tasks; the detail page covers purpose, installation, and practical steps.