From 6f109064e679ef095dac5e3df4f9d80ab7863706 Mon Sep 17 00:00:00 2001 From: vforvaick Date: Mon, 1 Sep 2025 21:16:27 +0700 Subject: [PATCH] feat: Add TDD demo story and implementation structure Add example story for User Email Validation TDD workflow: - Complete story with acceptance criteria in Gherkin format - Technical requirements and test plan with test IDs - TDD phase progress tracking (currently red) - Implementation tasks for Dev agent - Directory structure for JS and Python demo implementations This demo story provides teams with a practical example to reproduce the red-green-refactor TDD cycle using BMAD framework and methodology. --- bmad-core/scripts/tdd-guard.sh | 393 +++++++++++++++++++++++ bmad-core/templates/tdd-ci-template.yml | 351 ++++++++++++++++++++ examples/tdd-demo/1.1-user-validation.md | 201 ++++++++++++ 3 files changed, 945 insertions(+) create mode 100755 bmad-core/scripts/tdd-guard.sh create mode 100644 bmad-core/templates/tdd-ci-template.yml create mode 100644 examples/tdd-demo/1.1-user-validation.md diff --git a/bmad-core/scripts/tdd-guard.sh b/bmad-core/scripts/tdd-guard.sh new file mode 100755 index 00000000..81963660 --- /dev/null +++ b/bmad-core/scripts/tdd-guard.sh @@ -0,0 +1,393 @@ +#!/bin/bash +# TDD Guard - Validates that code changes follow TDD discipline +# Part of BMAD Framework TDD integration + +set -e + +# Configuration +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +CONFIG_FILE="${PROJECT_ROOT}/bmad-core/core-config.yaml" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Default values +TDD_ENABLED="false" +ALLOW_RED_PHASE_FAILURES="true" +EXIT_CODE=0 + +# Usage information +usage() { + cat << EOF +TDD Guard - Validates TDD discipline in code changes + +Usage: $0 [options] + +Options: + -h, --help Show this help message + -c, --config PATH Path to BMAD core config file + -b, --base REF Base commit/branch for comparison (default: HEAD~1) + -v, --verbose Verbose output + --phase PHASE Current TDD phase: red|green|refactor + --ci Running in CI mode (affects exit behavior) + --dry-run Show what would be checked without failing + +Examples: + $0 # Check changes against HEAD~1 + $0 --base main # Check changes against main branch + $0 --phase green # Validate green phase rules + $0 --ci --phase red # CI mode, red phase (allows failures) + +Exit Codes: + 0 No TDD violations found + 1 TDD violations found (in green phase) + 2 Configuration error + 3 Git/repository error +EOF +} + +# Logging functions +log_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +log_warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +log_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +# Parse command line arguments +BASE_REF="HEAD~1" +VERBOSE=false +TDD_PHASE="" +CI_MODE=false +DRY_RUN=false + +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + usage + exit 0 + ;; + -c|--config) + CONFIG_FILE="$2" + shift 2 + ;; + -b|--base) + BASE_REF="$2" + shift 2 + ;; + -v|--verbose) + VERBOSE=true + shift + ;; + --phase) + TDD_PHASE="$2" + shift 2 + ;; + --ci) + CI_MODE=true + shift + ;; + --dry-run) + DRY_RUN=true + shift + ;; + *) + log_error "Unknown option: $1" + usage + exit 2 + ;; + esac +done + +# Check if we're in a git repository +if ! git rev-parse --git-dir > /dev/null 2>&1; then + log_error "Not in a git repository" + exit 3 +fi + +# Load configuration +load_config() { + if [[ ! -f "$CONFIG_FILE" ]]; then + if [[ "$VERBOSE" == true ]]; then + log_warn "Config file not found: $CONFIG_FILE" + log_info "Assuming TDD disabled" + fi + return 0 + fi + + # Extract TDD settings from YAML (basic parsing) + if command -v yq > /dev/null 2>&1; then + TDD_ENABLED=$(yq e '.tdd.enabled // false' "$CONFIG_FILE" 2>/dev/null || echo "false") + ALLOW_RED_PHASE_FAILURES=$(yq e '.tdd.allow_red_phase_ci_failures // true' "$CONFIG_FILE" 2>/dev/null || echo "true") + else + # Fallback: basic grep parsing + if grep -q "tdd:" "$CONFIG_FILE" && grep -A 10 "tdd:" "$CONFIG_FILE" | grep -q "enabled: true"; then + TDD_ENABLED="true" + fi + fi + + if [[ "$VERBOSE" == true ]]; then + log_info "TDD enabled: $TDD_ENABLED" + log_info "Allow red phase failures: $ALLOW_RED_PHASE_FAILURES" + fi +} + +# Detect TDD phase from commit messages or branch name +detect_tdd_phase() { + if [[ -n "$TDD_PHASE" ]]; then + return 0 + fi + + # Check recent commit messages for TDD phase indicators + RECENT_COMMITS=$(git log --oneline -5 "$BASE_REF".."HEAD" 2>/dev/null || echo "") + + if echo "$RECENT_COMMITS" | grep -qi "\[RED\]"; then + TDD_PHASE="red" + elif echo "$RECENT_COMMITS" | grep -qi "\[GREEN\]"; then + TDD_PHASE="green" + elif echo "$RECENT_COMMITS" | grep -qi "\[REFACTOR\]"; then + TDD_PHASE="refactor" + else + # Try to detect from branch name + BRANCH_NAME=$(git branch --show-current 2>/dev/null || echo "") + if echo "$BRANCH_NAME" | grep -qi "tdd"; then + TDD_PHASE="green" # Default assumption + fi + fi + + if [[ "$VERBOSE" == true ]]; then + log_info "Detected TDD phase: ${TDD_PHASE:-unknown}" + fi +} + +# Get changed files between base and current +get_changed_files() { + # Get list of changed files + CHANGED_FILES=$(git diff --name-only "$BASE_REF"..."HEAD" 2>/dev/null || echo "") + + if [[ -z "$CHANGED_FILES" ]]; then + if [[ "$VERBOSE" == true ]]; then + log_info "No changed files detected" + fi + return 0 + fi + + # Separate source and test files + SOURCE_FILES="" + TEST_FILES="" + + while IFS= read -r file; do + if [[ -f "$file" ]]; then + if is_test_file "$file"; then + TEST_FILES="$TEST_FILES$file"$'\n' + elif is_source_file "$file"; then + SOURCE_FILES="$SOURCE_FILES$file"$'\n' + fi + fi + done <<< "$CHANGED_FILES" + + if [[ "$VERBOSE" == true ]]; then + log_info "Source files changed: $(echo "$SOURCE_FILES" | wc -l | tr -d ' ')" + log_info "Test files changed: $(echo "$TEST_FILES" | wc -l | tr -d ' ')" + fi +} + +# Check if file is a test file +is_test_file() { + local file="$1" + # Common test file patterns + if [[ "$file" =~ \.(test|spec)\.(js|ts|py|go|java|cs)$ ]] || \ + [[ "$file" =~ _test\.(py|go)$ ]] || \ + [[ "$file" =~ Test\.(java|cs)$ ]] || \ + [[ "$file" =~ tests?/ ]] || \ + [[ "$file" =~ spec/ ]]; then + return 0 + fi + return 1 +} + +# Check if file is a source file +is_source_file() { + local file="$1" + # Common source file patterns (excluding test files) + if [[ "$file" =~ \.(js|ts|py|go|java|cs|rb|php|cpp|c|h)$ ]] && ! is_test_file "$file"; then + return 0 + fi + return 1 +} + +# Check if commit message indicates refactoring +is_refactor_commit() { + local commits=$(git log --oneline "$BASE_REF".."HEAD" 2>/dev/null || echo "") + if echo "$commits" | grep -qi "\[refactor\]"; then + return 0 + fi + return 1 +} + +# Validate TDD rules +validate_tdd_rules() { + local violations=0 + + if [[ -z "$SOURCE_FILES" && -z "$TEST_FILES" ]]; then + if [[ "$VERBOSE" == true ]]; then + log_info "No relevant source or test files changed" + fi + return 0 + fi + + case "$TDD_PHASE" in + "red") + # Red phase: Tests should be added/modified, minimal or no source changes + if [[ -n "$SOURCE_FILES" ]] && [[ -z "$TEST_FILES" ]]; then + log_warn "RED phase violation: Source code changed without corresponding test changes" + log_warn "In TDD Red phase, tests should be written first" + if [[ "$ALLOW_RED_PHASE_FAILURES" == "false" ]] || [[ "$CI_MODE" == "false" ]]; then + violations=$((violations + 1)) + fi + fi + ;; + + "green") + # Green phase: Source changes must have corresponding test changes + if [[ -n "$SOURCE_FILES" ]] && [[ -z "$TEST_FILES" ]]; then + log_error "GREEN phase violation: Source code changed without corresponding tests" + log_error "In TDD Green phase, implementation should only make existing tests pass" + log_error "Source files modified:" + echo "$SOURCE_FILES" | while IFS= read -r file; do + [[ -n "$file" ]] && log_error " - $file" + done + violations=$((violations + 1)) + fi + + # Check for large changes (potential feature creep) + if [[ -n "$SOURCE_FILES" ]]; then + local large_changes=0 + while IFS= read -r file; do + if [[ -n "$file" ]] && [[ -f "$file" ]]; then + local additions=$(git diff --numstat "$BASE_REF" "$file" | cut -f1) + if [[ "$additions" =~ ^[0-9]+$ ]] && [[ "$additions" -gt 50 ]]; then + log_warn "Large change detected in $file: $additions lines added" + log_warn "Consider smaller, more focused changes in TDD Green phase" + large_changes=$((large_changes + 1)) + fi + fi + done <<< "$SOURCE_FILES" + + if [[ "$large_changes" -gt 0 ]]; then + log_warn "Consider breaking large changes into smaller TDD cycles" + fi + fi + ;; + + "refactor") + # Refactor phase: Source changes allowed, tests should remain stable + if is_refactor_commit; then + if [[ "$VERBOSE" == true ]]; then + log_info "Refactor phase: Changes detected with proper [REFACTOR] tag" + fi + else + if [[ -n "$SOURCE_FILES" ]] && [[ -z "$TEST_FILES" ]]; then + log_warn "Potential refactor phase: Consider tagging commits with [REFACTOR]" + fi + fi + ;; + + *) + # Unknown or no TDD phase + if [[ "$TDD_ENABLED" == "true" ]]; then + log_warn "TDD enabled but phase not detected" + log_warn "Consider tagging commits with [RED], [GREEN], or [REFACTOR]" + if [[ -n "$SOURCE_FILES" ]] && [[ -z "$TEST_FILES" ]]; then + log_warn "Source changes without test changes - may violate TDD discipline" + fi + fi + ;; + esac + + return $violations +} + +# Main execution +main() { + if [[ "$VERBOSE" == true ]]; then + log_info "TDD Guard starting..." + log_info "Base reference: $BASE_REF" + log_info "Config file: $CONFIG_FILE" + fi + + load_config + + if [[ "$TDD_ENABLED" != "true" ]]; then + if [[ "$VERBOSE" == true ]]; then + log_info "TDD not enabled, skipping validation" + fi + exit 0 + fi + + detect_tdd_phase + get_changed_files + + if [[ "$DRY_RUN" == true ]]; then + log_info "DRY RUN - Would check:" + log_info " TDD Phase: ${TDD_PHASE:-unknown}" + log_info " Source files: $(echo "$SOURCE_FILES" | grep -c . || echo 0)" + log_info " Test files: $(echo "$TEST_FILES" | grep -c . || echo 0)" + exit 0 + fi + + validate_tdd_rules + local violations=$? + + if [[ "$violations" -eq 0 ]]; then + log_success "TDD validation passed" + exit 0 + else + log_error "$violations TDD violation(s) found" + + # Provide helpful suggestions + echo "" + echo "๐Ÿ’ก TDD Suggestions:" + case "$TDD_PHASE" in + "green") + echo " - Ensure all source changes have corresponding failing tests first" + echo " - Consider running QA agent's *write-failing-tests command" + echo " - Keep implementation minimal - only make tests pass" + ;; + "red") + echo " - Write failing tests before implementation" + echo " - Use QA agent to create test cases first" + ;; + *) + echo " - Follow TDD Red-Green-Refactor cycle" + echo " - Tag commits with [RED], [GREEN], or [REFACTOR]" + echo " - Enable TDD workflow in BMAD configuration" + ;; + esac + echo "" + + if [[ "$TDD_PHASE" == "red" ]] && [[ "$ALLOW_RED_PHASE_FAILURES" == "true" ]] && [[ "$CI_MODE" == "true" ]]; then + log_warn "Red phase violations allowed in CI mode" + exit 0 + fi + + exit 1 + fi +} + +# Run main function +main "$@" diff --git a/bmad-core/templates/tdd-ci-template.yml b/bmad-core/templates/tdd-ci-template.yml new file mode 100644 index 00000000..75e21344 --- /dev/null +++ b/bmad-core/templates/tdd-ci-template.yml @@ -0,0 +1,351 @@ +# TDD-Enhanced CI/CD Workflow Template for BMAD Framework +# This template shows how to integrate TDD validation into CI/CD pipelines + +name: TDD-Enhanced CI/CD + +on: + push: + branches: [ main, develop, 'feature/tdd-*' ] + pull_request: + branches: [ main, develop ] + +env: + # TDD Configuration + TDD_ENABLED: true + TDD_ALLOW_RED_PHASE_FAILURES: true + TDD_COVERAGE_THRESHOLD: 80 + +jobs: + # Detect TDD phase and validate changes + tdd-validation: + name: TDD Phase Validation + runs-on: ubuntu-latest + outputs: + tdd-phase: ${{ steps.detect-phase.outputs.phase }} + tdd-enabled: ${{ steps.detect-phase.outputs.enabled }} + should-run-tests: ${{ steps.detect-phase.outputs.should-run-tests }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Need full history for TDD guard + + - name: Detect TDD phase + id: detect-phase + run: | + # Check if TDD is enabled in bmad-core/core-config.yaml + if grep -q "enabled: true" bmad-core/core-config.yaml 2>/dev/null; then + echo "enabled=true" >> $GITHUB_OUTPUT + echo "should-run-tests=true" >> $GITHUB_OUTPUT + else + echo "enabled=false" >> $GITHUB_OUTPUT + echo "should-run-tests=true" >> $GITHUB_OUTPUT # Run tests anyway + exit 0 + fi + + # Detect TDD phase from commit messages + COMMITS=$(git log --oneline -10 ${{ github.event.before }}..${{ github.sha }} || git log --oneline -10) + + if echo "$COMMITS" | grep -qi "\[RED\]"; then + echo "phase=red" >> $GITHUB_OUTPUT + elif echo "$COMMITS" | grep -qi "\[GREEN\]"; then + echo "phase=green" >> $GITHUB_OUTPUT + elif echo "$COMMITS" | grep -qi "\[REFACTOR\]"; then + echo "phase=refactor" >> $GITHUB_OUTPUT + else + # Default phase detection based on branch + if [[ "${{ github.ref }}" =~ tdd ]]; then + echo "phase=green" >> $GITHUB_OUTPUT + else + echo "phase=unknown" >> $GITHUB_OUTPUT + fi + fi + + - name: Run TDD Guard + if: steps.detect-phase.outputs.enabled == 'true' + run: | + echo "๐Ÿงช Running TDD Guard validation..." + + # Make TDD guard executable + chmod +x bmad-core/scripts/tdd-guard.sh + + # Run TDD guard with appropriate settings + if [[ "${{ steps.detect-phase.outputs.phase }}" == "red" ]]; then + # Allow red phase failures in CI + ./bmad-core/scripts/tdd-guard.sh --ci --phase red --verbose || { + echo "โš ๏ธ Red phase violations detected but allowed in CI" + exit 0 + } + else + # Strict validation for green/refactor phases + ./bmad-core/scripts/tdd-guard.sh --phase "${{ steps.detect-phase.outputs.phase }}" --verbose + fi + + # Test execution with TDD awareness + test: + name: Run Tests + runs-on: ubuntu-latest + needs: tdd-validation + if: needs.tdd-validation.outputs.should-run-tests == 'true' + + strategy: + matrix: + # Add multiple language support as needed + language: [javascript, python] + include: + - language: javascript + test-command: npm test + coverage-command: npm run test:coverage + setup: | + node-version: 18 + cache: npm + - language: python + test-command: pytest + coverage-command: pytest --cov=. + setup: | + python-version: '3.9' + cache: pip + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + # Language-specific setup + - name: Setup Node.js + if: matrix.language == 'javascript' + uses: actions/setup-node@v4 + with: + node-version: 18 + cache: 'npm' + + - name: Setup Python + if: matrix.language == 'python' + uses: actions/setup-python@v4 + with: + python-version: '3.9' + cache: 'pip' + + # Install dependencies + - name: Install JavaScript dependencies + if: matrix.language == 'javascript' + run: | + if [ -f package.json ]; then + npm ci + fi + + - name: Install Python dependencies + if: matrix.language == 'python' + run: | + if [ -f requirements.txt ]; then + pip install -r requirements.txt + fi + if [ -f requirements-dev.txt ]; then + pip install -r requirements-dev.txt + fi + + # Run tests with TDD phase awareness + - name: Run tests + id: run-tests + run: | + echo "๐Ÿงช Running tests for TDD phase: ${{ needs.tdd-validation.outputs.tdd-phase }}" + + case "${{ needs.tdd-validation.outputs.tdd-phase }}" in + "red") + echo "RED phase: Expecting some tests to fail" + ${{ matrix.test-command }} || { + echo "โš ๏ธ Tests failed as expected in RED phase" + if [[ "$TDD_ALLOW_RED_PHASE_FAILURES" == "true" ]]; then + echo "test-result=red-expected-fail" >> $GITHUB_OUTPUT + exit 0 + else + echo "test-result=fail" >> $GITHUB_OUTPUT + exit 1 + fi + } + echo "test-result=pass" >> $GITHUB_OUTPUT + ;; + "green"|"refactor") + echo "GREEN/REFACTOR phase: All tests should pass" + ${{ matrix.test-command }} + echo "test-result=pass" >> $GITHUB_OUTPUT + ;; + *) + echo "Unknown phase: Running standard test suite" + ${{ matrix.test-command }} + echo "test-result=pass" >> $GITHUB_OUTPUT + ;; + esac + + # Generate coverage report + - name: Generate coverage report + if: env.TDD_COVERAGE_THRESHOLD > 0 + run: | + echo "๐Ÿ“Š Generating coverage report..." + ${{ matrix.coverage-command }} || echo "Coverage command failed" + + # Upload coverage reports + - name: Upload coverage to Codecov + if: matrix.language == 'javascript' || matrix.language == 'python' + uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV_TOKEN }} + file: ./coverage.xml + flags: ${{ matrix.language }} + name: ${{ matrix.language }}-coverage + fail_ci_if_error: false + + # Quality gates specific to TDD phase + quality-gates: + name: Quality Gates + runs-on: ubuntu-latest + needs: [tdd-validation, test] + if: always() + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: TDD Phase Quality Gate + run: | + echo "๐Ÿšฆ Evaluating quality gates for TDD phase: ${{ needs.tdd-validation.outputs.tdd-phase }}" + + case "${{ needs.tdd-validation.outputs.tdd-phase }}" in + "red") + echo "RED phase quality gate:" + echo "โœ… Tests written first" + echo "โœ… Implementation minimal or non-existent" + if [[ "${{ needs.test.result }}" == "success" ]] || [[ "${{ needs.test.outputs.test-result }}" == "red-expected-fail" ]]; then + echo "โœ… RED phase gate: PASS" + else + echo "โŒ RED phase gate: FAIL" + exit 1 + fi + ;; + "green") + echo "GREEN phase quality gate:" + echo "โœ… All tests passing" + echo "โœ… Minimal implementation" + echo "โœ… No feature creep" + if [[ "${{ needs.test.result }}" == "success" ]]; then + echo "โœ… GREEN phase gate: PASS" + else + echo "โŒ GREEN phase gate: FAIL" + exit 1 + fi + ;; + "refactor") + echo "REFACTOR phase quality gate:" + echo "โœ… Tests remain green" + echo "โœ… Code quality improved" + echo "โœ… Behavior preserved" + if [[ "${{ needs.test.result }}" == "success" ]]; then + echo "โœ… REFACTOR phase gate: PASS" + else + echo "โŒ REFACTOR phase gate: FAIL" + exit 1 + fi + ;; + *) + echo "Standard quality gate:" + if [[ "${{ needs.test.result }}" == "success" ]]; then + echo "โœ… Standard gate: PASS" + else + echo "โŒ Standard gate: FAIL" + exit 1 + fi + ;; + esac + + - name: Generate TDD Report + if: needs.tdd-validation.outputs.tdd-enabled == 'true' + run: | + echo "# TDD Pipeline Report" > tdd-report.md + echo "" >> tdd-report.md + echo "**TDD Phase:** ${{ needs.tdd-validation.outputs.tdd-phase }}" >> tdd-report.md + echo "**Test Result:** ${{ needs.test.outputs.test-result || 'unknown' }}" >> tdd-report.md + echo "**Quality Gate:** $([ "${{ job.status }}" == "success" ] && echo "PASS" || echo "FAIL")" >> tdd-report.md + echo "" >> tdd-report.md + echo "## Phase-Specific Results" >> tdd-report.md + + case "${{ needs.tdd-validation.outputs.tdd-phase }}" in + "red") + echo "- โœ… Failing tests written first" >> tdd-report.md + echo "- โœ… Implementation postponed until GREEN phase" >> tdd-report.md + ;; + "green") + echo "- โœ… Tests now passing" >> tdd-report.md + echo "- โœ… Minimal implementation completed" >> tdd-report.md + ;; + "refactor") + echo "- โœ… Code quality improved" >> tdd-report.md + echo "- โœ… All tests remain green" >> tdd-report.md + ;; + esac + + - name: Comment TDD Report on PR + if: github.event_name == 'pull_request' && needs.tdd-validation.outputs.tdd-enabled == 'true' + uses: actions/github-script@v6 + with: + script: | + const fs = require('fs'); + + if (fs.existsSync('tdd-report.md')) { + const report = fs.readFileSync('tdd-report.md', 'utf8'); + + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: `## ๐Ÿงช TDD Pipeline Results\n\n${report}` + }); + } + + # Deploy only after successful TDD validation + deploy: + name: Deploy + runs-on: ubuntu-latest + needs: [tdd-validation, test, quality-gates] + if: github.ref == 'refs/heads/main' && success() + + steps: + - name: Deploy Application + run: | + echo "๐Ÿš€ Deploying application after successful TDD validation" + echo "TDD Phase: ${{ needs.tdd-validation.outputs.tdd-phase }}" + + # Add your deployment steps here + # Only deploy if all TDD phases pass validation + + if [[ "${{ needs.tdd-validation.outputs.tdd-phase }}" == "green" ]] || [[ "${{ needs.tdd-validation.outputs.tdd-phase }}" == "refactor" ]]; then + echo "โœ… Safe to deploy: Implementation complete and tested" + else + echo "โš ๏ธ Deployment skipped: Not in a stable TDD phase" + exit 0 + fi + +# Additional workflow for TDD metrics collection + tdd-metrics: + name: TDD Metrics + runs-on: ubuntu-latest + needs: [tdd-validation, test, quality-gates] + if: always() && needs.tdd-validation.outputs.tdd-enabled == 'true' + + steps: + - name: Collect TDD Metrics + run: | + echo "๐Ÿ“Š Collecting TDD metrics..." + + # Calculate TDD cycle time (example) + CYCLE_START=$(git log --grep="\[RED\]" --format="%ct" -1 || echo $(date +%s)) + CYCLE_END=$(date +%s) + CYCLE_TIME=$(( (CYCLE_END - CYCLE_START) / 60 )) # minutes + + echo "TDD Cycle Metrics:" + echo "- Phase: ${{ needs.tdd-validation.outputs.tdd-phase }}" + echo "- Cycle Time: ${CYCLE_TIME} minutes" + echo "- Test Status: ${{ needs.test.outputs.test-result }}" + echo "- Quality Gate: $([ "${{ needs.quality-gates.result }}" == "success" ] && echo "PASS" || echo "FAIL")" + + # Store metrics (example - adapt to your metrics system) + echo "Metrics would be stored in your preferred system (Grafana, etc.)" diff --git a/examples/tdd-demo/1.1-user-validation.md b/examples/tdd-demo/1.1-user-validation.md new file mode 100644 index 00000000..9a2e79a2 --- /dev/null +++ b/examples/tdd-demo/1.1-user-validation.md @@ -0,0 +1,201 @@ +# Story 1.1: User Email Validation + +## Story Metadata + +```yaml +story: + epic: '1' + number: '1' + title: 'User Email Validation' + status: 'ready' + priority: 'high' + +# TDD Configuration +tdd: + status: 'red' # Current phase: red|green|refactor|done + cycle: 1 + coverage_target: 90.0 + tests: + - id: 'UV-001' + name: 'should validate correct email format' + type: unit + status: failing + file_path: 'tests/user-validator.test.js' + - id: 'UV-002' + name: 'should reject invalid email format' + type: unit + status: failing + file_path: 'tests/user-validator.test.js' + - id: 'UV-003' + name: 'should handle edge cases' + type: unit + status: failing + file_path: 'tests/user-validator.test.js' +``` + +## Story Description + +**As a** System Administrator +**I want** to validate user email addresses +**So that** only users with valid email formats can register + +### Context + +This is a foundational feature for user registration. We need robust email validation that follows RFC standards while being user-friendly. This will be used by the registration system and user profile updates. + +## Acceptance Criteria + +```gherkin +Feature: User Email Validation + +Scenario: Valid email formats are accepted + Given a user provides an email address + When the email has correct format with @ symbol and domain + Then the validation should return true + +Scenario: Invalid email formats are rejected + Given a user provides an invalid email address + When the email lacks @ symbol or proper domain format + Then the validation should return false with appropriate error message + +Scenario: Edge cases are handled properly + Given a user provides edge case email formats + When validation is performed on emails with special characters or unusual formats + Then the system should handle them according to RFC standards +``` + +## Technical Requirements + +### Functional Requirements + +- Validate email format using RFC-compliant rules +- Return boolean result with error details when invalid +- Handle common edge cases (special characters, multiple @, etc.) +- Performance: validation should complete in < 1ms + +### Non-Functional Requirements + +- **Performance:** < 1ms validation time per email +- **Security:** Prevent injection attacks via email input +- **Reliability:** 99.9% accuracy on email format validation +- **Maintainability:** Clear error messages for debugging + +## TDD Test Plan (QA Agent Responsibility) + +### Test Strategy + +- **Primary Test Type:** unit +- **Mocking Approach:** No external dependencies to mock +- **Test Data:** Fixed test cases covering valid/invalid formats + +### Planned Test Scenarios + +| ID | Scenario | Type | Priority | AC Reference | +| ------ | ---------------------------- | ---- | -------- | ------------ | +| UV-001 | Valid email formats accepted | unit | P0 | AC1 | +| UV-002 | Invalid formats rejected | unit | P0 | AC2 | +| UV-003 | Edge cases handled | unit | P1 | AC3 | +| UV-004 | Performance requirements met | unit | P2 | NFR | + +## TDD Progress + +### Current Phase: RED + +**Cycle:** 1 +**Last Updated:** 2025-01-12 + +### Red Phase - Cycle 1 + +**Date:** 2025-01-12 +**Agent:** Quinn (QA Agent) + +**Tests Written:** + +- UV-001: should validate correct email format (FAILING โœ…) +- UV-002: should reject invalid email format (FAILING โœ…) +- UV-003: should handle edge cases (FAILING โœ…) + +**Test Files:** + +- tests/user-validator.test.js + +**Next Step:** Dev Agent to implement minimal code to make tests pass + +--- + +## Implementation Tasks (Dev Agent) + +### Primary Tasks + +- [ ] Create UserValidator class +- [ ] Implement email validation logic +- [ ] Handle error cases and edge cases + +### Subtasks + +- [ ] Set up basic class structure +- [ ] Implement regex-based validation +- [ ] Add error message generation +- [ ] Performance optimization + +## Definition of Done + +### TDD-Specific DoD + +- [ ] Tests written first (Red phase completed) +- [ ] All tests passing (Green phase completed) +- [ ] Code refactored for quality (Refactor phase completed) +- [ ] Test coverage meets target (90%) +- [ ] All external dependencies properly mocked (N/A for this story) +- [ ] No features implemented without corresponding tests + +### General DoD + +- [ ] All acceptance criteria met +- [ ] Code follows project standards +- [ ] Documentation updated +- [ ] Ready for review + +## Dev Agent Record + +### Implementation Notes + +_(Dev agent will document implementation decisions here)_ + +### TDD Cycle Log + +_(Automatic tracking of Red-Green-Refactor progression)_ + +**Cycle 1:** + +- Red Phase: 2025-01-12 - 3 failing tests written +- Green Phase: _(pending)_ +- Refactor Phase: _(pending)_ + +### File List + +_(Dev agent will list all files created/modified)_ + +- tests/user-validator.test.js (created) +- _(implementation files will be added during GREEN phase)_ + +### Test Execution Log + +```bash +# RED phase test runs will be logged here +``` + +## QA Results + +_(QA agent will populate this during review)_ + +## Change Log + +- **2025-01-12**: Story created from TDD template +- **2025-01-12**: Red phase completed - failing tests written + +--- + +**TDD Status:** ๐Ÿ”ด RED Phase +**Agent Assigned:** Quinn (QA) โ†’ James (Dev) +**Estimated Effort:** 2 hours