Tdd Workflow

affaan-m/ECC/.kiro/skills/tdd-workflow

by affaan-mef648e01899ba3e8dc6371642deaaf64b4477775No license275K starsListed Oct 9, 2026Updated Oct 9, 2026Repository updated 4 days ago

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.

Instructions onlySoftware Development
AI-generated overview

Guides test-driven development: write tests first, implement code, refactor, and verify 80%+ coverage.

What it does
This skill provides an instruction-only workflow for test-driven development. It walks through writing user journeys, generating unit, integration, and E2E test cases, running tests to see them fail, implementing minimal code, refactoring, and checking coverage. It also supplies testing patterns, mocking examples, file organization conventions, and common mistakes to avoid.
When to use it
Use it when adding new features, fixing bugs, refactoring code, adding API endpoints, or creating new components. It is intended for teams or agents that want tests written before implementation and a minimum coverage threshold enforced.
Requirements
No scripts are included; it is instructions only. The examples assume a JavaScript or TypeScript project with npm, Jest or Vitest, React Testing Library, Playwright, and optional mocking of services such as Supabase, Redis, and OpenAI.

Test-Driven Development Workflow

This skill ensures all code development follows TDD principles with comprehensive test coverage.

When to Activate

  • Writing new features or functionality
  • Fixing bugs or issues
  • Refactoring existing code
  • Adding API endpoints
  • Creating new components

Core Principles

1. Tests BEFORE Code

ALWAYS write tests first, then implement code to make tests pass.

2. Coverage Requirements

  • Minimum 80% coverage (unit + integration + E2E)
  • All edge cases covered
  • Error scenarios tested
  • Boundary conditions verified

3. Test Types

Unit Tests
  • Individual functions and utilities
  • Component logic
  • Pure functions
  • Helpers and utilities
Integration Tests
  • API endpoints
  • Database operations
  • Service interactions
  • External API calls
E2E Tests (Playwright)
  • Critical user flows
  • Complete workflows
  • Browser automation
  • UI interactions

TDD Workflow Steps

Step 1: Write User Journeys

As a [role], I want to [action], so that [benefit]
Example:As a user, I want to search for markets semantically,so that I can find relevant markets even without exact keywords.

Step 2: Generate Test Cases

For each user journey, create comprehensive test cases:

