UNPKG

cqt-agent

Version:
451 lines (368 loc) 14.3 kB
# Test Runner & Validator This utility automatically executes generated tests and validates their functionality, providing detailed feedback and remediation steps for any failures. ## Purpose Execute all generated test suites (unit, integration, E2E) to ensure they work correctly before delivery, and provide actionable feedback for any issues encountered. ## Test Execution Pipeline ### Phase 1: Pre-Execution Validation #### 1. Environment Setup Validation ```bash #!/bin/bash # Validate test environment setup validate_environment() { local validation_report=() # Check Node.js and npm versions if command -v node &> /dev/null; then NODE_VERSION=$(node --version) echo "✓ Node.js version: $NODE_VERSION" else validation_report+=("❌ Node.js not installed. Install Node.js 18+ from https://nodejs.org") fi # Check test frameworks if npx playwright --version &> /dev/null; then PLAYWRIGHT_VERSION=$(npx playwright --version) echo "✓ Playwright version: $PLAYWRIGHT_VERSION" else validation_report+=("❌ Playwright not installed. Run: npm install -D @playwright/test") fi # Check Java for Karate tests if command -v java &> /dev/null; then JAVA_VERSION=$(java -version 2>&1 | head -n 1) echo "✓ Java version: $JAVA_VERSION" else validation_report+=("❌ Java not installed. Install Java 11+ for Karate tests") fi # Check database connectivity if nc -z localhost 5432 &> /dev/null; then echo "✓ Database connection available" else validation_report+=("⚠️ Database not accessible. Some integration tests may fail") fi return ${#validation_report[@]} } ``` #### 2. Syntax Validation ```bash validate_test_syntax() { local syntax_errors=() echo "Validating test file syntax..." # Validate TypeScript test files find tests -name "*.ts" -type f | while read -r file; do if ! npx tsc --noEmit "$file" 2>/dev/null; then syntax_errors+=("TypeScript syntax error in: $file") fi done # Validate Playwright tests if ! npx playwright test --dry-run --reporter=json 2>/dev/null; then syntax_errors+=("Playwright configuration or test syntax errors detected") fi # Validate Karate tests find tests -name "*.feature" -type f | while read -r file; do if ! java -jar karate.jar "$file" --dry-run 2>/dev/null; then syntax_errors+=("Karate feature syntax error in: $file") fi done if [ ${#syntax_errors[@]} -eq 0 ]; then echo "✓ All test files have valid syntax" return 0 else echo "❌ Syntax validation failed:" printf '%s\n' "${syntax_errors[@]}" return 1 fi } ``` #### 3. Dependency Resolution ```bash resolve_dependencies() { echo "Resolving test dependencies..." # Install npm dependencies if ! npm ci --silent; then echo "❌ Failed to install npm dependencies" echo "Action: Run 'npm install' and fix any dependency conflicts" return 1 fi # Install Playwright browsers if ! npx playwright install --with-deps; then echo "❌ Failed to install Playwright browsers" echo "Action: Run 'npx playwright install' manually" return 1 fi # Verify Karate JAR if [ ! -f "karate.jar" ]; then echo "⚠️ Karate JAR not found, downloading..." wget -O karate.jar https://github.com/karatelabs/karate/releases/download/v1.4.1/karate-1.4.1.jar fi echo "✓ All dependencies resolved successfully" return 0 } ``` ### Phase 2: Test Execution #### 1. Unit Test Execution ```bash execute_unit_tests() { echo "Executing unit tests..." local unit_results_file="test-results/unit-test-results.json" mkdir -p test-results # Run unit tests with coverage if npm run test:unit -- --coverage --reporter=json --outputFile="$unit_results_file"; then local coverage=$(jq -r '.coverageMap.totals.lines.pct' "$unit_results_file" 2>/dev/null || echo "0") local passed_tests=$(jq -r '.numPassedTests' "$unit_results_file" 2>/dev/null || echo "0") local failed_tests=$(jq -r '.numFailedTests' "$unit_results_file" 2>/dev/null || echo "0") echo "✓ Unit tests completed: $passed_tests passed, $failed_tests failed" echo "✓ Code coverage: $coverage%" if (( $(echo "$coverage < 85" | bc -l) )); then echo "⚠️ Code coverage below 85% threshold" fi return $failed_tests else echo "❌ Unit tests failed to execute" return 1 fi } ``` #### 2. Integration Test Execution ```bash execute_integration_tests() { echo "Executing integration tests..." local integration_results_file="test-results/integration-test-results.json" # Start test database if needed if docker ps | grep -q test-db; then echo "✓ Test database already running" else echo "Starting test database..." docker-compose -f docker-compose.test.yml up -d db sleep 10 # Wait for database to be ready fi # Run integration tests if java -jar karate.jar tests/integration --output "$integration_results_file"; then local total_scenarios=$(jq -r '.scenariosPassed + .scenariosFailed' "$integration_results_file" 2>/dev/null || echo "0") local passed_scenarios=$(jq -r '.scenariosPassed' "$integration_results_file" 2>/dev/null || echo "0") local failed_scenarios=$(jq -r '.scenariosFailed' "$integration_results_file" 2>/dev/null || echo "0") echo "✓ Integration tests completed: $passed_scenarios passed, $failed_scenarios failed" return $failed_scenarios else echo "❌ Integration tests failed to execute" return 1 fi } ``` #### 3. End-to-End Test Execution ```bash execute_e2e_tests() { echo "Executing end-to-end tests..." local e2e_results_file="test-results/e2e-test-results.json" # Start application in test mode if ! pgrep -f "npm run start:test" > /dev/null; then echo "Starting application in test mode..." npm run start:test & APP_PID=$! sleep 15 # Wait for application to start fi # Run E2E tests if npx playwright test --reporter=json --output-file="$e2e_results_file"; then local total_tests=$(jq -r '.suites[].tests | length' "$e2e_results_file" | awk '{sum+=$1} END {print sum}' || echo "0") local passed_tests=$(jq -r '.suites[].tests[] | select(.outcome=="passed") | length' "$e2e_results_file" | wc -l || echo "0") local failed_tests=$(jq -r '.suites[].tests[] | select(.outcome=="failed") | length' "$e2e_results_file" | wc -l || echo "0") echo "✓ E2E tests completed: $passed_tests passed, $failed_tests failed" # Cleanup if [ -n "$APP_PID" ]; then kill $APP_PID 2>/dev/null fi return $failed_tests else echo "❌ E2E tests failed to execute" if [ -n "$APP_PID" ]; then kill $APP_PID 2>/dev/null fi return 1 fi } ``` ### Phase 3: Results Analysis & Reporting #### 1. Performance Validation ```bash validate_performance() { echo "Validating performance metrics..." local performance_issues=() # Check E2E test execution times local avg_test_duration=$(jq -r '.suites[].tests[].duration' test-results/e2e-test-results.json | awk '{sum+=$1; count++} END {if(count>0) print sum/count; else print 0}') if (( $(echo "$avg_test_duration > 30000" | bc -l) )); then performance_issues+=("⚠️ Average E2E test duration (${avg_test_duration}ms) exceeds 30s threshold") fi # Check API response times local avg_api_response=$(jq -r '.scenarioResults[].stepResults[] | select(.step.text | contains("When method")) | .executionTime' test-results/integration-test-results.json | awk '{sum+=$1; count++} END {if(count>0) print sum/count; else print 0}') if (( $(echo "$avg_api_response > 2000" | bc -l) )); then performance_issues+=("⚠️ Average API response time (${avg_api_response}ms) exceeds 2s threshold") fi if [ ${#performance_issues[@]} -eq 0 ]; then echo "✓ All performance metrics within acceptable limits" else echo "Performance warnings:" printf '%s\n' "${performance_issues[@]}" fi } ``` #### 2. Test Quality Analysis ```bash analyze_test_quality() { echo "Analyzing test quality..." local quality_issues=() # Check for missing assertions local tests_without_assertions=$(grep -r "test\|scenario" tests/ | wc -l) local total_assertions=$(grep -r "expect\|assert\|match" tests/ | wc -l) local assertion_ratio=$(echo "scale=2; $total_assertions / $tests_without_assertions" | bc) if (( $(echo "$assertion_ratio < 3" | bc -l) )); then quality_issues+=("⚠️ Low assertion-to-test ratio ($assertion_ratio). Tests may lack sufficient validation") fi # Check for hardcoded values local hardcoded_values=$(grep -r "localhost\|127.0.0.1\|password123" tests/ | wc -l) if [ $hardcoded_values -gt 0 ]; then quality_issues+=("⚠️ Found $hardcoded_values hardcoded values in tests. Use configuration or test data files") fi # Check for test isolation local shared_state_tests=$(grep -r "beforeAll\|afterAll" tests/ | wc -l) local total_test_files=$(find tests/ -name "*.ts" -o -name "*.feature" | wc -l) if (( shared_state_tests > total_test_files * 2 )); then quality_issues+=("⚠️ Many tests share state. Consider improving test isolation") fi if [ ${#quality_issues[@]} -eq 0 ]; then echo "✓ Test quality analysis passed" else echo "Test quality warnings:" printf '%s\n' "${quality_issues[@]}" fi } ``` ### Phase 4: Comprehensive Reporting #### 1. Generate Consolidated Report ```bash generate_test_report() { local report_file="test-results/consolidated-report.json" local html_report="test-results/test-report.html" # Consolidate all test results jq -n \ --slurpfile unit test-results/unit-test-results.json \ --slurpfile integration test-results/integration-test-results.json \ --slurpfile e2e test-results/e2e-test-results.json \ '{ timestamp: now | strftime("%Y-%m-%d %H:%M:%S"), summary: { unit: { passed: ($unit[0].numPassedTests // 0), failed: ($unit[0].numFailedTests // 0), coverage: ($unit[0].coverageMap.totals.lines.pct // 0) }, integration: { passed: ($integration[0].scenariosPassed // 0), failed: ($integration[0].scenariosFailed // 0) }, e2e: { passed: ($e2e[0].suites[].tests[] | select(.outcome=="passed") | length), failed: ($e2e[0].suites[].tests[] | select(.outcome=="failed") | length) } }, details: { unit: $unit[0], integration: $integration[0], e2e: $e2e[0] } }' > "$report_file" # Generate HTML report generate_html_report "$report_file" "$html_report" echo "✓ Consolidated test report generated: $html_report" } generate_html_report() { local json_report=$1 local html_report=$2 cat > "$html_report" << 'EOF' <!DOCTYPE html> <html> <head> <title>Test Execution Report</title> <style> body { font-family: Arial, sans-serif; margin: 20px; } .summary { background: #f5f5f5; padding: 15px; border-radius: 5px; margin-bottom: 20px; } .pass { color: #28a745; } .fail { color: #dc3545; } .warn { color: #ffc107; } table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid #ddd; padding: 8px; text-align: left; } th { background-color: #f2f2f2; } </style> </head> <body> <h1>Test Execution Report</h1> <div id="report-content"></div> <script> // Load and display JSON report data fetch('consolidated-report.json') .then(response => response.json()) .then(data => displayReport(data)); function displayReport(data) { // Implementation for displaying test results document.getElementById('report-content').innerHTML = generateReportHTML(data); } </script> </body> </html> EOF } ``` ## Main Execution Function ```bash main_test_execution() { echo "🧪 Starting comprehensive test execution pipeline..." echo "================================================" local total_failures=0 local execution_log="test-results/execution.log" mkdir -p test-results # Phase 1: Pre-execution validation echo "Phase 1: Environment Validation" if ! validate_environment; then echo "❌ Environment validation failed. Please fix the issues above and retry." return 1 fi if ! validate_test_syntax; then echo "❌ Syntax validation failed. Please fix syntax errors and retry." return 1 fi if ! resolve_dependencies; then echo "❌ Dependency resolution failed. Please fix dependency issues and retry." return 1 fi # Phase 2: Test execution echo -e "\nPhase 2: Test Execution" execute_unit_tests total_failures=$((total_failures + $?)) execute_integration_tests total_failures=$((total_failures + $?)) execute_e2e_tests total_failures=$((total_failures + $?)) # Phase 3: Analysis echo -e "\nPhase 3: Results Analysis" validate_performance analyze_test_quality # Phase 4: Reporting echo -e "\nPhase 4: Report Generation" generate_test_report # Final summary echo -e "\n🎯 Test Execution Summary" echo "========================" if [ $total_failures -eq 0 ]; then echo "✅ All tests passed successfully!" echo "📊 Detailed report available at: test-results/test-report.html" else echo "❌ $total_failures test suite(s) had failures" echo "📊 Detailed report available at: test-results/test-report.html" echo "🔍 Run the test-failure-analyzer for detailed remediation steps" fi return $total_failures } ``` ## Usage Integration This utility integrates with the auto-e2e-generator task: 1. **Automatic Execution**: After generating tests, immediately validates them 2. **Failure Detection**: Identifies syntax errors, environment issues, logic problems 3. **Actionable Feedback**: Provides specific steps to resolve each type of issue 4. **Quality Assurance**: Ensures generated tests meet quality standards before delivery The test runner provides comprehensive validation and clear remediation guidance for any issues encountered during test execution.