com.valectric.mooserunner 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/CLI~/mooserunnerCli.exe +0 -0
  3. package/CLI~/mooserunnerCliDaemon.exe +0 -0
  4. package/Editor/GUI/MooseRunnerFail.png +0 -0
  5. package/Editor/GUI/MooseRunnerFail.png.meta +140 -0
  6. package/Editor/GUI/MooseRunnerGreenLED.png +0 -0
  7. package/Editor/GUI/MooseRunnerGreenLED.png.meta +140 -0
  8. package/Editor/GUI/MooseRunnerLogoBannerSmall.png +0 -0
  9. package/Editor/GUI/MooseRunnerLogoBannerSmall.png.meta +140 -0
  10. package/Editor/GUI/MooseRunnerNotRun.png +0 -0
  11. package/Editor/GUI/MooseRunnerNotRun.png.meta +140 -0
  12. package/Editor/GUI/MooseRunnerPass.png +0 -0
  13. package/Editor/GUI/MooseRunnerPass.png.meta +140 -0
  14. package/Editor/GUI/MooseRunnerYellowLED.png +0 -0
  15. package/Editor/GUI/MooseRunnerYellowLED.png.meta +140 -0
  16. package/Editor/MooseRunner.Editor.asmdef +17 -0
  17. package/Editor/MooseRunner.Editor.asmdef.meta +7 -0
  18. package/Editor/MooseRunner.Internal.Editor.dll +0 -0
  19. package/Editor/MooseRunner.Internal.Editor.dll.meta +33 -0
  20. package/Editor/MooseRunner.SessionRecorder.dll +0 -0
  21. package/Editor/MooseRunner.SessionRecorder.dll.meta +33 -0
  22. package/Editor/MooseRunner.Worker.dll +0 -0
  23. package/Editor/MooseRunner.Worker.dll.meta +33 -0
  24. package/Editor/_WrapperStub.cs +3 -0
  25. package/Editor/_WrapperStub.cs.meta +11 -0
  26. package/LICENSE.md +28 -0
  27. package/README.md +347 -0
  28. package/Runtime/Helpers/DoNotDestroyOnTeardown/DoNotDestroyOnTeardown.cs +262 -0
  29. package/Runtime/Helpers/DoNotDestroyOnTeardown/DoNotDestroyOnTeardown.cs.meta +2 -0
  30. package/Runtime/Helpers/DoNotDestroyOnTeardown/MooseRunner.helper.asmdef +18 -0
  31. package/Runtime/Helpers/DoNotDestroyOnTeardown/MooseRunner.helper.asmdef.meta +7 -0
  32. package/Runtime/MooseRunner.Helpers.Runtime.dll +0 -0
  33. package/Runtime/MooseRunner.Helpers.Runtime.dll.meta +27 -0
  34. package/Runtime/MooseRunner.Internal.dll +0 -0
  35. package/Runtime/MooseRunner.Internal.dll.meta +27 -0
  36. package/Runtime/MooseRunner.Multiplaytest.Types.dll +0 -0
  37. package/Runtime/MooseRunner.Multiplaytest.Types.dll.meta +27 -0
  38. package/Runtime/MooseRunner.Runtime.asmdef +20 -0
  39. package/Runtime/MooseRunner.Runtime.asmdef.meta +7 -0
  40. package/Runtime/MooseRunner.SessionRecorder.Runtime.dll +0 -0
  41. package/Runtime/MooseRunner.SessionRecorder.Runtime.dll.meta +27 -0
  42. package/Runtime/MooseRunner.dll +0 -0
  43. package/Runtime/MooseRunner.dll.meta +27 -0
  44. package/Runtime/_WrapperStub.cs +3 -0
  45. package/Runtime/_WrapperStub.cs.meta +11 -0
  46. package/Samples~/Demos/MooseRunner.Demo.CancellationTokens.Tests/BatchCancellationTests.cs +37 -0
  47. package/Samples~/Demos/MooseRunner.Demo.CancellationTokens.Tests/BatchCancellationTests.cs.meta +2 -0
  48. package/Samples~/Demos/MooseRunner.Demo.CancellationTokens.Tests/CancellationTokenTests.cs +186 -0
  49. package/Samples~/Demos/MooseRunner.Demo.CancellationTokens.Tests/CancellationTokenTests.cs.meta +2 -0
  50. package/Samples~/Demos/MooseRunner.Demo.CancellationTokens.Tests/MooseRunner.Demo.CancellationTokens.Tests.asmdef +28 -0
  51. package/Samples~/Demos/MooseRunner.Demo.CancellationTokens.Tests/MooseRunner.Demo.CancellationTokens.Tests.asmdef.meta +7 -0
  52. package/Samples~/Demos/MooseRunner.Demo.CancellationTokens.Tests/SetupTeardownCancellationTests.cs +84 -0
  53. package/Samples~/Demos/MooseRunner.Demo.CancellationTokens.Tests/SetupTeardownCancellationTests.cs.meta +2 -0
  54. package/Samples~/Demos/MooseRunner.Demo.CancellationTokens.Tests/TESTING_INSTRUCTIONS.md +491 -0
  55. package/Samples~/Demos/MooseRunner.Demo.CancellationTokens.Tests/TESTING_INSTRUCTIONS.md.meta +7 -0
  56. package/Samples~/Demos/MooseRunner.Demo.ErrorHandling.Tests/ErrorHandelingTest.cs +177 -0
  57. package/Samples~/Demos/MooseRunner.Demo.ErrorHandling.Tests/ErrorHandelingTest.cs.meta +11 -0
  58. package/Samples~/Demos/MooseRunner.Demo.ErrorHandling.Tests/MooseRunner.Demo.ErrorHandling.Tests.asmdef +28 -0
  59. package/Samples~/Demos/MooseRunner.Demo.ErrorHandling.Tests/MooseRunner.Demo.ErrorHandling.Tests.asmdef.meta +7 -0
  60. package/Samples~/Demos/MooseRunner.Demo.Flow.TestSupport/LogEntry.cs +51 -0
  61. package/Samples~/Demos/MooseRunner.Demo.Flow.TestSupport/LogEntry.cs.meta +11 -0
  62. package/Samples~/Demos/MooseRunner.Demo.Flow.TestSupport/LogFileParser.cs +70 -0
  63. package/Samples~/Demos/MooseRunner.Demo.Flow.TestSupport/LogFileParser.cs.meta +11 -0
  64. package/Samples~/Demos/MooseRunner.Demo.Flow.TestSupport/MooseRunner.Demo.Flow.TestSupport.asmdef +22 -0
  65. package/Samples~/Demos/MooseRunner.Demo.Flow.TestSupport/MooseRunner.Demo.Flow.TestSupport.asmdef.meta +7 -0
  66. package/Samples~/Demos/MooseRunner.Demo.Flow.TestSupport/MooseRunnerLogReference.json +62 -0
  67. package/Samples~/Demos/MooseRunner.Demo.Flow.TestSupport/MooseRunnerLogReference.json.meta +7 -0
  68. package/Samples~/Demos/MooseRunner.Demo.Flow.TestSupport/MooseRunnerLogReference_2.json +33 -0
  69. package/Samples~/Demos/MooseRunner.Demo.Flow.TestSupport/MooseRunnerLogReference_2.json.meta +7 -0
  70. package/Samples~/Demos/MooseRunner.Demo.Flow.TestSupport/MooseRunnerLogReference_No_UniTask.json +57 -0
  71. package/Samples~/Demos/MooseRunner.Demo.Flow.TestSupport/MooseRunnerLogReference_No_UniTask.json.meta +7 -0
  72. package/Samples~/Demos/MooseRunner.Demo.OrderAttribute/MethodOrderAttributeTests.cs +62 -0
  73. package/Samples~/Demos/MooseRunner.Demo.OrderAttribute/MethodOrderAttributeTests.cs.meta +2 -0
  74. package/Samples~/Demos/MooseRunner.Demo.OrderAttribute/MooseRunner.Demo.OrderAttribute.asmdef +20 -0
  75. package/Samples~/Demos/MooseRunner.Demo.OrderAttribute/MooseRunner.Demo.OrderAttribute.asmdef.meta +7 -0
  76. package/Samples~/Demos/MooseRunner.Demo.RealUseCase/CatAnimation.controller +276 -0
  77. package/Samples~/Demos/MooseRunner.Demo.RealUseCase/CatAnimation.controller.meta +8 -0
  78. package/Samples~/Demos/MooseRunner.Demo.RealUseCase/Enemy.cs +101 -0
  79. package/Samples~/Demos/MooseRunner.Demo.RealUseCase/Enemy.cs.meta +11 -0
  80. package/Samples~/Demos/MooseRunner.Demo.RealUseCase/FireComponent.cs +19 -0
  81. package/Samples~/Demos/MooseRunner.Demo.RealUseCase/FireComponent.cs.meta +3 -0
  82. package/Samples~/Demos/MooseRunner.Demo.RealUseCase/Model/Ghost_cat.fbx +0 -0
  83. package/Samples~/Demos/MooseRunner.Demo.RealUseCase/Model/Ghost_cat.fbx.meta +547 -0
  84. package/Samples~/Demos/MooseRunner.Demo.RealUseCase/Model.meta +8 -0
  85. package/Samples~/Demos/MooseRunner.Demo.RealUseCase/MooseRunner.Demo.RealUseCase.asmdef +29 -0
  86. package/Samples~/Demos/MooseRunner.Demo.RealUseCase/MooseRunner.Demo.RealUseCase.asmdef.meta +7 -0
  87. package/Samples~/Demos/MooseRunner.Demo.RealUseCase/RealUseCaseScene.unity +4758 -0
  88. package/Samples~/Demos/MooseRunner.Demo.RealUseCase/RealUseCaseScene.unity.meta +7 -0
  89. package/Samples~/Demos/MooseRunner.Demo.RealUseCase/RealUseCaseTest.cs +307 -0
  90. package/Samples~/Demos/MooseRunner.Demo.RealUseCase/RealUseCaseTest.cs.meta +3 -0
  91. package/Samples~/Demos/MooseRunner.Demo.RealUseCase/Resources/Ghost_cat.prefab +157 -0
  92. package/Samples~/Demos/MooseRunner.Demo.RealUseCase/Resources/Ghost_cat.prefab.meta +7 -0
  93. package/Samples~/Demos/MooseRunner.Demo.RealUseCase/Resources.meta +8 -0
  94. package/Samples~/Demos/MooseRunner.Demo.Support/MessageDisplayManager.cs +291 -0
  95. package/Samples~/Demos/MooseRunner.Demo.Support/MessageDisplayManager.cs.meta +11 -0
  96. package/Samples~/Demos/MooseRunner.Demo.Support/MooseRunner.Demo.Support.asmdef +19 -0
  97. package/Samples~/Demos/MooseRunner.Demo.Support/MooseRunner.Demo.Support.asmdef.meta +7 -0
  98. package/Samples~/Demos/MooseRunner.Demo.Tests/DummyTestBase1.cs +71 -0
  99. package/Samples~/Demos/MooseRunner.Demo.Tests/DummyTestBase1.cs.meta +11 -0
  100. package/Samples~/Demos/MooseRunner.Demo.Tests/DummyTestClass1.cs +301 -0
  101. package/Samples~/Demos/MooseRunner.Demo.Tests/DummyTestClass1.cs.meta +11 -0
  102. package/Samples~/Demos/MooseRunner.Demo.Tests/DummyTestClass2.cs +69 -0
  103. package/Samples~/Demos/MooseRunner.Demo.Tests/DummyTestClass2.cs.meta +11 -0
  104. package/Samples~/Demos/MooseRunner.Demo.Tests/ExplicitAttributeTests.cs +36 -0
  105. package/Samples~/Demos/MooseRunner.Demo.Tests/ExplicitAttributeTests.cs.meta +2 -0
  106. package/Samples~/Demos/MooseRunner.Demo.Tests/HumanReviewModeDemo.cs +99 -0
  107. package/Samples~/Demos/MooseRunner.Demo.Tests/HumanReviewModeDemo.cs.meta +2 -0
  108. package/Samples~/Demos/MooseRunner.Demo.Tests/InstanceHandlingVerificationTest.cs +99 -0
  109. package/Samples~/Demos/MooseRunner.Demo.Tests/InstanceHandlingVerificationTest.cs.meta +2 -0
  110. package/Samples~/Demos/MooseRunner.Demo.Tests/MooseRunner.Demo.Tests.asmdef +23 -0
  111. package/Samples~/Demos/MooseRunner.Demo.Tests/MooseRunner.Demo.Tests.asmdef.meta +7 -0
  112. package/Samples~/Demos/MooseRunner.Demo.Tests/PauseTestExecutionDemo.cs +74 -0
  113. package/Samples~/Demos/MooseRunner.Demo.Tests/PauseTestExecutionDemo.cs.meta +2 -0
  114. package/Samples~/Demos/TestResources/OneCamera/Materials/Background.mat +137 -0
  115. package/Samples~/Demos/TestResources/OneCamera/Materials/Background.mat.meta +8 -0
  116. package/Samples~/Demos/TestResources/OneCamera/Materials/Background.png +0 -0
  117. package/Samples~/Demos/TestResources/OneCamera/Materials/Background.png.meta +127 -0
  118. package/Samples~/Demos/TestResources/OneCamera/Materials/Grid.mat +71 -0
  119. package/Samples~/Demos/TestResources/OneCamera/Materials/Grid.mat.meta +8 -0
  120. package/Samples~/Demos/TestResources/OneCamera/Materials/Grid.png +0 -0
  121. package/Samples~/Demos/TestResources/OneCamera/Materials/Grid.png.meta +127 -0
  122. package/Samples~/Demos/TestResources/OneCamera/Materials/Grid.shadergraph +1910 -0
  123. package/Samples~/Demos/TestResources/OneCamera/Materials/Grid.shadergraph.meta +10 -0
  124. package/Samples~/Demos/TestResources/OneCamera/Materials/GridNormal.png +0 -0
  125. package/Samples~/Demos/TestResources/OneCamera/Materials/GridNormal.png.meta +127 -0
  126. package/Samples~/Demos/TestResources/OneCamera/Materials.meta +8 -0
  127. package/Samples~/Demos/TestResources/OneCamera/OneCameraScene.unity +598 -0
  128. package/Samples~/Demos/TestResources/OneCamera/OneCameraScene.unity.meta +7 -0
  129. package/Samples~/Demos/TestResources/OneCamera.meta +8 -0
  130. package/Third Party Notices.md +37 -0
  131. package/package.json +38 -0
