chore(unity): 固定Unity CLI Loop本地包并移除UnitySkills依赖

This commit is contained in:
Liubing\LB
2026-09-28 18:14:59 +08:00
parent 0eb43b2b40
commit c4ae02def9
952 changed files with 70137 additions and 11 deletions

View File

@@ -0,0 +1,94 @@
using System;
namespace io.github.hatayama.uLoopMCP
{
/// <summary>
/// Response schema for RunTests command
/// Provides type-safe response structure
/// </summary>
public class RunTestsResponse : BaseToolResponse
{
public const string TestFrameworkUnavailableMessage =
"run-tests requires the Unity Test Framework package (com.unity.test-framework). Install it via Package Manager to use test execution.";
/// <summary>
/// Whether test execution was successful
/// </summary>
public bool Success { get; set; }
/// <summary>
/// Test execution message
/// </summary>
public string Message { get; set; }
/// <summary>
/// Test execution completion timestamp
/// </summary>
public string CompletedAt { get; set; }
/// <summary>
/// Total number of tests executed
/// </summary>
public int TestCount { get; set; }
/// <summary>
/// Number of passed tests
/// </summary>
public int PassedCount { get; set; }
/// <summary>
/// Number of failed tests
/// </summary>
public int FailedCount { get; set; }
/// <summary>
/// Number of skipped tests
/// </summary>
public int SkippedCount { get; set; }
/// <summary>
/// Path to XML result file (if saved)
/// </summary>
public string XmlPath { get; set; }
/// <summary>
/// Create a new RunTestsResponse
/// </summary>
public RunTestsResponse(bool success, string message, string completedAt, int testCount,
int passedCount, int failedCount, int skippedCount, string xmlPath = null)
{
Success = success;
Message = message;
CompletedAt = completedAt;
TestCount = testCount;
PassedCount = passedCount;
FailedCount = failedCount;
SkippedCount = skippedCount;
XmlPath = xmlPath;
}
/// <summary>
/// Parameterless constructor for JSON deserialization
/// </summary>
public RunTestsResponse()
{
Message = string.Empty;
CompletedAt = string.Empty;
XmlPath = string.Empty;
}
public static RunTestsResponse CreateTestFrameworkUnavailable()
{
return new RunTestsResponse(
success: false,
message: TestFrameworkUnavailableMessage,
completedAt: DateTime.UtcNow.ToString("o"),
testCount: 0,
passedCount: 0,
failedCount: 0,
skippedCount: 0,
xmlPath: null
);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0e07c934664e244f7bb0c9928d6ac9c2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,54 @@
using System.ComponentModel;
namespace io.github.hatayama.uLoopMCP
{
// Mirrors Unity Test Runner mode names without making the command schema depend on Test Framework types.
public enum RunTestMode
{
EditMode = 1,
PlayMode = 2
}
/// <summary>
/// Supported test filter types
/// </summary>
public enum TestFilterType
{
all = 0,
exact = 1,
regex = 2,
assembly = 3
}
/// <summary>
/// Schema for RunTests command parameters
/// Provides type-safe parameter access with default values
/// </summary>
public class RunTestsSchema : BaseToolSchema
{
/// <summary>
/// Test mode - EditMode(1), PlayMode(2)
/// </summary>
[Description("Test mode - EditMode(1), PlayMode(2)")]
public RunTestMode TestMode { get; set; } = RunTestMode.EditMode;
/// <summary>
/// Type of test filter - all(0), exact(1), regex(2), assembly(3)
/// </summary>
[Description("Type of test filter - all(0), exact(1), regex(2), assembly(3)")]
public TestFilterType FilterType { get; set; } = TestFilterType.all;
/// <summary>
/// Filter value (specify when filterType is not all)
/// • exact: Individual test method name (e.g.: io.github.hatayama.uLoopMCP.ConsoleLogRetrieverTests.GetAllLogs_WithMaskAllOff_StillReturnsAllLogs)
/// • regex: Class name or namespace (e.g.: io.github.hatayama.uLoopMCP.ConsoleLogRetrieverTests, io.github.hatayama.uLoopMCP)
/// • assembly: Assembly name (e.g.: uLoopMCP.Tests.Editor)
/// </summary>
[Description("Filter value (specify when filterType is not all)\n• exact: Individual test method name (e.g.: io.github.hatayama.uLoopMCP.ConsoleLogRetrieverTests.GetAllLogs_WithMaskAllOff_StillReturnsAllLogs)\n• regex: Class name or namespace (e.g.: io.github.hatayama.uLoopMCP.ConsoleLogRetrieverTests, io.github.hatayama.uLoopMCP)\n• assembly: Assembly name (e.g.: uLoopMCP.Tests.Editor)")]
public string FilterValue { get; set; } = "";
[Description("Save unsaved loaded Scene changes and current Prefab Stage changes before running tests")]
public bool SaveBeforeRun { get; set; } = false;
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fcfc452995c36409e993e09326c2693d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
using System.Threading;
using System.Threading.Tasks;
namespace io.github.hatayama.uLoopMCP
{
/// <summary>
/// Test execution tool handler - Type-safe implementation using Schema and Response
/// Executes tests using Unity Test Runner and returns the results
///
///
/// This Tool class delegates to RunTestsUseCase for business logic execution,
/// following the UseCase + Tool pattern for separation of concerns.
///
/// Related classes:
/// - RunTestsUseCase: Business logic and orchestration
/// - RunTestsSchema: Type-safe parameter schema
/// - RunTestsResponse: Type-safe response structure
/// </summary>
[McpTool(
Description = "Execute Unity Test Runner with advanced filtering options - exact test methods, regex patterns for classes/namespaces, assembly filtering"
)]
public class RunTestsTool : AbstractUnityTool<RunTestsSchema, RunTestsResponse>
{
public override string ToolName => McpConstants.TOOL_NAME_RUN_TESTS;
protected override async Task<RunTestsResponse> ExecuteAsync(RunTestsSchema parameters, CancellationToken ct)
{
// Create and execute RunTestsUseCase instance
RunTestsUseCase useCase = new();
return await useCase.ExecuteAsync(parameters, ct);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b7287f0e369c642d3bb24494f1561b5b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 86f9b7044f75e4de087ba50d53036889
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,71 @@
---
name: uloop-run-tests
description: "Run Unity Test Runner and report detailed results. Use for EditMode/PlayMode tests, change verification, or failure diagnosis."
---
# uloop run-tests
Execute Unity Test Runner. This command requires the Unity Test Framework package (`com.unity.test-framework`). If that package is not installed, the command returns `Success: false` with an unsupported message and does not affect the other Unity CLI Loop tools.
When tests fail, NUnit XML results with error messages and stack traces are automatically saved. Read the XML file at `XmlPath` for detailed failure diagnosis.
Before executing tests, `uloop run-tests` checks for unsaved loaded Scene changes and unsaved current Prefab Stage changes. If any are found, it returns `Success: false`, keeps `TestCount` at `0`, lists the unsaved items in `Message`, and does not start the Unity Test Runner. Save or discard those editor changes, then rerun the command. Use `--save-before-run true` only when the user explicitly asks to save editor changes before continuing.
## Usage
```bash
uloop run-tests [options]
```
## Parameters
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `--test-mode` | string | `EditMode` | Test mode: `EditMode`, `PlayMode` |
| `--filter-type` | string | `all` | Filter type: `all`, `exact`, `regex`, `assembly` |
| `--filter-value` | string | - | Filter value (test name, pattern, or assembly) |
| `--save-before-run` | boolean | `false` | Save unsaved loaded Scene changes and current Prefab Stage changes before running tests |
## Global Options
| Option | Description |
|--------|-------------|
| `--project-path <path>` | Optional. Use only when the target Unity project is not the current directory. |
## Examples
```bash
# Run all EditMode tests
uloop run-tests
# Run PlayMode tests
uloop run-tests --test-mode PlayMode
# Save explicitly approved editor changes before running tests
uloop run-tests --save-before-run true
# Run specific test
uloop run-tests --filter-type exact --filter-value "MyTest.TestMethod"
# Run tests matching pattern
uloop run-tests --filter-type regex --filter-value ".*Integration.*"
```
## Output
Returns JSON with:
- `Success` (boolean): Whether all tests passed
- `Message` (string): Summary message
- `CompletedAt` (string): ISO timestamp when the run finished
- `TestCount` (number): Total tests executed
- `PassedCount` (number): Passed tests
- `FailedCount` (number): Failed tests
- `SkippedCount` (number): Skipped tests
- `XmlPath` (string | null): Path to NUnit XML result file. `null` when no XML was saved; populated only when tests failed and the XML file exists on disk.
### XML Result File
When tests fail, NUnit XML results are automatically saved to `{project_root}/.uloop/outputs/TestResults/<timestamp>.xml`. The XML contains per-test-case results including:
- Test name and full name
- Pass/fail/skip status and duration
- For failed tests: `<message>` (assertion error) and `<stack-trace>`

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: cae04d651537c45d6817556ccd093c39
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: