RunVSAgent/scripts/test.sh
2025-08-01 20:21:08 +08:00

608 lines
No EOL
18 KiB
Bash
Executable file

#!/bin/bash
# Test script for RunVSAgent project
# This script runs various tests and validations
set -euo pipefail
# Source common utilities
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/common.sh"
# Script configuration
readonly SCRIPT_NAME="test.sh"
readonly SCRIPT_VERSION="1.0.0"
# Test types
readonly TEST_ALL="all"
readonly TEST_UNIT="unit"
readonly TEST_INTEGRATION="integration"
readonly TEST_LINT="lint"
readonly TEST_BUILD="build"
readonly TEST_ENV="env"
# Test configuration
TEST_TYPE="$TEST_ALL"
FAIL_FAST=false
COVERAGE=false
WATCH_MODE=false
# Show help for this script
show_help() {
cat << EOF
$SCRIPT_NAME - Run tests for RunVSAgent project
USAGE:
$SCRIPT_NAME [OPTIONS] [TEST_TYPE]
DESCRIPTION:
This script runs various types of tests and validations:
- Unit tests for individual components
- Integration tests for component interactions
- Linting and code quality checks
- Build validation tests
- Environment validation
TEST TYPES:
all Run all tests (default)
unit Run unit tests only
integration Run integration tests only
lint Run linting and code quality checks
build Run build validation tests
env Run environment validation tests
OPTIONS:
-f, --fail-fast Stop on first test failure
-c, --coverage Generate test coverage reports
-w, --watch Run tests in watch mode
-v, --verbose Enable verbose output
-n, --dry-run Show what tests would be run
-h, --help Show this help message
EXAMPLES:
$SCRIPT_NAME # Run all tests
$SCRIPT_NAME unit # Run unit tests only
$SCRIPT_NAME --coverage lint # Run linting with coverage
$SCRIPT_NAME --fail-fast # Stop on first failure
ENVIRONMENT:
CI Set to 'true' for CI environment
TEST_TIMEOUT Test timeout in seconds (default: 300)
COVERAGE_THRESHOLD Minimum coverage percentage (default: 80)
EXIT CODES:
0 All tests passed
1 General error
2 Test failures
3 Invalid arguments
4 Environment issues
EOF
}
# Parse command line arguments
parse_test_args() {
while [[ $# -gt 0 ]]; do
case $1 in
-f|--fail-fast)
FAIL_FAST=true
shift
;;
-c|--coverage)
COVERAGE=true
shift
;;
-w|--watch)
WATCH_MODE=true
shift
;;
-v|--verbose)
VERBOSE=true
shift
;;
-n|--dry-run)
DRY_RUN=true
shift
;;
-h|--help)
show_help
exit 0
;;
-*)
log_error "Unknown option: $1"
log_info "Use --help for usage information"
exit 3
;;
*)
# Positional argument (test type)
TEST_TYPE="$1"
shift
;;
esac
done
# Validate test type
case "$TEST_TYPE" in
"$TEST_ALL"|"$TEST_UNIT"|"$TEST_INTEGRATION"|"$TEST_LINT"|"$TEST_BUILD"|"$TEST_ENV")
;;
*)
log_error "Invalid test type: $TEST_TYPE"
log_info "Valid types: $TEST_ALL, $TEST_UNIT, $TEST_INTEGRATION, $TEST_LINT, $TEST_BUILD, $TEST_ENV"
exit 3
;;
esac
}
# Setup test environment
setup_test_environment() {
log_step "Setting up test environment..."
# Set CI environment variables
if [[ "${CI:-false}" == "true" ]]; then
log_info "Running in CI environment"
export NODE_ENV="test"
export CI="true"
fi
# Set test timeout
export TEST_TIMEOUT="${TEST_TIMEOUT:-300}"
# Set coverage threshold
export COVERAGE_THRESHOLD="${COVERAGE_THRESHOLD:-80}"
# Create test output directories
ensure_dir "$PROJECT_ROOT/test-results"
ensure_dir "$PROJECT_ROOT/coverage"
log_success "Test environment set up"
}
# Run environment validation tests
run_env_tests() {
if [[ "$TEST_TYPE" != "$TEST_ENV" && "$TEST_TYPE" != "$TEST_ALL" ]]; then
return 0
fi
log_step "Running environment validation tests..."
local test_failures=0
# Test 1: Validate system requirements
log_info "Testing system requirements..."
if validate_environment 2>/dev/null; then
log_success "✓ System requirements test passed"
else
log_error "✗ System requirements test failed"
((test_failures++))
[[ "$FAIL_FAST" == "true" ]] && return $test_failures
fi
# Test 2: Check project structure
log_info "Testing project structure..."
local required_dirs=("$EXTENSION_HOST_DIR" "$IDEA_DIR" "scripts")
local structure_ok=true
for dir in "${required_dirs[@]}"; do
if [[ ! -d "$PROJECT_ROOT/$dir" ]]; then
log_error "Required directory missing: $dir"
structure_ok=false
fi
done
if [[ "$structure_ok" == "true" ]]; then
log_success "✓ Project structure test passed"
else
log_error "✗ Project structure test failed"
((test_failures++))
[[ "$FAIL_FAST" == "true" ]] && return $test_failures
fi
# Test 3: Check Git configuration
log_info "Testing Git configuration..."
if git rev-parse --git-dir >/dev/null 2>&1; then
log_success "✓ Git configuration test passed"
else
log_error "✗ Git configuration test failed"
((test_failures++))
[[ "$FAIL_FAST" == "true" ]] && return $test_failures
fi
log_info "Environment tests completed with $test_failures failures"
return $test_failures
}
# Run linting tests
run_lint_tests() {
if [[ "$TEST_TYPE" != "$TEST_LINT" && "$TEST_TYPE" != "$TEST_ALL" ]]; then
return 0
fi
log_step "Running linting tests..."
local test_failures=0
# Test shell scripts with shellcheck if available
if command_exists "shellcheck"; then
log_info "Running shellcheck on shell scripts..."
local shell_files
shell_files=$(find "$PROJECT_ROOT/scripts" -name "*.sh" -type f)
if [[ -n "$shell_files" ]]; then
if [[ "$DRY_RUN" == "true" ]]; then
log_debug "Would run: shellcheck on shell scripts"
else
if echo "$shell_files" | xargs shellcheck; then
log_success "✓ Shell script linting passed"
else
log_error "✗ Shell script linting failed"
((test_failures++))
[[ "$FAIL_FAST" == "true" ]] && return $test_failures
fi
fi
fi
else
log_warn "shellcheck not found, skipping shell script linting"
fi
# Test base extension linting
local base_dir="$PROJECT_ROOT/$EXTENSION_HOST_DIR"
if [[ -f "$base_dir/package.json" ]]; then
log_info "Running base extension linting..."
cd "$base_dir"
if npm run lint --if-present >/dev/null 2>&1; then
if [[ "$DRY_RUN" == "true" ]]; then
log_debug "Would run: npm run lint in base directory"
else
if npm run lint; then
log_success "✓ Base extension linting passed"
else
log_error "✗ Base extension linting failed"
((test_failures++))
[[ "$FAIL_FAST" == "true" ]] && return $test_failures
fi
fi
else
log_debug "No lint script found in base extension"
fi
fi
# Test VSCode extension linting
local vscode_dir="$PROJECT_ROOT/$VSCODE_SUBMODULE_PATH"
if [[ -d "$vscode_dir" && -f "$vscode_dir/package.json" ]]; then
log_info "Running VSCode extension linting..."
cd "$vscode_dir"
local pkg_manager="npm"
if command_exists "pnpm" && [[ -f "pnpm-lock.yaml" ]]; then
pkg_manager="pnpm"
fi
if $pkg_manager run lint --if-present >/dev/null 2>&1; then
if [[ "$DRY_RUN" == "true" ]]; then
log_debug "Would run: $pkg_manager run lint in VSCode directory"
else
if $pkg_manager run lint; then
log_success "✓ VSCode extension linting passed"
else
log_error "✗ VSCode extension linting failed"
((test_failures++))
[[ "$FAIL_FAST" == "true" ]] && return $test_failures
fi
fi
else
log_debug "No lint script found in VSCode extension"
fi
fi
log_info "Linting tests completed with $test_failures failures"
return $test_failures
}
# Run unit tests
run_unit_tests() {
if [[ "$TEST_TYPE" != "$TEST_UNIT" && "$TEST_TYPE" != "$TEST_ALL" ]]; then
return 0
fi
log_step "Running unit tests..."
local test_failures=0
# Run base extension unit tests
local base_dir="$PROJECT_ROOT/$EXTENSION_HOST_DIR"
if [[ -f "$base_dir/package.json" ]]; then
log_info "Running base extension unit tests..."
cd "$base_dir"
local test_cmd="npm test"
if [[ "$COVERAGE" == "true" ]]; then
test_cmd="npm run test:coverage"
fi
if npm run test --if-present >/dev/null 2>&1; then
if [[ "$DRY_RUN" == "true" ]]; then
log_debug "Would run: $test_cmd in base directory"
else
if eval "$test_cmd"; then
log_success "✓ Base extension unit tests passed"
else
log_error "✗ Base extension unit tests failed"
((test_failures++))
[[ "$FAIL_FAST" == "true" ]] && return $test_failures
fi
fi
else
log_debug "No test script found in base extension"
fi
fi
# Run VSCode extension unit tests
local vscode_dir="$PROJECT_ROOT/$VSCODE_SUBMODULE_PATH"
if [[ -d "$vscode_dir" && -f "$vscode_dir/package.json" ]]; then
log_info "Running VSCode extension unit tests..."
cd "$vscode_dir"
local pkg_manager="npm"
if command_exists "pnpm" && [[ -f "pnpm-lock.yaml" ]]; then
pkg_manager="pnpm"
fi
local test_cmd="$pkg_manager test"
if [[ "$COVERAGE" == "true" ]]; then
test_cmd="$pkg_manager run test:coverage"
fi
if $pkg_manager run test --if-present >/dev/null 2>&1; then
if [[ "$DRY_RUN" == "true" ]]; then
log_debug "Would run: $test_cmd in VSCode directory"
else
if eval "$test_cmd"; then
log_success "✓ VSCode extension unit tests passed"
else
log_error "✗ VSCode extension unit tests failed"
((test_failures++))
[[ "$FAIL_FAST" == "true" ]] && return $test_failures
fi
fi
else
log_debug "No test script found in VSCode extension"
fi
fi
log_info "Unit tests completed with $test_failures failures"
return $test_failures
}
# Run integration tests
run_integration_tests() {
if [[ "$TEST_TYPE" != "$TEST_INTEGRATION" && "$TEST_TYPE" != "$TEST_ALL" ]]; then
return 0
fi
log_step "Running integration tests..."
local test_failures=0
# Test 1: Build integration test
log_info "Testing build integration..."
if [[ "$DRY_RUN" == "true" ]]; then
log_debug "Would run: build integration test"
else
# Try a minimal build to test integration
local temp_dir
temp_dir=$(mktemp -d)
if "$SCRIPT_DIR/build.sh" --dry-run >/dev/null 2>&1; then
log_success "✓ Build integration test passed"
else
log_error "✗ Build integration test failed"
((test_failures++))
[[ "$FAIL_FAST" == "true" ]] && return $test_failures
fi
rm -rf "$temp_dir"
fi
# Test 2: Script integration test
log_info "Testing script integration..."
local scripts=("setup.sh" "build.sh" "clean.sh")
for script in "${scripts[@]}"; do
if [[ -f "$SCRIPT_DIR/$script" ]]; then
if [[ "$DRY_RUN" == "true" ]]; then
log_debug "Would test: $script --help"
else
if "$SCRIPT_DIR/$script" --help >/dev/null 2>&1; then
log_debug "$script help test passed"
else
log_error "$script help test failed"
((test_failures++))
[[ "$FAIL_FAST" == "true" ]] && return $test_failures
fi
fi
fi
done
if [[ $test_failures -eq 0 ]]; then
log_success "✓ Script integration tests passed"
fi
log_info "Integration tests completed with $test_failures failures"
return $test_failures
}
# Run build validation tests
run_build_tests() {
if [[ "$TEST_TYPE" != "$TEST_BUILD" && "$TEST_TYPE" != "$TEST_ALL" ]]; then
return 0
fi
log_step "Running build validation tests..."
local test_failures=0
# Test 1: Validate build script syntax
log_info "Testing build script syntax..."
if [[ "$DRY_RUN" == "true" ]]; then
log_debug "Would validate: build script syntax"
else
if bash -n "$SCRIPT_DIR/build.sh"; then
log_success "✓ Build script syntax test passed"
else
log_error "✗ Build script syntax test failed"
((test_failures++))
[[ "$FAIL_FAST" == "true" ]] && return $test_failures
fi
fi
# Test 2: Validate required build files
log_info "Testing required build files..."
local required_files=(
"$PROJECT_ROOT/$EXTENSION_HOST_DIR/package.json"
"$PROJECT_ROOT/$IDEA_DIR/build.gradle"
)
local files_ok=true
for file in "${required_files[@]}"; do
if [[ ! -f "$file" && ! -f "${file%.gradle}.kts" ]]; then
log_error "Required build file missing: $file"
files_ok=false
fi
done
if [[ "$files_ok" == "true" ]]; then
log_success "✓ Required build files test passed"
else
log_error "✗ Required build files test failed"
((test_failures++))
[[ "$FAIL_FAST" == "true" ]] && return $test_failures
fi
log_info "Build validation tests completed with $test_failures failures"
return $test_failures
}
# Generate test report
generate_test_report() {
local total_failures="$1"
log_step "Generating test report..."
local report_file="$PROJECT_ROOT/test-results/test-report.txt"
ensure_dir "$(dirname "$report_file")"
cat > "$report_file" << EOF
RunVSAgent Test Report
=====================
Date: $(date)
Test Type: $TEST_TYPE
Platform: $(get_platform)
Total Failures: $total_failures
Test Configuration:
- Fail Fast: $FAIL_FAST
- Coverage: $COVERAGE
- Watch Mode: $WATCH_MODE
- Verbose: $VERBOSE
- Dry Run: $DRY_RUN
Environment:
- Node Version: $(node --version 2>/dev/null || echo "Not found")
- NPM Version: $(npm --version 2>/dev/null || echo "Not found")
- Git Version: $(git --version 2>/dev/null || echo "Not found")
Test Results:
$(if [[ $total_failures -eq 0 ]]; then echo "✓ All tests passed"; else echo "✗ $total_failures test(s) failed"; fi)
EOF
log_info "Test report generated: $report_file"
}
# Show test summary
show_test_summary() {
local total_failures="$1"
log_step "Test Summary"
echo ""
if [[ $total_failures -eq 0 ]]; then
log_success "All tests passed!"
else
log_error "$total_failures test(s) failed"
fi
log_info "Test type: $TEST_TYPE"
log_info "Platform: $(get_platform)"
if [[ "$DRY_RUN" == "true" ]]; then
log_info "Mode: DRY RUN (no tests were actually executed)"
fi
echo ""
log_info "Test report: $PROJECT_ROOT/test-results/test-report.txt"
if [[ "$COVERAGE" == "true" ]]; then
log_info "Coverage reports: $PROJECT_ROOT/coverage/"
fi
echo ""
}
# Main test function
main() {
log_info "Starting RunVSAgent test process..."
log_info "Script: $SCRIPT_NAME v$SCRIPT_VERSION"
log_info "Platform: $(get_platform)"
log_info "Project root: $PROJECT_ROOT"
# Parse arguments
parse_test_args "$@"
log_info "Test configuration:"
log_info " Type: $TEST_TYPE"
log_info " Fail fast: $FAIL_FAST"
log_info " Coverage: $COVERAGE"
log_info " Watch mode: $WATCH_MODE"
if [[ "$DRY_RUN" == "true" ]]; then
log_warn "DRY RUN MODE - No tests will be executed"
fi
# Setup test environment
setup_test_environment
# Run tests
local total_failures=0
run_env_tests
((total_failures += $?))
run_lint_tests
((total_failures += $?))
run_unit_tests
((total_failures += $?))
run_integration_tests
((total_failures += $?))
run_build_tests
((total_failures += $?))
# Generate report and show summary
generate_test_report "$total_failures"
show_test_summary "$total_failures"
if [[ $total_failures -eq 0 ]]; then
log_success "Test process completed successfully!"
exit 0
else
log_error "Test process completed with failures!"
exit 2
fi
}
# Run main function with all arguments
main "$@"