package/README.md ADDED
@@ -0,0 +1,347 @@
1
+ # MooseRunner (Unity Git Submodule)
2
+
3
+ This project integrates **[MooseRunner](https://github.com/Valectric/MooseRunner)** as a Unity package using **Git submodules**.
4
+ Unity detects it as an **embedded package** via its `package.json`.
5
+
6
+ ---
7
+
8
+ ## Why use a submodule?
9
+
10
+ Instead of copying MooseRunner’s source code directly, we use a **Git submodule** because:
11
+
12
+ - Keeps MooseRunner’s history and version tracking intact
13
+ - Easy to update to the latest changes (or pin to a specific commit)
14
+ - Keeps your repository clean while still embedding MooseRunner as a Unity package
15
+ - Works seamlessly with Unity’s Package Manager as an **embedded package**
16
+
17
+ ---
18
+
19
+ ## Adding MooseRunner
20
+
21
+ To add MooseRunner as a submodule in your Unity project:
22
+
23
+ ```bash
24
+ git submodule add https://github.com/Valectric/MooseRunner.git Packages/MooseRunnerGit
25
+ git commit -m "Add MooseRunner as submodule in Packages/MooseRunnerGit"
26
+ ```
27
+
28
+ Then manual add MooseRunner as a pakcage in packagemanager from disk by selecting
29
+ the package.json in the subfolder MooseRunner
30
+
31
+ ### Important: Enable Test Assemblies
32
+
33
+ When using MooseRunner as a package, you must add it to the `testables` array in your project's `Packages/manifest.json`:
34
+
35
+ ```json
36
+ {
37
+ "dependencies": {
38
+ ...
39
+ },
40
+ "testables": [
41
+ "com.valectric.mooserunner"
42
+ ]
43
+ }
44
+ ```
45
+
46
+ This ensures Unity includes MooseRunner's test assemblies, allowing the SelectMethod list to properly display all available tests.
47
+
48
+ ---
49
+
50
+ ## Cloning With Submodules
51
+
52
+ When cloning this repository fresh, make sure to fetch submodules:
53
+
54
+ ```bash
55
+ git clone <your-repo-url>
56
+ cd <your-repo>
57
+ git submodule update --init --recursive
58
+ ```
59
+
60
+ ---
61
+
62
+ ## Updating MooseRunner
63
+
64
+ Update MooseRunner to the latest version:
65
+
66
+ ```bash
67
+ cd Packages/MooseRunnerGit
68
+ git pull origin main
69
+ ```
70
+
71
+ Update all submodules in one go:
72
+
73
+ ```bash
74
+ git submodule update --remote --merge
75
+ ```
76
+
77
+ ---
78
+
79
+ ## Listing Submodules
80
+
81
+ Check the status of submodules (commit SHA and path):
82
+
83
+ ```bash
84
+ git submodule status
85
+ ```
86
+
87
+ List configured submodule URLs:
88
+
89
+ ```bash
90
+ git config --file .gitmodules --get-regexp url
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Removing MooseRunner
96
+
97
+ To completely remove the MooseRunner submodule:
98
+
99
+ ```bash
100
+ git submodule deinit -f Packages/MooseRunnerGit
101
+ git rm -f Packages/MooseRunnerGit
102
+ rm -rf .git/modules/Packages/MooseRunnerGit
103
+ git commit -m "Remove MooseRunner submodule"
104
+ ```
105
+
106
+ ---
107
+
108
+ With this setup, Unity treats MooseRunner as an **embedded package** while Git keeps it synced as a **submodule**.
109
+
110
+ ---
111
+
112
+ ## Claude Code Integration
113
+
114
+ MooseRunner includes skills for Claude Code that provide comprehensive documentation on writing and running tests.
115
+
116
+ ### Available Skills
117
+
118
+ Skills are located in `MooseRunner/skills/`:
119
+
120
+ | Skill | Use Case |
121
+ |-------|----------|
122
+ | **play-mode-tester** | Isolated component tests with SetUp/TearDown |
123
+ | **e2e-tester** | E2E gameplay flow tests (chained, no setup between) |
124
+
125
+ ### Installing Skills
126
+
127
+ Skills sync automatically via git hooks on checkout/merge.
128
+
129
+ #### Step 1: Create Hooks Folder
130
+
131
+ Create a `.githooks/` folder in your project root (tracked by git, unlike `.git/hooks/`):
132
+
133
+ ```bash
134
+ mkdir .githooks
135
+ ```
136
+
137
+ #### Step 2: Copy the Sync Script
138
+
139
+ ```bash
140
+ cp Assets/MooseRunnerGit/MooseRunner/hooks/sync-mooserunner-skills.ps1 .githooks/
141
+ ```
142
+
143
+ **Note:** If MooseRunner is in `Packages/` instead of `Assets/`, edit the script's `$SubmodulePath` parameter.
144
+
145
+ #### Step 3: Set Up Git Hooks
146
+
147
+ Copy or create `post-checkout` and `post-merge` in `.githooks/`:
148
+
149
+ ```bash
150
+ cp Assets/MooseRunnerGit/MooseRunner/hooks/post-checkout .githooks/
151
+ cp Assets/MooseRunnerGit/MooseRunner/hooks/post-merge .githooks/
152
+ ```
153
+
154
+ Or add this line to existing hooks:
155
+
156
+ ```bash
157
+ powershell -NoProfile -ExecutionPolicy Bypass -File .githooks/sync-mooserunner-skills.ps1
158
+ ```
159
+
160
+ #### Step 4: Configure Git to Use Tracked Hooks
161
+
162
+ ```bash
163
+ git config core.hooksPath .githooks
164
+ ```
165
+
166
+ > **Tip**: Add this to a setup script so new developers run it once after cloning.
167
+
168
+ #### Step 5: Run the Sync Script
169
+
170
+ ```powershell
171
+ .\.githooks\sync-mooserunner-skills.ps1
172
+ ```
173
+
174
+ #### Step 6: Update .gitignore
175
+
176
+ Add the junctioned folders to your `.gitignore`:
177
+
178
+ ```gitignore
179
+ # Skills synced from MooseRunner submodule
180
+ .claude/skills/play-mode-tester/
181
+ .claude/skills/e2e-tester/
182
+ ```
183
+
184
+ #### Step 7: Update settings.json (Optional)
185
+
186
+ To allow skills to run without permission prompts, add to `.claude/settings.json`:
187
+
188
+ ```json
189
+ "Skill(play-mode-tester)",
190
+ "Skill(e2e-tester)"
191
+ ```
192
+
193
+ ### Windows Developer Mode
194
+
195
+ Junction creation requires Developer Mode on Windows:
196
+
197
+ **Settings > Update & Security > For developers > Developer Mode**
198
+
199
+ Without it, skills are copied instead of junctioned (won't auto-update with submodule).
200
+
201
+ ### What the Skills Provide
202
+
203
+ - **Test Structure Guidelines**: Arrange – Act – Assert – Cleanup pattern
204
+ - **Scene Cleanup Methods**: `DoNotDestroyOnTeardown.CleanSceneImmediate()` and `CleanSceneSafeUsingUpdateAsync()`
205
+ - **MCP Integration**: How to run tests via MCP tools
206
+ - **E2E Test Patterns**: Dynamic loading rules, first-test-method setup, chained execution
207
+ - **Debugging Workflows**: Console analysis and debug logging patterns
208
+
209
+ ### Recommended CLAUDE.md Settings
210
+
211
+ Add to your project's `CLAUDE.md`:
212
+
213
+ ```markdown
214
+ ## Critical Constraints
215
+ - For tests use the `play-mode-tester` skill (isolated tests) or `e2e-tester` skill (E2E gameplay flows). Never run the MCP run_play_mode_test yourself.
216
+
217
+ ## MooseRunner Testing
218
+
219
+ Deny these MCP tools in `.claude/settings.json` to prevent direct test execution:
220
+ - `mcp__unityMCP__run_tests`
221
+ - `mcp__unityMCP__refresh_unity`
222
+ - `mcp__unityMCP__get_test_job`
223
+
224
+ Use the skills instead, which handle test execution properly via MooseRunner.
225
+ ```
226
+
227
+ ---
228
+
229
+ ## Troubleshooting
230
+
231
+ ### Skills Not Appearing in Claude Code
232
+ - Verify junctions exist: `ls .claude/skills/`
233
+ - Re-run sync script: `.\.git\hooks\sync-mooserunner-skills.ps1`
234
+ - Restart Claude Code after installation
235
+
236
+ ### Junction Creation Failed
237
+ - Enable Developer Mode: Settings > Update & Security > For developers
238
+ - Without Developer Mode, skills are copied (won't auto-update)
239
+
240
+ ### Hook Not Executing on Checkout
241
+ - Verify hook is executable (Git Bash): `chmod +x .git/hooks/post-checkout`
242
+ - Check hooks path: `git config core.hooksPath`
243
+
244
+ ### PowerShell Execution Policy Error
245
+ - Run: `Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned`
246
+
247
+ ---
248
+
249
+ ## AI Installation Guide
250
+
251
+ If you are an AI assistant installing this for a user:
252
+
253
+ ### Pre-Installation Checks (Silent)
254
+ 1. Check if `.claude/skills/` directory exists
255
+ 2. Check if hooks folder exists (`.git/hooks` or custom path via `git config core.hooksPath`)
256
+ 3. Check if `sync-mooserunner-skills.ps1` already exists in hooks folder
257
+
258
+ ### Installation Notes
259
+ - **Merging**: When updating settings.json, merge new permissions into existing `permissions.allow` array
260
+ - **Existing hooks**: Add sync line to existing post-checkout/post-merge, don't replace entire file
261
+ - **Verification**: After running sync script, verify junctions created with `ls .claude/skills/`
262
+
263
+ ### Questions to Ask User
264
+ - "Do you have a custom hooks path configured?" (if unsure, run `git config core.hooksPath`)
265
+ - "Should I add these skills to your settings.json permissions?"
266
+
267
+ ---
268
+
269
+ ## Optional Components
270
+
271
+ MooseRunner includes optional utilities. Each component can be installed independently.
272
+
273
+ ### A. MooseRunner Core (Skills + Test CLI)
274
+
275
+ **What it does:** Test skills for Claude Code + CLI script for long-running tests.
276
+
277
+ **Why useful:** Skills provide test documentation and patterns. CLI bypasses MCP timeout for long tests.
278
+
279
+ **Setup:** Follow "Installing Skills" section above.
280
+
281
+ **CLAUDE.md snippet:**
282
+ ```markdown
283
+ ## Critical Constraints
284
+ - For tests use the `play-mode-tester` skill (isolated tests) or `e2e-tester` skill (E2E gameplay flows).
285
+
286
+ ## MooseRunner Testing
287
+ Script location: `Assets/MooseRunnerGit/MooseRunner/Editor/MCPForUnityTools/run-moose-test.py`
288
+
289
+ ```bash
290
+ python run-moose-test.py --method Assembly Class Method
291
+ python run-moose-test.py --class Assembly Class
292
+ python run-moose-test.py --assembly Assembly
293
+ ```
294
+ ```
295
+
296
+ ---
297
+
298
+ ### B. Unity MCP CLI
299
+
300
+ **What it does:** Command-line interface for Unity MCP tools.
301
+
302
+ **Why useful:** Avoids MCP reconnection issues. When Unity restarts, MCP connection breaks and requires human `/mcp reconnect`. CLI works via HTTP - no persistent connection needed.
303
+
304
+ **Installation:**
305
+ ```bash
306
+ cd Server # In unity-mcp repo (https://github.com/CoplayDev/unity-mcp)
307
+ pip install -e .
308
+ ```
309
+
310
+ **Prerequisite:** MCP HTTP server must be running. Use `restart-unity.ps1` from `General-Claude-Code-Skill-And-Agents/Unity_Control/` which handles this automatically.
311
+
312
+ **Setup:** Unity needs `AutoStartMcpSession` component to connect to MCP server.
313
+
314
+ **CLAUDE.md snippet:**
315
+ ```markdown
316
+ ## Unity MCP (CLI Mode)
317
+
318
+ We use Unity MCP via **CLI** instead of MCP server connection. This avoids reconnection issues when Unity restarts.
319
+
320
+ ### Core Commands
321
+ ```bash
322
+ unity-mcp instance list # List Unity instances
323
+ unity-mcp editor play|pause|stop # Control play mode
324
+ unity-mcp editor console # Get console logs
325
+ unity-mcp scene hierarchy # Get scene hierarchy
326
+ unity-mcp gameobject find "Name" # Find GameObject
327
+ unity-mcp raw tool_name 'JSON_params' # Any tool via raw access
328
+ ```
329
+
330
+ Full reference: https://github.com/CoplayDev/unity-mcp/blob/main/docs/guides/CLI_USAGE.md
331
+ ```
332
+
333
+ ---
334
+
335
+ ### Why These Components Are Separate
336
+
337
+ | Component | Purpose | When to Install |
338
+ |-----------|---------|-----------------|
339
+ | **MooseRunner Core** | Test documentation + CLI | Always (for testing) |
340
+ | **Unity MCP CLI** | CLI instead of MCP connection | If Unity restarts break your workflow |
341
+
342
+ Each component solves a specific problem:
343
+ - **MooseRunner Core**: "How do I write and run tests?"
344
+ - **Unity MCP CLI**: "How do I avoid MCP reconnection issues?"
345
+
346
+ **Note:** Unity Control Scripts (start/stop/restart Unity) have moved to `General-Claude-Code-Skill-And-Agents/Unity_Control/`.
347
+
@@ -0,0 +1,262 @@
1
+ using System.Threading;
2
+ using System.Threading.Tasks;
3
+ using UnityEngine;
4
+ using MooseRunner.Internal.Helper;
5
+ using Object = UnityEngine.Object;
6
+
7
+ namespace MooseRunner.helper
8
+ {
9
+ /// <summary>
10
+ /// Tag component that marks a GameObject as protected from test teardown cleanup.
11
+ /// Provides static cleanup methods for test scenes while preserving protected objects.
12
+ /// By default, protected objects are: GameObjects with TestRunnerHelper or DoNotDestroyOnTeardown components.
13
+ /// When includeMarkedObjects is true, only TestRunnerHelper objects are preserved.
14
+ /// </summary>
15
+ public class DoNotDestroyOnTeardown : MonoBehaviour
16
+ {
17
+ /// <summary>
18
+ /// When true, logs all GameObjects instead of destroying them.
19
+ /// Useful for debugging what objects exist in the scene.
20
+ /// </summary>
21
+ public static bool DebugLogObjectsOnly = false;
22
+
23
+ /// <summary>
24
+ /// Cleans the scene immediately using DestroyImmediate. Synchronous, no coroutine needed.
25
+ /// Use in SetUp methods or when immediate cleanup is required.
26
+ /// TestRunnerHelper objects are always preserved.
27
+ /// DoNotDestroyOnTeardown-marked objects are preserved by default unless includeMarkedObjects is true.
28
+ /// Warnings are suppressed during cleanup to avoid RequireComponent circular dependency spam.
29
+ /// </summary>
30
+ /// <param name="hiddenObjectsIncluded">If true, includes hidden objects with HideFlags.
31
+ /// Set to false to prevent SceneView cache issues with lights.</param>
32
+ /// <param name="includeMarkedObjects">If true, DoNotDestroyOnTeardown-marked objects are also
33
+ /// destroyed. TestRunnerHelper objects are always preserved regardless of this flag.</param>
34
+ public static void CleanSceneImmediate(bool hiddenObjectsIncluded = true, bool includeMarkedObjects = false)
35
+ {
36
+ GameObject[] visibleObjects = Object.FindObjectsByType<GameObject>(FindObjectsSortMode.None);
37
+
38
+ if (DebugLogObjectsOnly)
39
+ {
40
+ LogGameObjects(visibleObjects, "Visible Objects", includeMarkedObjects);
41
+ if (hiddenObjectsIncluded)
42
+ {
43
+ GameObject[] allObjects = Resources.FindObjectsOfTypeAll<GameObject>();
44
+ LogGameObjects(allObjects, "All Objects (including hidden)", includeMarkedObjects);
45
+ }
46
+ return;
47
+ }
48
+
49
+ // Suppress RequireComponent circular dependency warnings during destruction
50
+ var previousLogType = Debug.unityLogger.filterLogType;
51
+ Debug.unityLogger.filterLogType = LogType.Error;
52
+
53
+ try
54
+ {
55
+ DestroyGameObjectsImmediate(visibleObjects, includeMarkedObjects);
56
+
57
+ if (hiddenObjectsIncluded)
58
+ {
59
+ GameObject[] allObjects = Resources.FindObjectsOfTypeAll<GameObject>();
60
+ DestroyGameObjectsImmediate(allObjects, includeMarkedObjects);
61
+ }
62
+ }
63
+ finally
64
+ {
65
+ Debug.unityLogger.filterLogType = previousLogType;
66
+ }
67
+ }
68
+
69
+ /// <summary>
70
+ /// Cleans the scene safely using Destroy (frame-delayed). Use in TearDown contexts.
71
+ /// TestRunnerHelper objects are always preserved.
72
+ /// DoNotDestroyOnTeardown-marked objects are preserved by default unless includeMarkedObjects is true.
73
+ /// Uses two-pass approach: fast pass for visible objects, thorough pass for hidden objects.
74
+ /// Spans multiple frames: destroy, wait, verify.
75
+ /// Warnings are suppressed during cleanup to avoid RequireComponent circular dependency spam.
76
+ /// </summary>
77
+ /// <param name="hiddenObjectsIncluded">If true, includes hidden objects with HideFlags.
78
+ /// Set to false to prevent SceneView cache issues with lights.</param>
79
+ /// <param name="ct">Cancellation token for async operation.</param>
80
+ /// <param name="includeMarkedObjects">If true, DoNotDestroyOnTeardown-marked objects are also
81
+ /// destroyed. TestRunnerHelper objects are always preserved regardless of this flag.</param>
82
+ public static async Task CleanSceneSafeUsingUpdateAsync(
83
+ bool hiddenObjectsIncluded,
84
+ CancellationToken ct,
85
+ bool includeMarkedObjects = false)
86
+ {
87
+ // Frame 1: Destroy objects
88
+ GameObject[] visibleObjects = Object.FindObjectsByType<GameObject>(FindObjectsSortMode.None);
89
+
90
+ if (DebugLogObjectsOnly)
91
+ {
92
+ LogGameObjects(visibleObjects, "Visible Objects (Async)", includeMarkedObjects);
93
+ if (hiddenObjectsIncluded)
94
+ {
95
+ GameObject[] allObjects = Resources.FindObjectsOfTypeAll<GameObject>();
96
+ LogGameObjects(allObjects, "All Objects including hidden (Async)", includeMarkedObjects);
97
+ }
98
+ return;
99
+ }
100
+
101
+ // Suppress RequireComponent circular dependency warnings during destruction
102
+ var previousLogType = Debug.unityLogger.filterLogType;
103
+ Debug.unityLogger.filterLogType = LogType.Error;
104
+
105
+ try
106
+ {
107
+ DestroyGameObjects(visibleObjects, includeMarkedObjects);
108
+
109
+ if (hiddenObjectsIncluded)
110
+ {
111
+ GameObject[] allObjects = Resources.FindObjectsOfTypeAll<GameObject>();
112
+ DestroyGameObjects(allObjects, includeMarkedObjects);
113
+ }
114
+ }
115
+ finally
116
+ {
117
+ Debug.unityLogger.filterLogType = previousLogType;
118
+ }
119
+
120
+ // Frame 2: Wait for destruction
121
+ await Awaitable.NextFrameAsync(ct);
122
+
123
+ // Frame 3: Verify cleanup
124
+ await Awaitable.NextFrameAsync(ct);
125
+ }
126
+
127
+ /// <summary>
128
+ /// Checks if a GameObject is excluded from destruction.
129
+ /// TestRunnerHelper objects are always excluded.
130
+ /// DoNotDestroyOnTeardown-marked objects are excluded unless includeMarkedObjects is true.
131
+ /// </summary>
132
+ /// <param name="go">The GameObject to check.</param>
133
+ /// <param name="includeMarkedObjects">If true, DoNotDestroyOnTeardown-marked objects
134
+ /// are NOT excluded (they will be destroyed).</param>
135
+ /// <returns>True if excluded from destruction, false otherwise.</returns>
136
+ private static bool IsExcludedGameObject(GameObject go, bool includeMarkedObjects)
137
+ {
138
+ // TestRunnerHelper is ALWAYS excluded — never destroyed regardless of flags
139
+ if (go.GetComponent<TestRunnerHelper>() != null)
140
+ {
141
+ return true;
142
+ }
143
+
144
+ // DoNotDestroyOnTeardown excluded only when includeMarkedObjects is false
145
+ if (!includeMarkedObjects && go.GetComponent<DoNotDestroyOnTeardown>() != null)
146
+ {
147
+ return true;
148
+ }
149
+
150
+ return false;
151
+ }
152
+
153
+ /// <summary>
154
+ /// Checks if a GameObject is an editor-internal object that should never be destroyed.
155
+ /// This includes Unity's SceneView lights, preview objects, and other editor infrastructure.
156
+ /// </summary>
157
+ /// <param name="go">The GameObject to check.</param>
158
+ /// <returns>True if this is an editor-internal object, false otherwise.</returns>
159
+ private static bool IsEditorInternalObject(GameObject go)
160
+ {
161
+ // Skip objects with DontSave flag (editor-only objects like SceneView lights)
162
+ if ((go.hideFlags & HideFlags.DontSave) != 0)
163
+ {
164
+ return true;
165
+ }
166
+
167
+ // Skip objects in editor-internal scenes (SceneView lighting scenes)
168
+ if (go.scene.IsValid() && go.scene.name.StartsWith("CustomLightsScene"))
169
+ {
170
+ return true;
171
+ }
172
+
173
+ return false;
174
+ }
175
+
176
+ /// <summary>
177
+ /// Logs all GameObjects with detailed information for debugging.
178
+ /// </summary>
179
+ /// <param name="objects">Array of GameObjects to log.</param>
180
+ /// <param name="category">Category label for the log output.</param>
181
+ /// <param name="includeMarkedObjects">If true, DoNotDestroyOnTeardown-marked objects
182
+ /// are shown as WOULD_DESTROY instead of PROTECTED.</param>
183
+ private static void LogGameObjects(GameObject[] objects, string category, bool includeMarkedObjects)
184
+ {
185
+ Debug.Log($"=== {category} ({objects.Length} total) ===");
186
+
187
+ foreach (GameObject go in objects)
188
+ {
189
+ if (go == null)
190
+ {
191
+ Debug.Log(" [null GameObject]");
192
+ continue;
193
+ }
194
+
195
+ string sceneName = go.scene.IsValid() ? go.scene.name : "[no scene]";
196
+ bool sceneLoaded = go.scene.isLoaded;
197
+ string parentInfo = go.transform.parent != null ? $"Parent: {go.transform.parent.name}" : "Root";
198
+ string hideFlags = go.hideFlags.ToString();
199
+
200
+ // Get components for additional context
201
+ var components = go.GetComponents<Component>();
202
+ string componentNames = string.Join(", ", System.Array.ConvertAll(components, c => c != null ? c.GetType().Name : "null"));
203
+
204
+ bool wouldBeExcluded = IsExcludedGameObject(go, includeMarkedObjects);
205
+ bool wouldBeSkippedParent = go.transform.parent != null;
206
+ bool wouldBeSkippedScene = !sceneLoaded;
207
+ bool wouldBeSkippedEditorInternal = IsEditorInternalObject(go);
208
+
209
+ string status = "";
210
+ if (wouldBeExcluded) status += "[PROTECTED] ";
211
+ if (wouldBeSkippedParent) status += "[HAS_PARENT] ";
212
+ if (wouldBeSkippedScene) status += "[UNLOADED_SCENE] ";
213
+ if (wouldBeSkippedEditorInternal) status += "[EDITOR_INTERNAL] ";
214
+ if (string.IsNullOrEmpty(status)) status = "[WOULD_DESTROY] ";
215
+
216
+ Debug.Log($" {status}{go.name} | Scene: {sceneName} (loaded: {sceneLoaded}) | {parentInfo} | HideFlags: {hideFlags} | Components: [{componentNames}]");
217
+ }
218
+
219
+ Debug.Log($"=== End {category} ===");
220
+ }
221
+
222
+ /// <summary>
223
+ /// Destroys GameObjects with filtering of excluded GameObjects (frame-delayed).
224
+ /// </summary>
225
+ /// <param name="objects">Array of GameObjects to process.</param>
226
+ /// <param name="includeMarkedObjects">If true, DoNotDestroyOnTeardown-marked objects
227
+ /// are also destroyed.</param>
228
+ private static void DestroyGameObjects(GameObject[] objects, bool includeMarkedObjects)
229
+ {
230
+ foreach (GameObject go in objects)
231
+ {
232
+ if (go == null) continue;
233
+ if (go.transform.parent != null) continue;
234
+ if (!go.scene.isLoaded) continue;
235
+ if (IsExcludedGameObject(go, includeMarkedObjects)) continue;
236
+ if (IsEditorInternalObject(go)) continue;
237
+
238
+ Object.Destroy(go);
239
+ }
240
+ }
241
+
242
+ /// <summary>
243
+ /// Destroys GameObjects immediately with filtering of excluded GameObjects.
244
+ /// </summary>
245
+ /// <param name="objects">Array of GameObjects to process.</param>
246
+ /// <param name="includeMarkedObjects">If true, DoNotDestroyOnTeardown-marked objects
247
+ /// are also destroyed.</param>
248
+ private static void DestroyGameObjectsImmediate(GameObject[] objects, bool includeMarkedObjects)
249
+ {
250
+ foreach (GameObject go in objects)
251
+ {
252
+ if (go == null) continue;
253
+ if (go.transform.parent != null) continue;
254
+ if (!go.scene.isLoaded) continue;
255
+ if (IsExcludedGameObject(go, includeMarkedObjects)) continue;
256
+ if (IsEditorInternalObject(go)) continue;
257
+
258
+ Object.DestroyImmediate(go);
259
+ }
260
+ }
261
+ }
262
+ }
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 4594a5f81e5beaa45b83fc17373526cc
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "MooseRunner.helper",
3
+ "rootNamespace": "MooseRunner.helper",
4
+ "references": [
5
+ "UniTask",
6
+ "MooseRunner.Runtime"
7
+ ],
8
+ "includePlatforms": [],
9
+ "excludePlatforms": [],
10
+ "allowUnsafeCode": false,
11
+ "precompiledReferences": [
12
+ "nunit.framework.dll"
13
+ ],
14
+ "autoReferenced": false,
15
+ "defineConstraints": [],
16
+ "versionDefines": [],
17
+ "noEngineReferences": false
18
+ }
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: 4e4df4892916ee748934a507e8875051
3
+ AssemblyDefinitionImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
@@ -0,0 +1,27 @@
1
+ fileFormatVersion: 2
2
+ guid: 4b0d06f854cbfcb0fa36cc3d79c7e1b0
3
+ PluginImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ iconMap: {}
7
+ executionOrder: {}
8
+ defineConstraints: []
9
+ isPreloaded: 0
10
+ isOverridable: 1
11
+ isExplicitlyReferenced: 0
12
+ validateReferences: 0
13
+ platformData:
14
+ - first:
15
+ Any:
16
+ second:
17
+ enabled: 1
18
+ settings: {}
19
+ - first:
20
+ Editor: Editor
21
+ second:
22
+ enabled: 1
23
+ settings:
24
+ DefaultValueInitialized: true
25
+ userData:
26
+ assetBundleName:
27
+ assetBundleVariant:
Binary file