typescript
describe('Semantic Search', () => {  it('returns relevant markets for query', async () => {    // Test implementation  })
  it('handles empty query gracefully', async () => {    // Test edge case  })
  it('falls back to substring search when Redis unavailable', async () => {    // Test fallback behavior  })
  it('sorts results by similarity score', async () => {    // Test sorting logic  })})

Step 3: Run Tests (They Should Fail)

bash
npm test# Tests should fail - we haven't implemented yet

Step 4: Implement Code

Write minimal code to make tests pass:

typescript
// Implementation guided by testsexport async function searchMarkets(query: string) {  // Implementation here}

Step 5: Run Tests Again

bash
npm test# Tests should now pass

Step 6: Refactor

Improve code quality while keeping tests green:

  • Remove duplication
  • Improve naming
  • Optimize performance
  • Enhance readability

Step 7: Verify Coverage

bash
npm run test:coverage# Verify 80%+ coverage achieved

Testing Patterns

Unit Test Pattern (Jest/Vitest)

typescript
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 Integration Test Pattern

typescript
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 database failure    const request = new NextRequest('http://localhost/api/markets')    // Test error handling  })})

E2E Test Pattern (Playwright)

typescript
import { test, expect } from '@playwright/test'
test('user can search and filter markets', async ({ page }) => {  // Navigate to markets page  await page.goto('/')  await page.click('a[href="/markets"]')
  // Verify page loaded  await expect(page.locator('h1')).toContainText('Markets')
  // Search for markets  await page.fill('input[placeholder="Search markets"]', 'election')
  // Wait for debounce and results  await page.waitForTimeout(600)
  // Verify search results displayed  const results = page.locator('[data-testid="market-card"]')  await expect(results).toHaveCount(5, { timeout: 5000 })
  // Verify results contain search term  const firstResult = results.first()  await expect(firstResult).toContainText('election', { ignoreCase: true })
  // Filter by status  await page.click('button:has-text("Active")')
  // Verify filtered results  await expect(results).toHaveCount(3)})
test('user can create a new market', async ({ page }) => {  // Login first  await page.goto('/creator-dashboard')
  // Fill market creation form  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')
  // Submit form  await page.click('button[type="submit"]')
  // Verify success message  await expect(page.locator('text=Market created successfully')).toBeVisible()
  // Verify redirect to market page  await expect(page).toHaveURL(/\/markets\/test-market/)})

Test File Organization

src/├── components/│   ├── Button/│   │   ├── Button.tsx│   │   ├── Button.test.tsx          # Unit tests│   │   └── Button.stories.tsx       # Storybook│   └── MarketCard/│       ├── MarketCard.tsx│       └── MarketCard.test.tsx├── app/│   └── api/│       └── markets/│           ├── route.ts│           └── route.test.ts         # Integration tests└── e2e/    ├── markets.spec.ts               # E2E tests    ├── trading.spec.ts    └── auth.spec.ts

Mocking External Services

Supabase Mock

typescript
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 Mock

typescript
jest.mock('@/lib/redis', () => ({  searchMarketsByVector: jest.fn(() => Promise.resolve([    { slug: 'test-market', similarity_score: 0.95 }  ])),  checkRedisHealth: jest.fn(() => Promise.resolve({ connected: true }))}))

OpenAI Mock

typescript
jest.mock('@/lib/openai', () => ({  generateEmbedding: jest.fn(() => Promise.resolve(    new Array(1536).fill(0.1) // Mock 1536-dim embedding  ))}))

Test Coverage Verification

Run Coverage Report

bash
npm run test:coverage

Coverage Thresholds

json
{  "jest": {    "coverageThresholds": {      "global": {        "branches": 80,        "functions": 80,        "lines": 80,        "statements": 80      }    }  }}

Common Testing Mistakes to Avoid

FAIL: WRONG: Testing Implementation Details

typescript
// Don't test internal stateexpect(component.state.count).toBe(5)

PASS: CORRECT: Test User-Visible Behavior

typescript
// Test what users seeexpect(screen.getByText('Count: 5')).toBeInTheDocument()

FAIL: WRONG: Brittle Selectors

typescript
// Breaks easilyawait page.click('.css-class-xyz')

PASS: CORRECT: Semantic Selectors

typescript
// Resilient to changesawait page.click('button:has-text("Submit")')await page.click('[data-testid="submit-button"]')

FAIL: WRONG: No Test Isolation

typescript
// Tests depend on each othertest('creates user', () => { /* ... */ })test('updates same user', () => { /* depends on previous test */ })

PASS: CORRECT: Independent Tests

typescript
// Each test sets up its own datatest('creates user', () => {  const user = createTestUser()  // Test logic})
test('updates user', () => {  const user = createTestUser()  // Update logic})

Continuous Testing

Watch Mode During Development

bash
npm test -- --watch# Tests run automatically on file changes

Pre-Commit Hook

bash
# Runs before every commitnpm test && npm run lint

CI/CD Integration

yaml
# GitHub Actions- name: Run Tests  run: npm test -- --coverage- name: Upload Coverage  uses: codecov/codecov-action@v3

Best Practices

  1. Write Tests First - Always TDD
  2. One Assert Per Test - Focus on single behavior
  3. Descriptive Test Names - Explain what's tested
  4. Arrange-Act-Assert - Clear test structure
  5. Mock External Dependencies - Isolate unit tests
  6. Test Edge Cases - Null, undefined, empty, large
  7. Test Error Paths - Not just happy paths
  8. Keep Tests Fast - Unit tests < 50ms each
  9. Clean Up After Tests - No side effects
  10. Review Coverage Reports - Identify gaps

Success Metrics

  • 80%+ code coverage achieved
  • All tests passing (green)
  • No skipped or disabled tests
  • Fast test execution (< 30s for unit tests)
  • E2E tests cover critical user flows
  • Tests catch bugs before production

Remember: Tests are not optional. They are the safety net that enables confident refactoring, rapid development, and production reliability.

Source and attribution

Source:affaan-m/ECCin.kiro/skills/tdd-workflowat commitef648e0

License: No license

Content belongs to its original authors. SourceWeft indexes it from a public repository.

Report or request removal