测试新增: - T05 Free 自由路径(FreePathAutomationTests:完整动画 + 逐帧位置=路径点) - T06 碰撞报告内容断言(CollisionReportAssertions 接入虚拟/真实物体测试) 服务端增强: - list-model-items 端点(枚举物体:DisplayName/PathId/包围盒中心/祖先链) - run-virtual-collision-test 支持 frameRate/durationSeconds(测试动画加速:15fps/5s) - 测试执行串行锁(SemaphoreSlim,防客户端超时后任务占用 UI 线程并发污染) - 标准路径清单/XML 增加自动测试_Free Bug 修复: - AnimationControlViewModel.InvalidateLastGeneratedReport(跨测试碰撞报告残留) - 真实物体身份校验 ReferenceEquals→InstanceGuid(NW ModelItem 实例不保证同引用) - 真实物体动态解析(ModelPath 跨会话不稳定,禁止硬编码 PathId) - PathImportValidity 测试点 Id 随机化(PathPoints.Id 全局主键,p1/p2 固定会冲突) - start-navisworks.ps1:启动前清理 AutoSave(避免恢复弹窗拦截)、文件关联打开模型、dismiss 兜底、启动 15s→4.4s 验证:集成测试 13/13 通过,完整集 6min→59.6s(动画 15fps/5s)
182 lines
6.6 KiB
PowerShell
182 lines
6.6 KiB
PowerShell
[CmdletBinding()]
|
||
param(
|
||
[Parameter(Position = 0)]
|
||
[string]$ModelPath
|
||
)
|
||
|
||
$ErrorActionPreference = 'Stop'
|
||
$scriptDirectory = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||
$repoRoot = Split-Path -Parent $scriptDirectory
|
||
$defaultsFilePath = Join-Path $scriptDirectory 'test-automation.defaults.json'
|
||
|
||
function Resolve-RoamerPath {
|
||
$candidates = New-Object System.Collections.Generic.List[string]
|
||
$appPathKeys = @(
|
||
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Roamer.exe',
|
||
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\App Paths\Roamer.exe'
|
||
)
|
||
|
||
foreach ($key in $appPathKeys) {
|
||
try {
|
||
$value = (Get-ItemProperty -Path $key -ErrorAction Stop).'(default)'
|
||
if (-not [string]::IsNullOrWhiteSpace($value)) {
|
||
$candidates.Add($value)
|
||
}
|
||
}
|
||
catch {
|
||
}
|
||
}
|
||
|
||
$wellKnownPaths = @(
|
||
(Join-Path ${env:ProgramFiles} 'Autodesk\Navisworks Manage 2026\Roamer.exe'),
|
||
(Join-Path ${env:ProgramFiles(x86)} 'Autodesk\Navisworks Manage 2026\Roamer.exe'),
|
||
(Join-Path ${env:ProgramFiles} 'Autodesk\Navisworks Simulate 2026\Roamer.exe'),
|
||
(Join-Path ${env:ProgramFiles(x86)} 'Autodesk\Navisworks Simulate 2026\Roamer.exe')
|
||
) | Where-Object { $_ }
|
||
|
||
foreach ($path in $wellKnownPaths) {
|
||
$candidates.Add($path)
|
||
}
|
||
|
||
foreach ($candidate in $candidates | Select-Object -Unique) {
|
||
if (-not [string]::IsNullOrWhiteSpace($candidate) -and (Test-Path $candidate)) {
|
||
return [System.IO.Path]::GetFullPath($candidate)
|
||
}
|
||
}
|
||
|
||
throw '找不到 Roamer.exe。请确认 Navisworks Manage 2026 已安装。'
|
||
}
|
||
|
||
function Resolve-DefaultModelPath {
|
||
if (-not (Test-Path $defaultsFilePath)) {
|
||
return $null
|
||
}
|
||
|
||
try {
|
||
$defaults = Get-Content $defaultsFilePath -Raw | ConvertFrom-Json
|
||
$defaultModelPath = [string]$defaults.defaultModelPath
|
||
if ([string]::IsNullOrWhiteSpace($defaultModelPath)) {
|
||
return $null
|
||
}
|
||
|
||
$resolvedPath = [System.IO.Path]::GetFullPath($defaultModelPath)
|
||
if (-not (Test-Path $resolvedPath)) {
|
||
throw "默认模型文件不存在: $resolvedPath"
|
||
}
|
||
|
||
return $resolvedPath
|
||
}
|
||
catch {
|
||
throw "读取默认测试配置失败: $($_.Exception.Message)"
|
||
}
|
||
}
|
||
|
||
function Dismiss-RecoveryPromptIfPresent {
|
||
param(
|
||
[int]$TimeoutSeconds = 20
|
||
)
|
||
|
||
Add-Type -AssemblyName System.Windows.Forms | Out-Null
|
||
$shell = New-Object -ComObject WScript.Shell
|
||
# NW 启动恢复提示框标题关键词(覆盖“从自动保存重新载入”“是否打开之前保存的模型”等变体)
|
||
$windowTitleKeywords = @(
|
||
'自动保存',
|
||
'保存的模型',
|
||
'重新载入',
|
||
'恢复'
|
||
)
|
||
|
||
$deadline = (Get-Date).AddSeconds($TimeoutSeconds)
|
||
while ((Get-Date) -lt $deadline) {
|
||
foreach ($keyword in $windowTitleKeywords) {
|
||
try {
|
||
# AppActivate 支持子串匹配,激活标题包含关键词的窗口
|
||
if ($shell.AppActivate($keyword)) {
|
||
Start-Sleep -Milliseconds 300
|
||
[System.Windows.Forms.SendKeys]::SendWait('%N')
|
||
Write-Host "已自动选择“否”以跳过恢复提示框(关键词: $keyword)。"
|
||
return
|
||
}
|
||
}
|
||
catch {
|
||
}
|
||
}
|
||
|
||
Start-Sleep -Milliseconds 300
|
||
}
|
||
}
|
||
|
||
function Clear-NavisworksAutoSave {
|
||
# 清理 NW 自动保存文件:NW 启动时检测到 AutoSave 残留会弹“是否打开之前保存的模型”
|
||
# 提示框并拦截命令行打开请求。测试环境提前清理可彻底避免弹窗(测试前先正常退出 NW 以保存用户数据)。
|
||
$autoSaveDir = Join-Path $env:APPDATA 'Autodesk\Navisworks Manage 2026\AutoSave'
|
||
if (Test-Path $autoSaveDir) {
|
||
$removedCount = (Get-ChildItem $autoSaveDir -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue | Measure-Object).Count
|
||
Write-Host "已清理 Navisworks 自动保存文件(避免恢复提示框): $autoSaveDir"
|
||
}
|
||
}
|
||
|
||
if ([string]::IsNullOrWhiteSpace($ModelPath)) {
|
||
$ModelPath = Resolve-DefaultModelPath
|
||
}
|
||
|
||
if (-not [string]::IsNullOrWhiteSpace($ModelPath)) {
|
||
$ModelPath = [System.IO.Path]::GetFullPath($ModelPath)
|
||
if (-not (Test-Path $ModelPath)) {
|
||
throw "模型文件不存在: $ModelPath"
|
||
}
|
||
}
|
||
|
||
$roamerPath = Resolve-RoamerPath
|
||
$existingProcess = Get-Process Roamer -ErrorAction SilentlyContinue | Select-Object -First 1
|
||
$env:TRANSPORTPLUGIN_TEST_AUTOMATION = '1'
|
||
|
||
if ($existingProcess) {
|
||
Write-Host ("Navisworks 已在运行,PID={0}" -f $existingProcess.Id)
|
||
if (-not [string]::IsNullOrWhiteSpace($ModelPath)) {
|
||
# 通过文件关联请求打开模型(Start-Process 传参对 NW 2026 不可靠)
|
||
Start-Process -FilePath $ModelPath | Out-Null
|
||
Write-Host ("已请求 Navisworks 打开模型: {0}" -f $ModelPath)
|
||
}
|
||
|
||
Dismiss-RecoveryPromptIfPresent -TimeoutSeconds 30
|
||
|
||
Write-Host '提示: 当前测试 HTTP 服务在插件 DockPane OnLoaded 中启动,首次测试前请确保插件面板已打开。'
|
||
exit 0
|
||
}
|
||
|
||
# 启动前清理自动保存文件,避免 NW 弹出恢复提示框(弹窗会拦截命令行打开模型)
|
||
Clear-NavisworksAutoSave
|
||
|
||
if (-not [string]::IsNullOrWhiteSpace($ModelPath)) {
|
||
# 直接通过文件关联启动并打开模型(NW 2026 命令行传参打开文件不可靠)
|
||
$startProcess = Start-Process -FilePath $ModelPath -PassThru
|
||
$processId = $startProcess.Id
|
||
Write-Host ("Navisworks 启动中(文件关联),PID={0}" -f $processId)
|
||
}
|
||
else {
|
||
$process = Start-Process -FilePath $roamerPath -PassThru
|
||
$processId = $process.Id
|
||
Write-Host ("Navisworks 启动中,PID={0}" -f $processId)
|
||
}
|
||
|
||
$deadline = (Get-Date).AddSeconds(30)
|
||
do {
|
||
Start-Sleep -Milliseconds 500
|
||
$running = Get-Process -Id $processId -ErrorAction SilentlyContinue
|
||
} while (-not $running -and (Get-Date) -lt $deadline)
|
||
|
||
if (-not $running) {
|
||
throw 'Navisworks 启动超时,30 秒内未检测到 Roamer.exe 进程。'
|
||
}
|
||
|
||
# 兜底:清理 AutoSave 后通常无恢复弹窗;短超时单次处理可能出现的其他提示框
|
||
Dismiss-RecoveryPromptIfPresent -TimeoutSeconds 3
|
||
|
||
Write-Host ("Navisworks 已启动: {0}" -f $roamerPath)
|
||
if (-not [string]::IsNullOrWhiteSpace($ModelPath)) {
|
||
Write-Host ("已打开模型参数: {0}" -f $ModelPath)
|
||
}
|
||
|
||
Write-Host '提示: 当前测试 HTTP 服务在插件 DockPane OnLoaded 中启动,首次测试前请确保插件面板已打开。'
|