282 lines
8.9 KiB
PowerShell
282 lines
8.9 KiB
PowerShell
# Gym Manage - 全量测试编排脚本
|
|
# 用法: .\run-all-tests.ps1 [-Backend] [-Admin] [-Member] [-Coach] [-All] [-ReportOnly] [-SkipBuild]
|
|
# 默认: -All
|
|
|
|
param(
|
|
[switch]$Backend,
|
|
[switch]$Admin,
|
|
[switch]$Member,
|
|
[switch]$Coach,
|
|
[switch]$All,
|
|
[switch]$ReportOnly,
|
|
[switch]$SkipBuild
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
$RootDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
|
|
# 颜色输出
|
|
function Write-Step { Write-Host "`n========================================" -ForegroundColor Cyan; Write-Host " $args" -ForegroundColor Cyan; Write-Host "========================================" -ForegroundColor Cyan }
|
|
function Write-Success { Write-Host " [OK] $args" -ForegroundColor Green }
|
|
function Write-Fail { Write-Host " [FAIL] $args" -ForegroundColor Red }
|
|
function Write-Warn { Write-Host " [WARN] $args" -ForegroundColor Yellow }
|
|
function Write-Info { Write-Host " [INFO] $args" -ForegroundColor Gray }
|
|
|
|
# 结果收集
|
|
$Results = @{}
|
|
$StartTime = Get-Date
|
|
|
|
# =============================================
|
|
# 阶段0: 环境检查
|
|
# =============================================
|
|
Write-Step "阶段0: 环境检查"
|
|
|
|
# 检查 Java
|
|
try {
|
|
$javaVer = java -version 2>&1 | Select-Object -First 1
|
|
Write-Success "Java available: $javaVer"
|
|
} catch {
|
|
Write-Fail "Java not found. Please install JDK 21."
|
|
exit 1
|
|
}
|
|
|
|
# 检查 Node
|
|
try {
|
|
$nodeVer = node -v
|
|
Write-Success "Node available: $nodeVer"
|
|
} catch {
|
|
Write-Fail "Node not found. Please install Node.js."
|
|
exit 1
|
|
}
|
|
|
|
# 检查 Maven Wrapper
|
|
$MvnCmd = if (Test-Path "$RootDir\gym-manage-api\mvnw.cmd") { "$RootDir\gym-manage-api\mvnw.cmd" } else { "mvn" }
|
|
|
|
# 检查微信开发者工具CLI(端口45869)
|
|
$wcCliPort = 45869
|
|
try {
|
|
$wcCheck = Invoke-WebRequest -Uri "http://127.0.0.1:$wcCliPort" -TimeoutSec 3 -ErrorAction SilentlyContinue
|
|
if ($wcCheck.StatusCode -eq 200 -or $wcCheck.StatusCode -eq 404) {
|
|
Write-Success "WeChat DevTools CLI available on port $wcCliPort"
|
|
}
|
|
} catch {
|
|
Write-Warn "WeChat DevTools CLI not detected on port $wcCliPort. MiniTest tests will be skipped."
|
|
}
|
|
|
|
# =============================================
|
|
# 阶段1: 启动后端服务
|
|
# =============================================
|
|
Write-Step "阶段1: 启动后端服务"
|
|
|
|
$BackendPort = 8084
|
|
$BackendHealthUrl = "http://localhost:$BackendPort/actuator/health"
|
|
|
|
function Test-BackendHealth {
|
|
try {
|
|
$r = Invoke-WebRequest -Uri $BackendHealthUrl -TimeoutSec 5 -ErrorAction SilentlyContinue
|
|
return ($r.StatusCode -eq 200)
|
|
} catch { return $false }
|
|
}
|
|
|
|
$backendWasRunning = Test-BackendHealth
|
|
if ($backendWasRunning) {
|
|
Write-Success "Backend already running on port $BackendPort"
|
|
} else {
|
|
Write-Info "Starting backend with Maven..."
|
|
|
|
$backendJob = Start-Job -ScriptBlock {
|
|
param($mvnCmd, $apiDir)
|
|
Set-Location $apiDir
|
|
& $mvnCmd spring-boot:run -Dspring-boot.run.profiles=test 2>&1
|
|
} -ArgumentList $MvnCmd, "$RootDir\gym-manage-api\manage-app"
|
|
|
|
# 等待后端就绪 (最多90秒)
|
|
$retries = 0
|
|
while (-not (Test-BackendHealth) -and $retries -lt 90) {
|
|
$retries++
|
|
Write-Progress -Activity "Waiting for backend..." -PercentComplete (($retries / 90) * 100) -Status "$retries/90s"
|
|
Start-Sleep -Seconds 1
|
|
}
|
|
Write-Progress -Activity "Waiting for backend..." -Completed
|
|
|
|
if (Test-BackendHealth) {
|
|
Write-Success "Backend started successfully ($retries seconds)"
|
|
} else {
|
|
Write-Fail "Backend failed to start within 90 seconds"
|
|
Stop-Job $backendJob
|
|
Remove-Job $backendJob
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
# =============================================
|
|
# 阶段2: 执行测试套件
|
|
# =============================================
|
|
|
|
function Invoke-TestStage {
|
|
param(
|
|
[string]$Name,
|
|
[string]$WorkingDir,
|
|
[string]$Command,
|
|
[bool]$Enabled = $true
|
|
)
|
|
|
|
if (-not $Enabled) {
|
|
Write-Warn "Skipping $Name (not requested)"
|
|
$Results[$Name] = "SKIPPED"
|
|
return
|
|
}
|
|
|
|
Write-Step "Running: $Name"
|
|
Write-Info "Working directory: $WorkingDir"
|
|
Write-Info "Command: $Command"
|
|
|
|
try {
|
|
Push-Location $WorkingDir
|
|
$sw = [System.Diagnostics.Stopwatch]::StartNew()
|
|
Invoke-Expression $Command
|
|
$sw.Stop()
|
|
Write-Success "$Name completed in $([math]::Round($sw.Elapsed.TotalSeconds, 1))s"
|
|
$Results[$Name] = "PASS ($([math]::Round($sw.Elapsed.TotalSeconds, 1))s)"
|
|
Pop-Location
|
|
} catch {
|
|
Write-Fail "$Name failed: $_"
|
|
$Results[$Name] = "FAIL"
|
|
Pop-Location
|
|
}
|
|
}
|
|
|
|
# 决定执行哪些测试
|
|
$runBackend = $All -or $Backend
|
|
$runAdmin = $All -or $Admin
|
|
$runMember = $All -or $Member
|
|
$runCoach = $All -or $Coach
|
|
|
|
if (-not ($Backend -or $Admin -or $Member -or $Coach)) { $runBackend = $runAdmin = $runMember = $runCoach = $true }
|
|
|
|
# 后端 API 契约测试
|
|
Invoke-TestStage -Name "Backend-API-Contract" `
|
|
-WorkingDir "$RootDir\gym-manage-api" `
|
|
-Command "$MvnCmd test -pl manage-app -Dtest='cn.novalon.gym.manage.app.contract.*Test' -DfailIfNoTests=false" `
|
|
-Enabled $runBackend
|
|
|
|
# Admin E2E: Smoke
|
|
Invoke-TestStage -Name "Admin-E2E-Smoke" `
|
|
-WorkingDir "$RootDir\gym-manage-web" `
|
|
-Command "npx playwright test --project=smoke --reporter=list" `
|
|
-Enabled $runAdmin
|
|
|
|
# Admin E2E: Journeys (需等待smoke完成)
|
|
if ($runAdmin) {
|
|
Invoke-TestStage -Name "Admin-E2E-Journeys" `
|
|
-WorkingDir "$RootDir\gym-manage-web" `
|
|
-Command "npx playwright test --project=journeys --reporter=list" `
|
|
-Enabled $true
|
|
}
|
|
|
|
# UniApp 会员端 MiniTest
|
|
if ($runMember) {
|
|
$memberTestDir = "$RootDir\gym-manage-uniapp"
|
|
if (Test-Path "$memberTestDir\jest.e2e.config.js") {
|
|
Invoke-TestStage -Name "UniApp-Member-MiniTest" `
|
|
-WorkingDir $memberTestDir `
|
|
-Command "npx jest --config jest.e2e.config.js --forceExit" `
|
|
-Enabled $true
|
|
} else {
|
|
Write-Warn "Member MiniTest config not found, skipping"
|
|
$Results["UniApp-Member-MiniTest"] = "SKIPPED (no config)"
|
|
}
|
|
}
|
|
|
|
# UniApp 教练端 MiniTest
|
|
if ($runCoach) {
|
|
$coachTestDir = "$RootDir\gym-manage-coach-uniapp"
|
|
if (Test-Path "$coachTestDir\jest.e2e.config.js") {
|
|
Invoke-TestStage -Name "UniApp-Coach-MiniTest" `
|
|
-WorkingDir $coachTestDir `
|
|
-Command "npx jest --config jest.e2e.config.js --forceExit" `
|
|
-Enabled $true
|
|
} else {
|
|
Write-Warn "Coach MiniTest config not found, skipping"
|
|
$Results["UniApp-Coach-MiniTest"] = "SKIPPED (no config)"
|
|
}
|
|
}
|
|
|
|
# =============================================
|
|
# 阶段3: 汇总报告
|
|
# =============================================
|
|
Write-Step "阶段3: 测试汇总报告"
|
|
|
|
$EndTime = Get-Date
|
|
$TotalTime = [math]::Round(($EndTime - $StartTime).TotalSeconds, 1)
|
|
|
|
$totalPass = 0
|
|
$totalFail = 0
|
|
$totalSkip = 0
|
|
|
|
Write-Host ""
|
|
Write-Host " Test Results Summary" -ForegroundColor White
|
|
Write-Host " $(('=' * 60))" -ForegroundColor DarkGray
|
|
|
|
foreach ($key in $Results.Keys | Sort-Object) {
|
|
$val = $Results[$key]
|
|
if ($val -like "PASS*") {
|
|
Write-Host " [PASS] " -NoNewline -ForegroundColor Green
|
|
Write-Host "$key : $val"
|
|
$totalPass++
|
|
} elseif ($val -like "FAIL*") {
|
|
Write-Host " [FAIL] " -NoNewline -ForegroundColor Red
|
|
Write-Host "$key : $val"
|
|
$totalFail++
|
|
} else {
|
|
Write-Host " [SKIP] " -NoNewline -ForegroundColor Yellow
|
|
Write-Host "$key : $val"
|
|
$totalSkip++
|
|
}
|
|
}
|
|
|
|
Write-Host " $(('=' * 60))" -ForegroundColor DarkGray
|
|
Write-Host (" Total: {0} | Pass: {1} | Fail: {2} | Skip: {3} | Time: {4}s" -f ($totalPass + $totalFail + $totalSkip), $totalPass, $totalFail, $totalSkip, $TotalTime) -ForegroundColor White
|
|
Write-Host ""
|
|
|
|
# 生成JSON报告
|
|
$ReportPath = "$RootDir\test-results\summary-$(Get-Date -Format 'yyyyMMdd-HHmmss').json"
|
|
$ReportDir = Split-Path $ReportPath -Parent
|
|
if (-not (Test-Path $ReportDir)) { New-Item -ItemType Directory -Path $ReportDir -Force | Out-Null }
|
|
|
|
$Report = @{
|
|
timestamp = (Get-Date -Format "yyyy-MM-ddTHH:mm:ss")
|
|
totalTimeSeconds = $TotalTime
|
|
results = $Results
|
|
summary = @{
|
|
total = $totalPass + $totalFail + $totalSkip
|
|
pass = $totalPass
|
|
fail = $totalFail
|
|
skip = $totalSkip
|
|
}
|
|
}
|
|
|
|
$Report | ConvertTo-Json -Depth 3 | Out-File -FilePath $ReportPath -Encoding UTF8
|
|
Write-Success "Report saved to: $ReportPath"
|
|
|
|
# =============================================
|
|
# 阶段4: 清理
|
|
# =============================================
|
|
Write-Step "阶段4: 清理"
|
|
|
|
# 如果后端是我们启动的,停止它
|
|
if (-not $backendWasRunning -and $backendJob) {
|
|
Write-Info "Stopping backend..."
|
|
Stop-Job $backendJob -ErrorAction SilentlyContinue
|
|
Remove-Job $backendJob -ErrorAction SilentlyContinue
|
|
Write-Success "Backend stopped"
|
|
}
|
|
|
|
if ($totalFail -gt 0) {
|
|
Write-Host "`n Some tests FAILED. Check reports for details." -ForegroundColor Red
|
|
exit 1
|
|
} else {
|
|
Write-Host "`n All tests PASSED!" -ForegroundColor Green
|
|
exit 0
|
|
}
|