unity-mcp/TestProjects/UnityMCPTests/Assets/Tests/EditMode/Tools/ManageScriptableObjectTests.cs

308 lines
14 KiB
C#
Raw Normal View History

using System;
Feature/run tests summary clean (#501) * Optimize run_tests to return summary by default, reducing token usage by 98% - Add includeFailedTests parameter: returns only failed/skipped test details - Add includeDetails parameter: returns all test details (original behavior) - Default behavior now returns summary only (~150 tokens vs ~13k tokens) - Make results field optional in Python schema for backward compatibility Token savings: - Default: ~13k tokens saved (98.9% reduction) - With failures: minimal tokens (only non-passing tests) - Full details: same as before when explicitly requested This prevents context bloat for typical test runs where you only need pass/fail counts, while still allowing detailed debugging when needed. * Add warning when run_tests filters match no tests; fix test organization TDD Feature: - Add warning message when filter criteria match zero tests - New RunTestsTests.cs validates message formatting logic - Modified RunTests.cs to append "(No tests matched the specified filters)" when total=0 Test Organization Fixes: - Move MCPToolParameterTests.cs from EditMode/ to EditMode/Tools/ (matches folder hierarchy) - Fix inconsistent namespaces to MCPForUnityTests.Editor.{Subfolder}: - MCPToolParameterTests: Tests.EditMode → MCPForUnityTests.Editor.Tools - DomainReloadResilienceTests: Tests.EditMode.Tools → MCPForUnityTests.Editor.Tools - Matrix4x4ConverterTests: MCPForUnityTests.EditMode.Helpers → MCPForUnityTests.Editor.Helpers * Refactor test result message formatting * Simplify RunTests warning assertions * Tests: de-flake cold-start EditMode runs - Make ManageScriptableObjectTests setup yield-based with longer Unity-ready timeout - Mark DomainReloadResilienceTests explicit to avoid triggering domain reload during Run All
2026-01-02 12:36:45 +08:00
using System.Collections;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
using UnityEditor;
using UnityEngine;
Feature/run tests summary clean (#501) * Optimize run_tests to return summary by default, reducing token usage by 98% - Add includeFailedTests parameter: returns only failed/skipped test details - Add includeDetails parameter: returns all test details (original behavior) - Default behavior now returns summary only (~150 tokens vs ~13k tokens) - Make results field optional in Python schema for backward compatibility Token savings: - Default: ~13k tokens saved (98.9% reduction) - With failures: minimal tokens (only non-passing tests) - Full details: same as before when explicitly requested This prevents context bloat for typical test runs where you only need pass/fail counts, while still allowing detailed debugging when needed. * Add warning when run_tests filters match no tests; fix test organization TDD Feature: - Add warning message when filter criteria match zero tests - New RunTestsTests.cs validates message formatting logic - Modified RunTests.cs to append "(No tests matched the specified filters)" when total=0 Test Organization Fixes: - Move MCPToolParameterTests.cs from EditMode/ to EditMode/Tools/ (matches folder hierarchy) - Fix inconsistent namespaces to MCPForUnityTests.Editor.{Subfolder}: - MCPToolParameterTests: Tests.EditMode → MCPForUnityTests.Editor.Tools - DomainReloadResilienceTests: Tests.EditMode.Tools → MCPForUnityTests.Editor.Tools - Matrix4x4ConverterTests: MCPForUnityTests.EditMode.Helpers → MCPForUnityTests.Editor.Helpers * Refactor test result message formatting * Simplify RunTests warning assertions * Tests: de-flake cold-start EditMode runs - Make ManageScriptableObjectTests setup yield-based with longer Unity-ready timeout - Mark DomainReloadResilienceTests explicit to avoid triggering domain reload during Run All
2026-01-02 12:36:45 +08:00
using UnityEngine.TestTools;
using MCPForUnity.Editor.Tools;
using MCPForUnityTests.Editor.Tools.Fixtures;
Harden `manage_scriptable_object` Tool (#522) * feat(manage_scriptable_object): harden tool with path normalization, auto-resize, bulk mapping Phase 1: Path Syntax & Auto-Resizing - Add NormalizePropertyPath() to convert field[index] to Array.data format - Add EnsureArrayCapacity() to auto-grow arrays when targeting out-of-bounds indices Phase 2: Consolidation - Replace duplicate TryGet* helpers with ParamCoercion/VectorParsing shared utilities - Add Vector4 parsing support to VectorParsing.cs Phase 3: Bulk Data Mapping - Handle JArray values for list/array properties (recursive element setting) - Handle JObject values for nested struct/class properties Phase 4: Enhanced Reference Resolution - Support plain 32-char GUID strings for ObjectReference fields Phase 5: Validation & Dry-Run - Add ValidatePatches() for pre-validation of all patches - Add dry_run parameter to validate without mutating Includes comprehensive stress test suite covering: - Big Bang (large nested arrays), Out of Bounds, Friendly Path Syntax - Deep Nesting, Mixed References, Rapid Fire, Type Mismatch - Bulk Array Mapping, GUID Shorthand, Dry Run validation * feat: Add AnimationCurve and Quaternion support to manage_scriptable_object tool - Implement TrySetAnimationCurve() supporting both {'keys': [...]} and direct [...] formats * Support keyframe properties: time, value, inSlope, outSlope, weightedMode, inWeight, outWeight * Gracefully default missing optional fields to 0 * Clear error messages for malformed structures - Implement TrySetQuaternion() with 4 input formats: * Euler array [x, y, z] - 3 elements interpreted as degrees * Raw array [x, y, z, w] - 4 components * Object format {x, y, z, w} - explicit components * Explicit euler {euler: [x, y, z]} - labeled format - Improve error handling: * Null values: AnimationCurve→empty, Quaternion→identity * Invalid inputs rejected with specific, actionable error messages * Validate keyframe objects and array sizes - Add comprehensive test coverage in ManageScriptableObjectStressTests.cs: * AnimationCurve with keyframe array format * AnimationCurve with direct array (no wrapper) * Quaternion via Euler angles * Quaternion via raw components * Quaternion via object format * Quaternion via explicit euler property - Fix test file compilation issues: * Replace undefined TestFolder with _runRoot * Add System.IO using statement * refactor: consolidate test utilities to eliminate duplication - Add TestUtilities.cs with shared helpers: - ToJObject() - consolidates 11 duplicates across test files - EnsureFolder() - consolidates 2 duplicates - WaitForUnityReady() - consolidates 2 duplicates - FindFallbackShader() - consolidates shader chain duplicates - SafeDeleteAsset() - helper for asset cleanup - CleanupEmptyParentFolders() - standardizes TearDown cleanup - Update 11 test files to use shared TestUtilities via 'using static' - Standardize TearDown cleanup patterns across all test files - Net reduction of ~40 lines while improving maintainability * fix: add missing animCurve and rotation fields to ComplexStressSO Add AnimationCurve and Quaternion fields required by Phase 6 stress tests.
2026-01-07 22:46:35 +08:00
using static MCPForUnityTests.Editor.TestUtilities;
namespace MCPForUnityTests.Editor.Tools
{
public class ManageScriptableObjectTests
{
private const string TempRoot = "Assets/Temp/ManageScriptableObjectTests";
Feature/run tests summary clean (#501) * Optimize run_tests to return summary by default, reducing token usage by 98% - Add includeFailedTests parameter: returns only failed/skipped test details - Add includeDetails parameter: returns all test details (original behavior) - Default behavior now returns summary only (~150 tokens vs ~13k tokens) - Make results field optional in Python schema for backward compatibility Token savings: - Default: ~13k tokens saved (98.9% reduction) - With failures: minimal tokens (only non-passing tests) - Full details: same as before when explicitly requested This prevents context bloat for typical test runs where you only need pass/fail counts, while still allowing detailed debugging when needed. * Add warning when run_tests filters match no tests; fix test organization TDD Feature: - Add warning message when filter criteria match zero tests - New RunTestsTests.cs validates message formatting logic - Modified RunTests.cs to append "(No tests matched the specified filters)" when total=0 Test Organization Fixes: - Move MCPToolParameterTests.cs from EditMode/ to EditMode/Tools/ (matches folder hierarchy) - Fix inconsistent namespaces to MCPForUnityTests.Editor.{Subfolder}: - MCPToolParameterTests: Tests.EditMode → MCPForUnityTests.Editor.Tools - DomainReloadResilienceTests: Tests.EditMode.Tools → MCPForUnityTests.Editor.Tools - Matrix4x4ConverterTests: MCPForUnityTests.EditMode.Helpers → MCPForUnityTests.Editor.Helpers * Refactor test result message formatting * Simplify RunTests warning assertions * Tests: de-flake cold-start EditMode runs - Make ManageScriptableObjectTests setup yield-based with longer Unity-ready timeout - Mark DomainReloadResilienceTests explicit to avoid triggering domain reload during Run All
2026-01-02 12:36:45 +08:00
private const double UnityReadyTimeoutSeconds = 180.0;
Async Test Infrastructure & Editor Readiness Status + new refresh_unity tool (#507) * Add editor readiness v2, refresh tool, and preflight guards * Detect external package changes and harden refresh retry * feat: add TestRunnerNoThrottle and async test running with background stall prevention - Add TestRunnerNoThrottle.cs: Sets editor to 'No Throttling' mode during test runs with SessionState persistence across domain reload - Add run_tests_async and get_test_job tools for non-blocking test execution - Add TestJobManager for async test job tracking with progress monitoring - Add ForceSynchronousImport to all AssetDatabase.Refresh() calls to prevent stalls - Mark DomainReloadResilienceTests as [Explicit] with documentation explaining the test infrastructure limitation (internal coroutine waits vs MCP socket polling) - MCP workflow is unaffected - socket messages provide external stimulus that keeps Unity responsive even when backgrounded * refactor: simplify and clean up code - Remove unused Newtonsoft.Json.Linq import from TestJobManager - Add throttling to SessionState persistence (once per second) to reduce overhead - Critical job state changes (start/finish) still persist immediately - Fix duplicate XML summary tag in DomainReloadResilienceTests * docs: add async test tools to README, document domain reload limitation - Add run_tests_async and get_test_job to main README tools list - Document background stall limitation for domain reload tests in DEV readme * ci: add separate job for domain reload tests Run [Explicit] domain_reload tests in their own job using -testCategory * ci: run domain reload tests in same job as regular tests Combines into single job with two test steps to reuse cached Library * fix: address coderabbit review issues - Fix TOCTOU race in TestJobManager.StartJob (single lock scope for check-and-set) - Store TestRunnerApi reference with HideAndDontSave to prevent GC/serialization issues * docs: update tool descriptions to prefer run_tests_async - run_tests_async is now marked as preferred for long-running suites - run_tests description notes it blocks and suggests async alternative * docs: update README screenshot to v8.6 UI * docs: add v8.6 UI screenshot * Update README for MCP version and instructions for v8.7 * fix: handle preflight busy signals and derive job status from test results - manage_asset, manage_gameobject, manage_scene now check preflight return value and propagate busy/retry signals to clients (fixes Sourcery #1) - TestJobManager.FinalizeCurrentJobFromRunFinished now sets job status to Failed when resultPayload.Failed > 0, not always Succeeded (fixes Sourcery #2) * fix: increase HTTP server startup timeout for dev mode When 'Force fresh server install' is enabled, uvx uses --no-cache --refresh which rebuilds the package and takes significantly longer to start. - Increase timeout from 10s to 45s when dev mode is enabled - Add informative log message explaining the longer startup time - Show actual timeout value in warning message * fix: derive job status from test results in FinalizeFromTask fallback Apply same logic as FinalizeCurrentJobFromRunFinished: check result.Failed > 0 to correctly mark jobs as Failed when tests fail, even in the fallback path when RunFinished callback is not delivered.
2026-01-04 04:42:32 +08:00
private string _runRoot;
private string _nestedFolder;
private string _createdAssetPath;
private string _createdGuid;
private string _matAPath;
private string _matBPath;
Feature/run tests summary clean (#501) * Optimize run_tests to return summary by default, reducing token usage by 98% - Add includeFailedTests parameter: returns only failed/skipped test details - Add includeDetails parameter: returns all test details (original behavior) - Default behavior now returns summary only (~150 tokens vs ~13k tokens) - Make results field optional in Python schema for backward compatibility Token savings: - Default: ~13k tokens saved (98.9% reduction) - With failures: minimal tokens (only non-passing tests) - Full details: same as before when explicitly requested This prevents context bloat for typical test runs where you only need pass/fail counts, while still allowing detailed debugging when needed. * Add warning when run_tests filters match no tests; fix test organization TDD Feature: - Add warning message when filter criteria match zero tests - New RunTestsTests.cs validates message formatting logic - Modified RunTests.cs to append "(No tests matched the specified filters)" when total=0 Test Organization Fixes: - Move MCPToolParameterTests.cs from EditMode/ to EditMode/Tools/ (matches folder hierarchy) - Fix inconsistent namespaces to MCPForUnityTests.Editor.{Subfolder}: - MCPToolParameterTests: Tests.EditMode → MCPForUnityTests.Editor.Tools - DomainReloadResilienceTests: Tests.EditMode.Tools → MCPForUnityTests.Editor.Tools - Matrix4x4ConverterTests: MCPForUnityTests.EditMode.Helpers → MCPForUnityTests.Editor.Helpers * Refactor test result message formatting * Simplify RunTests warning assertions * Tests: de-flake cold-start EditMode runs - Make ManageScriptableObjectTests setup yield-based with longer Unity-ready timeout - Mark DomainReloadResilienceTests explicit to avoid triggering domain reload during Run All
2026-01-02 12:36:45 +08:00
[UnitySetUp]
public IEnumerator SetUp()
{
Feature/run tests summary clean (#501) * Optimize run_tests to return summary by default, reducing token usage by 98% - Add includeFailedTests parameter: returns only failed/skipped test details - Add includeDetails parameter: returns all test details (original behavior) - Default behavior now returns summary only (~150 tokens vs ~13k tokens) - Make results field optional in Python schema for backward compatibility Token savings: - Default: ~13k tokens saved (98.9% reduction) - With failures: minimal tokens (only non-passing tests) - Full details: same as before when explicitly requested This prevents context bloat for typical test runs where you only need pass/fail counts, while still allowing detailed debugging when needed. * Add warning when run_tests filters match no tests; fix test organization TDD Feature: - Add warning message when filter criteria match zero tests - New RunTestsTests.cs validates message formatting logic - Modified RunTests.cs to append "(No tests matched the specified filters)" when total=0 Test Organization Fixes: - Move MCPToolParameterTests.cs from EditMode/ to EditMode/Tools/ (matches folder hierarchy) - Fix inconsistent namespaces to MCPForUnityTests.Editor.{Subfolder}: - MCPToolParameterTests: Tests.EditMode → MCPForUnityTests.Editor.Tools - DomainReloadResilienceTests: Tests.EditMode.Tools → MCPForUnityTests.Editor.Tools - Matrix4x4ConverterTests: MCPForUnityTests.EditMode.Helpers → MCPForUnityTests.Editor.Helpers * Refactor test result message formatting * Simplify RunTests warning assertions * Tests: de-flake cold-start EditMode runs - Make ManageScriptableObjectTests setup yield-based with longer Unity-ready timeout - Mark DomainReloadResilienceTests explicit to avoid triggering domain reload during Run All
2026-01-02 12:36:45 +08:00
yield return WaitForUnityReady(UnityReadyTimeoutSeconds);
EnsureFolder("Assets/Temp");
Async Test Infrastructure & Editor Readiness Status + new refresh_unity tool (#507) * Add editor readiness v2, refresh tool, and preflight guards * Detect external package changes and harden refresh retry * feat: add TestRunnerNoThrottle and async test running with background stall prevention - Add TestRunnerNoThrottle.cs: Sets editor to 'No Throttling' mode during test runs with SessionState persistence across domain reload - Add run_tests_async and get_test_job tools for non-blocking test execution - Add TestJobManager for async test job tracking with progress monitoring - Add ForceSynchronousImport to all AssetDatabase.Refresh() calls to prevent stalls - Mark DomainReloadResilienceTests as [Explicit] with documentation explaining the test infrastructure limitation (internal coroutine waits vs MCP socket polling) - MCP workflow is unaffected - socket messages provide external stimulus that keeps Unity responsive even when backgrounded * refactor: simplify and clean up code - Remove unused Newtonsoft.Json.Linq import from TestJobManager - Add throttling to SessionState persistence (once per second) to reduce overhead - Critical job state changes (start/finish) still persist immediately - Fix duplicate XML summary tag in DomainReloadResilienceTests * docs: add async test tools to README, document domain reload limitation - Add run_tests_async and get_test_job to main README tools list - Document background stall limitation for domain reload tests in DEV readme * ci: add separate job for domain reload tests Run [Explicit] domain_reload tests in their own job using -testCategory * ci: run domain reload tests in same job as regular tests Combines into single job with two test steps to reuse cached Library * fix: address coderabbit review issues - Fix TOCTOU race in TestJobManager.StartJob (single lock scope for check-and-set) - Store TestRunnerApi reference with HideAndDontSave to prevent GC/serialization issues * docs: update tool descriptions to prefer run_tests_async - run_tests_async is now marked as preferred for long-running suites - run_tests description notes it blocks and suggests async alternative * docs: update README screenshot to v8.6 UI * docs: add v8.6 UI screenshot * Update README for MCP version and instructions for v8.7 * fix: handle preflight busy signals and derive job status from test results - manage_asset, manage_gameobject, manage_scene now check preflight return value and propagate busy/retry signals to clients (fixes Sourcery #1) - TestJobManager.FinalizeCurrentJobFromRunFinished now sets job status to Failed when resultPayload.Failed > 0, not always Succeeded (fixes Sourcery #2) * fix: increase HTTP server startup timeout for dev mode When 'Force fresh server install' is enabled, uvx uses --no-cache --refresh which rebuilds the package and takes significantly longer to start. - Increase timeout from 10s to 45s when dev mode is enabled - Add informative log message explaining the longer startup time - Show actual timeout value in warning message * fix: derive job status from test results in FinalizeFromTask fallback Apply same logic as FinalizeCurrentJobFromRunFinished: check result.Failed > 0 to correctly mark jobs as Failed when tests fail, even in the fallback path when RunFinished callback is not delivered.
2026-01-04 04:42:32 +08:00
// Avoid deleting/recreating the entire TempRoot each test (can trigger heavy reimport churn).
// Instead, isolate each test in its own unique subfolder under TempRoot.
EnsureFolder(TempRoot);
Async Test Infrastructure & Editor Readiness Status + new refresh_unity tool (#507) * Add editor readiness v2, refresh tool, and preflight guards * Detect external package changes and harden refresh retry * feat: add TestRunnerNoThrottle and async test running with background stall prevention - Add TestRunnerNoThrottle.cs: Sets editor to 'No Throttling' mode during test runs with SessionState persistence across domain reload - Add run_tests_async and get_test_job tools for non-blocking test execution - Add TestJobManager for async test job tracking with progress monitoring - Add ForceSynchronousImport to all AssetDatabase.Refresh() calls to prevent stalls - Mark DomainReloadResilienceTests as [Explicit] with documentation explaining the test infrastructure limitation (internal coroutine waits vs MCP socket polling) - MCP workflow is unaffected - socket messages provide external stimulus that keeps Unity responsive even when backgrounded * refactor: simplify and clean up code - Remove unused Newtonsoft.Json.Linq import from TestJobManager - Add throttling to SessionState persistence (once per second) to reduce overhead - Critical job state changes (start/finish) still persist immediately - Fix duplicate XML summary tag in DomainReloadResilienceTests * docs: add async test tools to README, document domain reload limitation - Add run_tests_async and get_test_job to main README tools list - Document background stall limitation for domain reload tests in DEV readme * ci: add separate job for domain reload tests Run [Explicit] domain_reload tests in their own job using -testCategory * ci: run domain reload tests in same job as regular tests Combines into single job with two test steps to reuse cached Library * fix: address coderabbit review issues - Fix TOCTOU race in TestJobManager.StartJob (single lock scope for check-and-set) - Store TestRunnerApi reference with HideAndDontSave to prevent GC/serialization issues * docs: update tool descriptions to prefer run_tests_async - run_tests_async is now marked as preferred for long-running suites - run_tests description notes it blocks and suggests async alternative * docs: update README screenshot to v8.6 UI * docs: add v8.6 UI screenshot * Update README for MCP version and instructions for v8.7 * fix: handle preflight busy signals and derive job status from test results - manage_asset, manage_gameobject, manage_scene now check preflight return value and propagate busy/retry signals to clients (fixes Sourcery #1) - TestJobManager.FinalizeCurrentJobFromRunFinished now sets job status to Failed when resultPayload.Failed > 0, not always Succeeded (fixes Sourcery #2) * fix: increase HTTP server startup timeout for dev mode When 'Force fresh server install' is enabled, uvx uses --no-cache --refresh which rebuilds the package and takes significantly longer to start. - Increase timeout from 10s to 45s when dev mode is enabled - Add informative log message explaining the longer startup time - Show actual timeout value in warning message * fix: derive job status from test results in FinalizeFromTask fallback Apply same logic as FinalizeCurrentJobFromRunFinished: check result.Failed > 0 to correctly mark jobs as Failed when tests fail, even in the fallback path when RunFinished callback is not delivered.
2026-01-04 04:42:32 +08:00
_runRoot = $"{TempRoot}/Run_{Guid.NewGuid():N}";
EnsureFolder(_runRoot);
_nestedFolder = _runRoot + "/Nested/Deeper";
_createdAssetPath = null;
_createdGuid = null;
// Create two Materials we can reference by guid/path.
_matAPath = $"{TempRoot}/MatA_{Guid.NewGuid():N}.mat";
_matBPath = $"{TempRoot}/MatB_{Guid.NewGuid():N}.mat";
Harden `manage_scriptable_object` Tool (#522) * feat(manage_scriptable_object): harden tool with path normalization, auto-resize, bulk mapping Phase 1: Path Syntax & Auto-Resizing - Add NormalizePropertyPath() to convert field[index] to Array.data format - Add EnsureArrayCapacity() to auto-grow arrays when targeting out-of-bounds indices Phase 2: Consolidation - Replace duplicate TryGet* helpers with ParamCoercion/VectorParsing shared utilities - Add Vector4 parsing support to VectorParsing.cs Phase 3: Bulk Data Mapping - Handle JArray values for list/array properties (recursive element setting) - Handle JObject values for nested struct/class properties Phase 4: Enhanced Reference Resolution - Support plain 32-char GUID strings for ObjectReference fields Phase 5: Validation & Dry-Run - Add ValidatePatches() for pre-validation of all patches - Add dry_run parameter to validate without mutating Includes comprehensive stress test suite covering: - Big Bang (large nested arrays), Out of Bounds, Friendly Path Syntax - Deep Nesting, Mixed References, Rapid Fire, Type Mismatch - Bulk Array Mapping, GUID Shorthand, Dry Run validation * feat: Add AnimationCurve and Quaternion support to manage_scriptable_object tool - Implement TrySetAnimationCurve() supporting both {'keys': [...]} and direct [...] formats * Support keyframe properties: time, value, inSlope, outSlope, weightedMode, inWeight, outWeight * Gracefully default missing optional fields to 0 * Clear error messages for malformed structures - Implement TrySetQuaternion() with 4 input formats: * Euler array [x, y, z] - 3 elements interpreted as degrees * Raw array [x, y, z, w] - 4 components * Object format {x, y, z, w} - explicit components * Explicit euler {euler: [x, y, z]} - labeled format - Improve error handling: * Null values: AnimationCurve→empty, Quaternion→identity * Invalid inputs rejected with specific, actionable error messages * Validate keyframe objects and array sizes - Add comprehensive test coverage in ManageScriptableObjectStressTests.cs: * AnimationCurve with keyframe array format * AnimationCurve with direct array (no wrapper) * Quaternion via Euler angles * Quaternion via raw components * Quaternion via object format * Quaternion via explicit euler property - Fix test file compilation issues: * Replace undefined TestFolder with _runRoot * Add System.IO using statement * refactor: consolidate test utilities to eliminate duplication - Add TestUtilities.cs with shared helpers: - ToJObject() - consolidates 11 duplicates across test files - EnsureFolder() - consolidates 2 duplicates - WaitForUnityReady() - consolidates 2 duplicates - FindFallbackShader() - consolidates shader chain duplicates - SafeDeleteAsset() - helper for asset cleanup - CleanupEmptyParentFolders() - standardizes TearDown cleanup - Update 11 test files to use shared TestUtilities via 'using static' - Standardize TearDown cleanup patterns across all test files - Net reduction of ~40 lines while improving maintainability * fix: add missing animCurve and rotation fields to ComplexStressSO Add AnimationCurve and Quaternion fields required by Phase 6 stress tests.
2026-01-07 22:46:35 +08:00
var shader = FindFallbackShader();
Assert.IsNotNull(shader, "A fallback shader must be available for creating Material assets in tests.");
AssetDatabase.CreateAsset(new Material(shader), _matAPath);
AssetDatabase.CreateAsset(new Material(shader), _matBPath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
Feature/run tests summary clean (#501) * Optimize run_tests to return summary by default, reducing token usage by 98% - Add includeFailedTests parameter: returns only failed/skipped test details - Add includeDetails parameter: returns all test details (original behavior) - Default behavior now returns summary only (~150 tokens vs ~13k tokens) - Make results field optional in Python schema for backward compatibility Token savings: - Default: ~13k tokens saved (98.9% reduction) - With failures: minimal tokens (only non-passing tests) - Full details: same as before when explicitly requested This prevents context bloat for typical test runs where you only need pass/fail counts, while still allowing detailed debugging when needed. * Add warning when run_tests filters match no tests; fix test organization TDD Feature: - Add warning message when filter criteria match zero tests - New RunTestsTests.cs validates message formatting logic - Modified RunTests.cs to append "(No tests matched the specified filters)" when total=0 Test Organization Fixes: - Move MCPToolParameterTests.cs from EditMode/ to EditMode/Tools/ (matches folder hierarchy) - Fix inconsistent namespaces to MCPForUnityTests.Editor.{Subfolder}: - MCPToolParameterTests: Tests.EditMode → MCPForUnityTests.Editor.Tools - DomainReloadResilienceTests: Tests.EditMode.Tools → MCPForUnityTests.Editor.Tools - Matrix4x4ConverterTests: MCPForUnityTests.EditMode.Helpers → MCPForUnityTests.Editor.Helpers * Refactor test result message formatting * Simplify RunTests warning assertions * Tests: de-flake cold-start EditMode runs - Make ManageScriptableObjectTests setup yield-based with longer Unity-ready timeout - Mark DomainReloadResilienceTests explicit to avoid triggering domain reload during Run All
2026-01-02 12:36:45 +08:00
yield return WaitForUnityReady(UnityReadyTimeoutSeconds);
}
[TearDown]
public void TearDown()
{
// Best-effort cleanup
if (!string.IsNullOrEmpty(_createdAssetPath) && AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(_createdAssetPath) != null)
{
AssetDatabase.DeleteAsset(_createdAssetPath);
}
if (!string.IsNullOrEmpty(_matAPath) && AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(_matAPath) != null)
{
AssetDatabase.DeleteAsset(_matAPath);
}
if (!string.IsNullOrEmpty(_matBPath) && AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(_matBPath) != null)
{
AssetDatabase.DeleteAsset(_matBPath);
}
Async Test Infrastructure & Editor Readiness Status + new refresh_unity tool (#507) * Add editor readiness v2, refresh tool, and preflight guards * Detect external package changes and harden refresh retry * feat: add TestRunnerNoThrottle and async test running with background stall prevention - Add TestRunnerNoThrottle.cs: Sets editor to 'No Throttling' mode during test runs with SessionState persistence across domain reload - Add run_tests_async and get_test_job tools for non-blocking test execution - Add TestJobManager for async test job tracking with progress monitoring - Add ForceSynchronousImport to all AssetDatabase.Refresh() calls to prevent stalls - Mark DomainReloadResilienceTests as [Explicit] with documentation explaining the test infrastructure limitation (internal coroutine waits vs MCP socket polling) - MCP workflow is unaffected - socket messages provide external stimulus that keeps Unity responsive even when backgrounded * refactor: simplify and clean up code - Remove unused Newtonsoft.Json.Linq import from TestJobManager - Add throttling to SessionState persistence (once per second) to reduce overhead - Critical job state changes (start/finish) still persist immediately - Fix duplicate XML summary tag in DomainReloadResilienceTests * docs: add async test tools to README, document domain reload limitation - Add run_tests_async and get_test_job to main README tools list - Document background stall limitation for domain reload tests in DEV readme * ci: add separate job for domain reload tests Run [Explicit] domain_reload tests in their own job using -testCategory * ci: run domain reload tests in same job as regular tests Combines into single job with two test steps to reuse cached Library * fix: address coderabbit review issues - Fix TOCTOU race in TestJobManager.StartJob (single lock scope for check-and-set) - Store TestRunnerApi reference with HideAndDontSave to prevent GC/serialization issues * docs: update tool descriptions to prefer run_tests_async - run_tests_async is now marked as preferred for long-running suites - run_tests description notes it blocks and suggests async alternative * docs: update README screenshot to v8.6 UI * docs: add v8.6 UI screenshot * Update README for MCP version and instructions for v8.7 * fix: handle preflight busy signals and derive job status from test results - manage_asset, manage_gameobject, manage_scene now check preflight return value and propagate busy/retry signals to clients (fixes Sourcery #1) - TestJobManager.FinalizeCurrentJobFromRunFinished now sets job status to Failed when resultPayload.Failed > 0, not always Succeeded (fixes Sourcery #2) * fix: increase HTTP server startup timeout for dev mode When 'Force fresh server install' is enabled, uvx uses --no-cache --refresh which rebuilds the package and takes significantly longer to start. - Increase timeout from 10s to 45s when dev mode is enabled - Add informative log message explaining the longer startup time - Show actual timeout value in warning message * fix: derive job status from test results in FinalizeFromTask fallback Apply same logic as FinalizeCurrentJobFromRunFinished: check result.Failed > 0 to correctly mark jobs as Failed when tests fail, even in the fallback path when RunFinished callback is not delivered.
2026-01-04 04:42:32 +08:00
if (!string.IsNullOrEmpty(_runRoot) && AssetDatabase.IsValidFolder(_runRoot))
{
Async Test Infrastructure & Editor Readiness Status + new refresh_unity tool (#507) * Add editor readiness v2, refresh tool, and preflight guards * Detect external package changes and harden refresh retry * feat: add TestRunnerNoThrottle and async test running with background stall prevention - Add TestRunnerNoThrottle.cs: Sets editor to 'No Throttling' mode during test runs with SessionState persistence across domain reload - Add run_tests_async and get_test_job tools for non-blocking test execution - Add TestJobManager for async test job tracking with progress monitoring - Add ForceSynchronousImport to all AssetDatabase.Refresh() calls to prevent stalls - Mark DomainReloadResilienceTests as [Explicit] with documentation explaining the test infrastructure limitation (internal coroutine waits vs MCP socket polling) - MCP workflow is unaffected - socket messages provide external stimulus that keeps Unity responsive even when backgrounded * refactor: simplify and clean up code - Remove unused Newtonsoft.Json.Linq import from TestJobManager - Add throttling to SessionState persistence (once per second) to reduce overhead - Critical job state changes (start/finish) still persist immediately - Fix duplicate XML summary tag in DomainReloadResilienceTests * docs: add async test tools to README, document domain reload limitation - Add run_tests_async and get_test_job to main README tools list - Document background stall limitation for domain reload tests in DEV readme * ci: add separate job for domain reload tests Run [Explicit] domain_reload tests in their own job using -testCategory * ci: run domain reload tests in same job as regular tests Combines into single job with two test steps to reuse cached Library * fix: address coderabbit review issues - Fix TOCTOU race in TestJobManager.StartJob (single lock scope for check-and-set) - Store TestRunnerApi reference with HideAndDontSave to prevent GC/serialization issues * docs: update tool descriptions to prefer run_tests_async - run_tests_async is now marked as preferred for long-running suites - run_tests description notes it blocks and suggests async alternative * docs: update README screenshot to v8.6 UI * docs: add v8.6 UI screenshot * Update README for MCP version and instructions for v8.7 * fix: handle preflight busy signals and derive job status from test results - manage_asset, manage_gameobject, manage_scene now check preflight return value and propagate busy/retry signals to clients (fixes Sourcery #1) - TestJobManager.FinalizeCurrentJobFromRunFinished now sets job status to Failed when resultPayload.Failed > 0, not always Succeeded (fixes Sourcery #2) * fix: increase HTTP server startup timeout for dev mode When 'Force fresh server install' is enabled, uvx uses --no-cache --refresh which rebuilds the package and takes significantly longer to start. - Increase timeout from 10s to 45s when dev mode is enabled - Add informative log message explaining the longer startup time - Show actual timeout value in warning message * fix: derive job status from test results in FinalizeFromTask fallback Apply same logic as FinalizeCurrentJobFromRunFinished: check result.Failed > 0 to correctly mark jobs as Failed when tests fail, even in the fallback path when RunFinished callback is not delivered.
2026-01-04 04:42:32 +08:00
AssetDatabase.DeleteAsset(_runRoot);
}
Harden `manage_scriptable_object` Tool (#522) * feat(manage_scriptable_object): harden tool with path normalization, auto-resize, bulk mapping Phase 1: Path Syntax & Auto-Resizing - Add NormalizePropertyPath() to convert field[index] to Array.data format - Add EnsureArrayCapacity() to auto-grow arrays when targeting out-of-bounds indices Phase 2: Consolidation - Replace duplicate TryGet* helpers with ParamCoercion/VectorParsing shared utilities - Add Vector4 parsing support to VectorParsing.cs Phase 3: Bulk Data Mapping - Handle JArray values for list/array properties (recursive element setting) - Handle JObject values for nested struct/class properties Phase 4: Enhanced Reference Resolution - Support plain 32-char GUID strings for ObjectReference fields Phase 5: Validation & Dry-Run - Add ValidatePatches() for pre-validation of all patches - Add dry_run parameter to validate without mutating Includes comprehensive stress test suite covering: - Big Bang (large nested arrays), Out of Bounds, Friendly Path Syntax - Deep Nesting, Mixed References, Rapid Fire, Type Mismatch - Bulk Array Mapping, GUID Shorthand, Dry Run validation * feat: Add AnimationCurve and Quaternion support to manage_scriptable_object tool - Implement TrySetAnimationCurve() supporting both {'keys': [...]} and direct [...] formats * Support keyframe properties: time, value, inSlope, outSlope, weightedMode, inWeight, outWeight * Gracefully default missing optional fields to 0 * Clear error messages for malformed structures - Implement TrySetQuaternion() with 4 input formats: * Euler array [x, y, z] - 3 elements interpreted as degrees * Raw array [x, y, z, w] - 4 components * Object format {x, y, z, w} - explicit components * Explicit euler {euler: [x, y, z]} - labeled format - Improve error handling: * Null values: AnimationCurve→empty, Quaternion→identity * Invalid inputs rejected with specific, actionable error messages * Validate keyframe objects and array sizes - Add comprehensive test coverage in ManageScriptableObjectStressTests.cs: * AnimationCurve with keyframe array format * AnimationCurve with direct array (no wrapper) * Quaternion via Euler angles * Quaternion via raw components * Quaternion via object format * Quaternion via explicit euler property - Fix test file compilation issues: * Replace undefined TestFolder with _runRoot * Add System.IO using statement * refactor: consolidate test utilities to eliminate duplication - Add TestUtilities.cs with shared helpers: - ToJObject() - consolidates 11 duplicates across test files - EnsureFolder() - consolidates 2 duplicates - WaitForUnityReady() - consolidates 2 duplicates - FindFallbackShader() - consolidates shader chain duplicates - SafeDeleteAsset() - helper for asset cleanup - CleanupEmptyParentFolders() - standardizes TearDown cleanup - Update 11 test files to use shared TestUtilities via 'using static' - Standardize TearDown cleanup patterns across all test files - Net reduction of ~40 lines while improving maintainability * fix: add missing animCurve and rotation fields to ComplexStressSO Add AnimationCurve and Quaternion fields required by Phase 6 stress tests.
2026-01-07 22:46:35 +08:00
// Clean up empty parent folders to avoid debris
CleanupEmptyParentFolders(TempRoot);
AssetDatabase.Refresh();
}
[Test]
Async Test Infrastructure & Editor Readiness Status + new refresh_unity tool (#507) * Add editor readiness v2, refresh tool, and preflight guards * Detect external package changes and harden refresh retry * feat: add TestRunnerNoThrottle and async test running with background stall prevention - Add TestRunnerNoThrottle.cs: Sets editor to 'No Throttling' mode during test runs with SessionState persistence across domain reload - Add run_tests_async and get_test_job tools for non-blocking test execution - Add TestJobManager for async test job tracking with progress monitoring - Add ForceSynchronousImport to all AssetDatabase.Refresh() calls to prevent stalls - Mark DomainReloadResilienceTests as [Explicit] with documentation explaining the test infrastructure limitation (internal coroutine waits vs MCP socket polling) - MCP workflow is unaffected - socket messages provide external stimulus that keeps Unity responsive even when backgrounded * refactor: simplify and clean up code - Remove unused Newtonsoft.Json.Linq import from TestJobManager - Add throttling to SessionState persistence (once per second) to reduce overhead - Critical job state changes (start/finish) still persist immediately - Fix duplicate XML summary tag in DomainReloadResilienceTests * docs: add async test tools to README, document domain reload limitation - Add run_tests_async and get_test_job to main README tools list - Document background stall limitation for domain reload tests in DEV readme * ci: add separate job for domain reload tests Run [Explicit] domain_reload tests in their own job using -testCategory * ci: run domain reload tests in same job as regular tests Combines into single job with two test steps to reuse cached Library * fix: address coderabbit review issues - Fix TOCTOU race in TestJobManager.StartJob (single lock scope for check-and-set) - Store TestRunnerApi reference with HideAndDontSave to prevent GC/serialization issues * docs: update tool descriptions to prefer run_tests_async - run_tests_async is now marked as preferred for long-running suites - run_tests description notes it blocks and suggests async alternative * docs: update README screenshot to v8.6 UI * docs: add v8.6 UI screenshot * Update README for MCP version and instructions for v8.7 * fix: handle preflight busy signals and derive job status from test results - manage_asset, manage_gameobject, manage_scene now check preflight return value and propagate busy/retry signals to clients (fixes Sourcery #1) - TestJobManager.FinalizeCurrentJobFromRunFinished now sets job status to Failed when resultPayload.Failed > 0, not always Succeeded (fixes Sourcery #2) * fix: increase HTTP server startup timeout for dev mode When 'Force fresh server install' is enabled, uvx uses --no-cache --refresh which rebuilds the package and takes significantly longer to start. - Increase timeout from 10s to 45s when dev mode is enabled - Add informative log message explaining the longer startup time - Show actual timeout value in warning message * fix: derive job status from test results in FinalizeFromTask fallback Apply same logic as FinalizeCurrentJobFromRunFinished: check result.Failed > 0 to correctly mark jobs as Failed when tests fail, even in the fallback path when RunFinished callback is not delivered.
2026-01-04 04:42:32 +08:00
public void Create_CreatesNestedFolders_PlacesAssetCorrectly()
{
var create = new JObject
{
["action"] = "create",
["typeName"] = typeof(ManageScriptableObjectTestDefinition).FullName,
Async Test Infrastructure & Editor Readiness Status + new refresh_unity tool (#507) * Add editor readiness v2, refresh tool, and preflight guards * Detect external package changes and harden refresh retry * feat: add TestRunnerNoThrottle and async test running with background stall prevention - Add TestRunnerNoThrottle.cs: Sets editor to 'No Throttling' mode during test runs with SessionState persistence across domain reload - Add run_tests_async and get_test_job tools for non-blocking test execution - Add TestJobManager for async test job tracking with progress monitoring - Add ForceSynchronousImport to all AssetDatabase.Refresh() calls to prevent stalls - Mark DomainReloadResilienceTests as [Explicit] with documentation explaining the test infrastructure limitation (internal coroutine waits vs MCP socket polling) - MCP workflow is unaffected - socket messages provide external stimulus that keeps Unity responsive even when backgrounded * refactor: simplify and clean up code - Remove unused Newtonsoft.Json.Linq import from TestJobManager - Add throttling to SessionState persistence (once per second) to reduce overhead - Critical job state changes (start/finish) still persist immediately - Fix duplicate XML summary tag in DomainReloadResilienceTests * docs: add async test tools to README, document domain reload limitation - Add run_tests_async and get_test_job to main README tools list - Document background stall limitation for domain reload tests in DEV readme * ci: add separate job for domain reload tests Run [Explicit] domain_reload tests in their own job using -testCategory * ci: run domain reload tests in same job as regular tests Combines into single job with two test steps to reuse cached Library * fix: address coderabbit review issues - Fix TOCTOU race in TestJobManager.StartJob (single lock scope for check-and-set) - Store TestRunnerApi reference with HideAndDontSave to prevent GC/serialization issues * docs: update tool descriptions to prefer run_tests_async - run_tests_async is now marked as preferred for long-running suites - run_tests description notes it blocks and suggests async alternative * docs: update README screenshot to v8.6 UI * docs: add v8.6 UI screenshot * Update README for MCP version and instructions for v8.7 * fix: handle preflight busy signals and derive job status from test results - manage_asset, manage_gameobject, manage_scene now check preflight return value and propagate busy/retry signals to clients (fixes Sourcery #1) - TestJobManager.FinalizeCurrentJobFromRunFinished now sets job status to Failed when resultPayload.Failed > 0, not always Succeeded (fixes Sourcery #2) * fix: increase HTTP server startup timeout for dev mode When 'Force fresh server install' is enabled, uvx uses --no-cache --refresh which rebuilds the package and takes significantly longer to start. - Increase timeout from 10s to 45s when dev mode is enabled - Add informative log message explaining the longer startup time - Show actual timeout value in warning message * fix: derive job status from test results in FinalizeFromTask fallback Apply same logic as FinalizeCurrentJobFromRunFinished: check result.Failed > 0 to correctly mark jobs as Failed when tests fail, even in the fallback path when RunFinished callback is not delivered.
2026-01-04 04:42:32 +08:00
["folderPath"] = _nestedFolder,
["assetName"] = "My_Test_Def_Placement",
["overwrite"] = true,
};
var raw = ManageScriptableObject.HandleCommand(create);
var result = raw as JObject ?? JObject.FromObject(raw);
Assert.IsTrue(result.Value<bool>("success"), result.ToString());
var data = result["data"] as JObject;
Assert.IsNotNull(data, "Expected data payload");
_createdGuid = data!["guid"]?.ToString();
_createdAssetPath = data["path"]?.ToString();
Assert.IsTrue(AssetDatabase.IsValidFolder(_nestedFolder), "Nested folder should be created.");
Assert.IsTrue(_createdAssetPath!.StartsWith(_nestedFolder, StringComparison.Ordinal), $"Asset should be created under {_nestedFolder}: {_createdAssetPath}");
Assert.IsTrue(_createdAssetPath.EndsWith(".asset", StringComparison.OrdinalIgnoreCase), "Asset should have .asset extension.");
Assert.IsFalse(string.IsNullOrWhiteSpace(_createdGuid), "Expected guid in response.");
var asset = AssetDatabase.LoadAssetAtPath<ManageScriptableObjectTestDefinition>(_createdAssetPath);
Assert.IsNotNull(asset, "Created asset should load as TestDefinition.");
}
[Test]
public void Create_AppliesPatches_ToCreatedAsset()
{
var create = new JObject
{
["action"] = "create",
["typeName"] = typeof(ManageScriptableObjectTestDefinition).FullName,
// Patching correctness does not depend on nested folder creation; keep this lightweight.
["folderPath"] = _runRoot,
["assetName"] = "My_Test_Def_Patches",
["overwrite"] = true,
["patches"] = new JArray
{
new JObject { ["propertyPath"] = "displayName", ["op"] = "set", ["value"] = "Hello" },
new JObject { ["propertyPath"] = "baseNumber", ["op"] = "set", ["value"] = 42 },
new JObject { ["propertyPath"] = "nested.note", ["op"] = "set", ["value"] = "note!" }
}
};
var raw = ManageScriptableObject.HandleCommand(create);
var result = raw as JObject ?? JObject.FromObject(raw);
Assert.IsTrue(result.Value<bool>("success"), result.ToString());
Async Test Infrastructure & Editor Readiness Status + new refresh_unity tool (#507) * Add editor readiness v2, refresh tool, and preflight guards * Detect external package changes and harden refresh retry * feat: add TestRunnerNoThrottle and async test running with background stall prevention - Add TestRunnerNoThrottle.cs: Sets editor to 'No Throttling' mode during test runs with SessionState persistence across domain reload - Add run_tests_async and get_test_job tools for non-blocking test execution - Add TestJobManager for async test job tracking with progress monitoring - Add ForceSynchronousImport to all AssetDatabase.Refresh() calls to prevent stalls - Mark DomainReloadResilienceTests as [Explicit] with documentation explaining the test infrastructure limitation (internal coroutine waits vs MCP socket polling) - MCP workflow is unaffected - socket messages provide external stimulus that keeps Unity responsive even when backgrounded * refactor: simplify and clean up code - Remove unused Newtonsoft.Json.Linq import from TestJobManager - Add throttling to SessionState persistence (once per second) to reduce overhead - Critical job state changes (start/finish) still persist immediately - Fix duplicate XML summary tag in DomainReloadResilienceTests * docs: add async test tools to README, document domain reload limitation - Add run_tests_async and get_test_job to main README tools list - Document background stall limitation for domain reload tests in DEV readme * ci: add separate job for domain reload tests Run [Explicit] domain_reload tests in their own job using -testCategory * ci: run domain reload tests in same job as regular tests Combines into single job with two test steps to reuse cached Library * fix: address coderabbit review issues - Fix TOCTOU race in TestJobManager.StartJob (single lock scope for check-and-set) - Store TestRunnerApi reference with HideAndDontSave to prevent GC/serialization issues * docs: update tool descriptions to prefer run_tests_async - run_tests_async is now marked as preferred for long-running suites - run_tests description notes it blocks and suggests async alternative * docs: update README screenshot to v8.6 UI * docs: add v8.6 UI screenshot * Update README for MCP version and instructions for v8.7 * fix: handle preflight busy signals and derive job status from test results - manage_asset, manage_gameobject, manage_scene now check preflight return value and propagate busy/retry signals to clients (fixes Sourcery #1) - TestJobManager.FinalizeCurrentJobFromRunFinished now sets job status to Failed when resultPayload.Failed > 0, not always Succeeded (fixes Sourcery #2) * fix: increase HTTP server startup timeout for dev mode When 'Force fresh server install' is enabled, uvx uses --no-cache --refresh which rebuilds the package and takes significantly longer to start. - Increase timeout from 10s to 45s when dev mode is enabled - Add informative log message explaining the longer startup time - Show actual timeout value in warning message * fix: derive job status from test results in FinalizeFromTask fallback Apply same logic as FinalizeCurrentJobFromRunFinished: check result.Failed > 0 to correctly mark jobs as Failed when tests fail, even in the fallback path when RunFinished callback is not delivered.
2026-01-04 04:42:32 +08:00
var data = result["data"] as JObject;
Assert.IsNotNull(data, "Expected data payload");
_createdGuid = data!["guid"]?.ToString();
_createdAssetPath = data["path"]?.ToString();
Async Test Infrastructure & Editor Readiness Status + new refresh_unity tool (#507) * Add editor readiness v2, refresh tool, and preflight guards * Detect external package changes and harden refresh retry * feat: add TestRunnerNoThrottle and async test running with background stall prevention - Add TestRunnerNoThrottle.cs: Sets editor to 'No Throttling' mode during test runs with SessionState persistence across domain reload - Add run_tests_async and get_test_job tools for non-blocking test execution - Add TestJobManager for async test job tracking with progress monitoring - Add ForceSynchronousImport to all AssetDatabase.Refresh() calls to prevent stalls - Mark DomainReloadResilienceTests as [Explicit] with documentation explaining the test infrastructure limitation (internal coroutine waits vs MCP socket polling) - MCP workflow is unaffected - socket messages provide external stimulus that keeps Unity responsive even when backgrounded * refactor: simplify and clean up code - Remove unused Newtonsoft.Json.Linq import from TestJobManager - Add throttling to SessionState persistence (once per second) to reduce overhead - Critical job state changes (start/finish) still persist immediately - Fix duplicate XML summary tag in DomainReloadResilienceTests * docs: add async test tools to README, document domain reload limitation - Add run_tests_async and get_test_job to main README tools list - Document background stall limitation for domain reload tests in DEV readme * ci: add separate job for domain reload tests Run [Explicit] domain_reload tests in their own job using -testCategory * ci: run domain reload tests in same job as regular tests Combines into single job with two test steps to reuse cached Library * fix: address coderabbit review issues - Fix TOCTOU race in TestJobManager.StartJob (single lock scope for check-and-set) - Store TestRunnerApi reference with HideAndDontSave to prevent GC/serialization issues * docs: update tool descriptions to prefer run_tests_async - run_tests_async is now marked as preferred for long-running suites - run_tests description notes it blocks and suggests async alternative * docs: update README screenshot to v8.6 UI * docs: add v8.6 UI screenshot * Update README for MCP version and instructions for v8.7 * fix: handle preflight busy signals and derive job status from test results - manage_asset, manage_gameobject, manage_scene now check preflight return value and propagate busy/retry signals to clients (fixes Sourcery #1) - TestJobManager.FinalizeCurrentJobFromRunFinished now sets job status to Failed when resultPayload.Failed > 0, not always Succeeded (fixes Sourcery #2) * fix: increase HTTP server startup timeout for dev mode When 'Force fresh server install' is enabled, uvx uses --no-cache --refresh which rebuilds the package and takes significantly longer to start. - Increase timeout from 10s to 45s when dev mode is enabled - Add informative log message explaining the longer startup time - Show actual timeout value in warning message * fix: derive job status from test results in FinalizeFromTask fallback Apply same logic as FinalizeCurrentJobFromRunFinished: check result.Failed > 0 to correctly mark jobs as Failed when tests fail, even in the fallback path when RunFinished callback is not delivered.
2026-01-04 04:42:32 +08:00
Assert.IsTrue(_createdAssetPath!.StartsWith(_runRoot, StringComparison.Ordinal), $"Asset should be created under {_runRoot}: {_createdAssetPath}");
Assert.IsFalse(string.IsNullOrWhiteSpace(_createdGuid), "Expected guid in response.");
var asset = AssetDatabase.LoadAssetAtPath<ManageScriptableObjectTestDefinition>(_createdAssetPath);
Assert.IsNotNull(asset, "Created asset should load as TestDefinition.");
Assert.AreEqual("Hello", asset!.DisplayName, "Private [SerializeField] string should be set via SerializedProperty.");
Assert.AreEqual(42, asset.BaseNumber, "Inherited serialized field should be set via SerializedProperty.");
Assert.AreEqual("note!", asset.NestedNote, "Nested struct field should be set via SerializedProperty path.");
}
[Test]
public void Modify_ArrayResize_ThenAssignObjectRefs_ByGuidAndByPath()
{
// Create base asset first with no patches.
var create = new JObject
{
["action"] = "create",
["typeName"] = typeof(ManageScriptableObjectTestDefinition).FullName,
Async Test Infrastructure & Editor Readiness Status + new refresh_unity tool (#507) * Add editor readiness v2, refresh tool, and preflight guards * Detect external package changes and harden refresh retry * feat: add TestRunnerNoThrottle and async test running with background stall prevention - Add TestRunnerNoThrottle.cs: Sets editor to 'No Throttling' mode during test runs with SessionState persistence across domain reload - Add run_tests_async and get_test_job tools for non-blocking test execution - Add TestJobManager for async test job tracking with progress monitoring - Add ForceSynchronousImport to all AssetDatabase.Refresh() calls to prevent stalls - Mark DomainReloadResilienceTests as [Explicit] with documentation explaining the test infrastructure limitation (internal coroutine waits vs MCP socket polling) - MCP workflow is unaffected - socket messages provide external stimulus that keeps Unity responsive even when backgrounded * refactor: simplify and clean up code - Remove unused Newtonsoft.Json.Linq import from TestJobManager - Add throttling to SessionState persistence (once per second) to reduce overhead - Critical job state changes (start/finish) still persist immediately - Fix duplicate XML summary tag in DomainReloadResilienceTests * docs: add async test tools to README, document domain reload limitation - Add run_tests_async and get_test_job to main README tools list - Document background stall limitation for domain reload tests in DEV readme * ci: add separate job for domain reload tests Run [Explicit] domain_reload tests in their own job using -testCategory * ci: run domain reload tests in same job as regular tests Combines into single job with two test steps to reuse cached Library * fix: address coderabbit review issues - Fix TOCTOU race in TestJobManager.StartJob (single lock scope for check-and-set) - Store TestRunnerApi reference with HideAndDontSave to prevent GC/serialization issues * docs: update tool descriptions to prefer run_tests_async - run_tests_async is now marked as preferred for long-running suites - run_tests description notes it blocks and suggests async alternative * docs: update README screenshot to v8.6 UI * docs: add v8.6 UI screenshot * Update README for MCP version and instructions for v8.7 * fix: handle preflight busy signals and derive job status from test results - manage_asset, manage_gameobject, manage_scene now check preflight return value and propagate busy/retry signals to clients (fixes Sourcery #1) - TestJobManager.FinalizeCurrentJobFromRunFinished now sets job status to Failed when resultPayload.Failed > 0, not always Succeeded (fixes Sourcery #2) * fix: increase HTTP server startup timeout for dev mode When 'Force fresh server install' is enabled, uvx uses --no-cache --refresh which rebuilds the package and takes significantly longer to start. - Increase timeout from 10s to 45s when dev mode is enabled - Add informative log message explaining the longer startup time - Show actual timeout value in warning message * fix: derive job status from test results in FinalizeFromTask fallback Apply same logic as FinalizeCurrentJobFromRunFinished: check result.Failed > 0 to correctly mark jobs as Failed when tests fail, even in the fallback path when RunFinished callback is not delivered.
2026-01-04 04:42:32 +08:00
["folderPath"] = _runRoot,
["assetName"] = "Modify_Target",
["overwrite"] = true
};
var createRes = ToJObject(ManageScriptableObject.HandleCommand(create));
Assert.IsTrue(createRes.Value<bool>("success"), createRes.ToString());
_createdGuid = createRes["data"]?["guid"]?.ToString();
_createdAssetPath = createRes["data"]?["path"]?.ToString();
var matAGuid = AssetDatabase.AssetPathToGUID(_matAPath);
var modify = new JObject
{
["action"] = "modify",
["target"] = new JObject { ["guid"] = _createdGuid },
["patches"] = new JArray
{
// Resize list to 2
new JObject { ["propertyPath"] = "materials.Array.size", ["op"] = "array_resize", ["value"] = 2 },
// Assign element 0 by guid
new JObject
{
["propertyPath"] = "materials.Array.data[0]",
["op"] = "set",
["ref"] = new JObject { ["guid"] = matAGuid }
},
// Assign element 1 by path
new JObject
{
["propertyPath"] = "materials.Array.data[1]",
["op"] = "set",
["ref"] = new JObject { ["path"] = _matBPath }
}
}
};
var modRes = ToJObject(ManageScriptableObject.HandleCommand(modify));
Assert.IsTrue(modRes.Value<bool>("success"), modRes.ToString());
// Assert patch results are ok so failures are visible even if the tool returns success.
var results = modRes["data"]?["results"] as JArray;
Assert.IsNotNull(results, "Expected per-patch results in response.");
foreach (var r in results!)
{
Assert.IsTrue(r.Value<bool>("ok"), $"Patch failed: {r}");
}
var asset = AssetDatabase.LoadAssetAtPath<ManageScriptableObjectTestDefinition>(_createdAssetPath);
Assert.IsNotNull(asset);
Assert.AreEqual(2, asset!.Materials.Count, "List should be resized to 2.");
var matA = AssetDatabase.LoadAssetAtPath<Material>(_matAPath);
var matB = AssetDatabase.LoadAssetAtPath<Material>(_matBPath);
Assert.AreEqual(matA, asset.Materials[0], "Element 0 should be set by GUID ref.");
Assert.AreEqual(matB, asset.Materials[1], "Element 1 should be set by path ref.");
}
[Test]
public void Errors_InvalidAction_TypeNotFound_TargetNotFound()
{
// invalid action
var badAction = ToJObject(ManageScriptableObject.HandleCommand(new JObject { ["action"] = "nope" }));
Assert.IsFalse(badAction.Value<bool>("success"));
Assert.AreEqual("invalid_params", badAction.Value<string>("error"));
// type not found
var badType = ToJObject(ManageScriptableObject.HandleCommand(new JObject
{
["action"] = "create",
["typeName"] = "Nope.MissingType",
["folderPath"] = TempRoot,
["assetName"] = "X",
}));
Assert.IsFalse(badType.Value<bool>("success"));
Assert.AreEqual("type_not_found", badType.Value<string>("error"));
// target not found
var badTarget = ToJObject(ManageScriptableObject.HandleCommand(new JObject
{
["action"] = "modify",
["target"] = new JObject { ["guid"] = "00000000000000000000000000000000" },
["patches"] = new JArray(),
}));
Assert.IsFalse(badTarget.Value<bool>("success"));
Assert.AreEqual("target_not_found", badTarget.Value<string>("error"));
}
[Test]
public void Create_RejectsNonAssetsRootFolders()
{
var badPackages = ToJObject(ManageScriptableObject.HandleCommand(new JObject
{
["action"] = "create",
["typeName"] = typeof(ManageScriptableObjectTestDefinition).FullName,
["folderPath"] = "Packages/NotAllowed",
["assetName"] = "BadFolder",
["overwrite"] = true,
}));
Assert.IsFalse(badPackages.Value<bool>("success"));
Assert.AreEqual("invalid_folder_path", badPackages.Value<string>("error"));
var badAbsolute = ToJObject(ManageScriptableObject.HandleCommand(new JObject
{
["action"] = "create",
["typeName"] = typeof(ManageScriptableObjectTestDefinition).FullName,
["folderPath"] = "/tmp/not_allowed",
["assetName"] = "BadFolder2",
["overwrite"] = true,
}));
Assert.IsFalse(badAbsolute.Value<bool>("success"));
Assert.AreEqual("invalid_folder_path", badAbsolute.Value<string>("error"));
var badFileUri = ToJObject(ManageScriptableObject.HandleCommand(new JObject
{
["action"] = "create",
["typeName"] = typeof(ManageScriptableObjectTestDefinition).FullName,
["folderPath"] = "file:///tmp/not_allowed",
["assetName"] = "BadFolder3",
["overwrite"] = true,
}));
Assert.IsFalse(badFileUri.Value<bool>("success"));
Assert.AreEqual("invalid_folder_path", badFileUri.Value<string>("error"));
}
[Test]
public void Create_NormalizesRelativeAndBackslashPaths_AndAvoidsDoubleSlashesInResult()
{
var create = new JObject
{
["action"] = "create",
["typeName"] = typeof(ManageScriptableObjectTestDefinition).FullName,
["folderPath"] = @"Temp\ManageScriptableObjectTests\SlashProbe\\Deep",
["assetName"] = "SlashProbe",
["overwrite"] = true,
};
var res = ToJObject(ManageScriptableObject.HandleCommand(create));
Assert.IsTrue(res.Value<bool>("success"), res.ToString());
var path = res["data"]?["path"]?.ToString();
Assert.IsNotNull(path, "Expected path in response.");
Assert.IsTrue(path!.StartsWith("Assets/Temp/ManageScriptableObjectTests/SlashProbe/Deep", StringComparison.Ordinal),
$"Expected sanitized Assets-rooted path, got: {path}");
Assert.IsFalse(path.Contains("//", StringComparison.Ordinal), $"Path should not contain double slashes: {path}");
}
}
}