Skip to main content
Glama
run-unity-tests.ps112.8 kB
#!/usr/bin/env pwsh <# .SYNOPSIS Run Unity tests locally without Docker .DESCRIPTION This script executes Unity tests directly using your local Unity installation, replicating what the GitHub Actions workflow does but without Docker or act. .PARAMETER TestMode Which test mode to run: editmode, playmode, standalone, or all (default: all) .PARAMETER UnityPath Path to Unity.exe (required) .PARAMETER ProjectPath Path to Unity project (default: ./Unity-MCP-Plugin) .PARAMETER OutputDir Directory for test results and logs (default: ./TestResults) .EXAMPLE .\run-unity-tests.ps1 -UnityPath "C:\Program Files\Unity\Hub\Editor\2022.3.61f1\Editor\Unity.exe" .\run-unity-tests.ps1 -UnityPath "C:\Unity\Editor\Unity.exe" -TestMode editmode .\run-unity-tests.ps1 -UnityPath "C:\Unity\Editor\Unity.exe" -TestMode all -Verbose #> [CmdletBinding()] param( [ValidateSet('editmode', 'playmode', 'standalone', 'all')] [string]$TestMode = "all", [Parameter(Mandatory = $true)] [string]$UnityPath, [string]$ProjectPath = "./Unity-MCP-Plugin", [string]$OutputDir = "./commands/TestResults" ) # ============================================================================ # Helper Functions # ============================================================================ function Write-Section { param([string]$Title) Write-Host "" Write-Host "=== $Title ===" -ForegroundColor Cyan Write-Host "" } function Write-Success { param([string]$Message) Write-Host "[OK] $Message" -ForegroundColor Green } function Write-Error-Message { param([string]$Message) Write-Host "[ERROR] $Message" -ForegroundColor Red } function Write-Info { param([string]$Message) Write-Host "[INFO] $Message" -ForegroundColor White } function Invoke-UnityTest { param( [string]$UnityExe, [string]$ProjectPath, [string]$TestPlatform, [string]$ResultsFile, [string]$LogFile ) $testModeName = $TestPlatform Write-Section "Running $testModeName Tests" # Build Unity command $unityArgs = @( "-runTests", "-batchmode", "-projectPath", "`"$ProjectPath`"", "-testResults", "`"$ResultsFile`"", "-testPlatform", $TestPlatform, "-logFile", "`"$LogFile`"", "-CI", "true", "-GITHUB_ACTIONS", "true" ) Write-Info "Test Platform: $TestPlatform" Write-Info "Results: $ResultsFile" Write-Info "Log: $LogFile" Write-Host "" # Execute Unity $startTime = Get-Date $processInfo = New-Object System.Diagnostics.ProcessStartInfo $processInfo.FileName = $UnityExe $processInfo.Arguments = $unityArgs -join " " $processInfo.UseShellExecute = $false $processInfo.RedirectStandardOutput = $true $processInfo.RedirectStandardError = $true $process = New-Object System.Diagnostics.Process $process.StartInfo = $processInfo # Event handlers for output $outputBuilder = New-Object System.Text.StringBuilder $errorBuilder = New-Object System.Text.StringBuilder $outputHandler = { if ($EventArgs.Data) { $line = $EventArgs.Data [void]$Event.MessageData.AppendLine($line) if ($script:VerboseOutput -eq 'Continue') { Write-Host $line -ForegroundColor Gray } } } $errorHandler = { if ($EventArgs.Data) { $line = $EventArgs.Data [void]$Event.MessageData.AppendLine($line) Write-Host $line -ForegroundColor Red } } $script:VerboseOutput = $VerbosePreference Register-ObjectEvent -InputObject $process -EventName OutputDataReceived -Action $outputHandler -MessageData $outputBuilder | Out-Null Register-ObjectEvent -InputObject $process -EventName ErrorDataReceived -Action $errorHandler -MessageData $errorBuilder | Out-Null [void]$process.Start() $process.BeginOutputReadLine() $process.BeginErrorReadLine() Write-Host "Unity is running tests..." -ForegroundColor Cyan if ($VerbosePreference -ne 'Continue') { Write-Host "(Use -Verbose flag to see real-time output)" -ForegroundColor Gray } $process.WaitForExit() # Cleanup event handlers Get-EventSubscriber | Where-Object { $_.SourceObject -eq $process } | Unregister-Event $endTime = Get-Date $duration = $endTime - $startTime $exitCode = $process.ExitCode Write-Host "" Write-Info "Duration: $($duration.ToString('mm\:ss'))" Write-Info "Exit Code: $exitCode" return @{ ExitCode = $exitCode Duration = $duration TestPlatform = $TestPlatform ResultsFile = $ResultsFile LogFile = $LogFile } } function Parse-TestResults { param([string]$XmlPath) if (-not (Test-Path $XmlPath)) { return @{ Success = $false Total = 0 Passed = 0 Failed = 0 Skipped = 0 Error = "Results file not found" } } try { [xml]$xml = Get-Content $XmlPath # NUnit 3 format $testRun = $xml.'test-run' if ($testRun) { return @{ Success = ($testRun.failed -eq "0" -and $testRun.result -eq "Passed") Total = [int]$testRun.total Passed = [int]$testRun.passed Failed = [int]$testRun.failed Skipped = [int]$testRun.skipped Inconclusive = [int]$testRun.inconclusive Duration = $testRun.duration } } # Fallback NUnit 2 format $testResults = $xml.'test-results' if ($testResults) { $total = [int]$testResults.total $failures = [int]$testResults.failures $errors = [int]$testResults.errors $notRun = [int]$testResults.'not-run' return @{ Success = ($failures -eq 0 -and $errors -eq 0) Total = $total Passed = $total - $failures - $errors - $notRun Failed = $failures + $errors Skipped = $notRun } } return @{ Success = $false Error = "Unknown XML format" } } catch { return @{ Success = $false Error = $_.Exception.Message } } } # ============================================================================ # Main Script # ============================================================================ # Set location to repository root (parent of commands folder) $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $repoRoot = Split-Path -Parent $scriptDir Push-Location $repoRoot Write-Section "Unity Local Test Runner" Write-Info "Repository Root: $repoRoot" # Convert to absolute paths $ProjectPath = Resolve-Path $ProjectPath -ErrorAction SilentlyContinue if (-not $ProjectPath) { Write-Error-Message "Project path not found: $ProjectPath" Pop-Location exit 1 } Write-Info "Project: $ProjectPath" # ============================================================================ # Step 1: Verify Unity Path # ============================================================================ if (-not (Test-Path $UnityPath)) { Write-Error-Message "Unity.exe not found at: $UnityPath" Write-Host "" Write-Host "Please provide a valid path to Unity.exe:" -ForegroundColor Yellow Write-Host " Example: -UnityPath `"C:\Program Files\Unity\Hub\Editor\2022.3.61f1\Editor\Unity.exe`"" -ForegroundColor Gray Pop-Location exit 1 } Write-Success "Unity Executable: $UnityPath" # ============================================================================ # Step 2: Prepare Output Directories # ============================================================================ # Create directories first, then resolve to absolute path New-Item -ItemType Directory -Force -Path $OutputDir | Out-Null $OutputDir = (Resolve-Path $OutputDir).Path $logsDir = Join-Path $OutputDir "Logs" New-Item -ItemType Directory -Force -Path $logsDir | Out-Null Write-Success "Output Directory: $OutputDir" # ============================================================================ # Step 3: Determine Test Modes # ============================================================================ $testModes = @() if ($TestMode -eq "all") { $testModes = @("EditMode", "PlayMode", "StandaloneWindows64") } else { $testModes = switch ($TestMode) { "editmode" { @("EditMode") } "playmode" { @("PlayMode") } "standalone" { @("StandaloneWindows64") } } } Write-Info "Test Modes: $($testModes -join ', ')" # ============================================================================ # Step 4: Run Tests # ============================================================================ $results = @() foreach ($mode in $testModes) { $resultsFile = Join-Path $OutputDir "TestResults-$mode.xml" $logFile = Join-Path $logsDir "Unity-$mode.log" # Remove old results if (Test-Path $resultsFile) { Remove-Item $resultsFile -Force } if (Test-Path $logFile) { Remove-Item $logFile -Force } $result = Invoke-UnityTest ` -UnityExe $UnityPath ` -ProjectPath $ProjectPath ` -TestPlatform $mode ` -ResultsFile $resultsFile ` -LogFile $logFile $results += $result } # ============================================================================ # Step 5: Parse and Display Results # ============================================================================ Write-Section "Test Results Summary" $overallSuccess = $true $totalTests = 0 $totalPassed = 0 $totalFailed = 0 $totalSkipped = 0 foreach ($result in $results) { $mode = $result.TestPlatform $exitCode = $result.ExitCode Write-Host "" Write-Host "--- $mode ---" -ForegroundColor Cyan if ($exitCode -ne 0) { Write-Host "Status: FAILED (Exit Code: $exitCode)" -ForegroundColor Red $overallSuccess = $false Write-Host "Log file: $($result.LogFile)" -ForegroundColor Yellow } else { $parsed = Parse-TestResults -XmlPath $result.ResultsFile if ($parsed.Error) { Write-Host "Status: ERROR" -ForegroundColor Red Write-Host "Error: $($parsed.Error)" -ForegroundColor Red $overallSuccess = $false } elseif ($parsed.Success) { Write-Host "Status: PASSED" -ForegroundColor Green Write-Host "Tests: $($parsed.Passed)/$($parsed.Total) passed" -ForegroundColor Green if ($parsed.Skipped -gt 0) { Write-Host "Skipped: $($parsed.Skipped)" -ForegroundColor Yellow } $totalTests += $parsed.Total $totalPassed += $parsed.Passed $totalSkipped += $parsed.Skipped } else { Write-Host "Status: FAILED" -ForegroundColor Red Write-Host "Tests: $($parsed.Passed)/$($parsed.Total) passed, $($parsed.Failed) failed" -ForegroundColor Red $totalTests += $parsed.Total $totalPassed += $parsed.Passed $totalFailed += $parsed.Failed $totalSkipped += $parsed.Skipped $overallSuccess = $false } } Write-Host "Duration: $($result.Duration.ToString('mm\:ss'))" -ForegroundColor White Write-Host "Results: $($result.ResultsFile)" -ForegroundColor Gray } # ============================================================================ # Step 6: Final Summary # ============================================================================ Write-Section "Overall Summary" Write-Host "Total Tests: $totalTests" -ForegroundColor White Write-Host "Passed: $totalPassed" -ForegroundColor Green if ($totalFailed -gt 0) { Write-Host "Failed: $totalFailed" -ForegroundColor Red } if ($totalSkipped -gt 0) { Write-Host "Skipped: $totalSkipped" -ForegroundColor Yellow } Write-Host "" Write-Host "Results Location: $OutputDir" -ForegroundColor Cyan if ($overallSuccess) { Write-Host "" Write-Host "All tests PASSED!" -ForegroundColor Green Write-Host "" Pop-Location exit 0 } else { Write-Host "" Write-Host "Some tests FAILED!" -ForegroundColor Red Write-Host "" Write-Host "Troubleshooting:" -ForegroundColor Yellow Write-Host " - Check log files in: $logsDir" -ForegroundColor Gray Write-Host " - Check test results in: $OutputDir" -ForegroundColor Gray Write-Host " - Run with -Verbose flag for detailed output" -ForegroundColor Gray Write-Host "" Pop-Location exit 1 }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/IvanMurzak/Unity-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server