Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when writing or running Unity tests - Unity Test Framework EditMode vs PlayMode, test assembly definitions, testing plain C# and ScriptableObjects, PlayMode scene/physics/input tests, batchmode CLI with result XML, coverage, and the dotnet test fallback when no editor is installed.
インストール方法を見るインストールする前に、エージェントに与えられる指示の中身を確認できます。
The Unity Test Framework (NUnit 3 underneath) runs tests in two modes. EditMode tests run in the editor without entering Play mode — fast, ideal for plain C# rules, ScriptableObjects and editor tooling. PlayMode tests run the player loop — needed for scenes, physics, coroutines and input, and slower. Most tests should be EditMode tests against plain classes (testable-game-logic).
Core principle: EditMode first; PlayMode only for behaviour that needs the player loop. Read the result XML, not the log tail.
| Question | Mode | Typical setup |
|---|---|---|
| Does the damage/cooldown/inventory rule compute correctly? | EditMode | new the plain class |
| Is every shipped definition valid? | EditMode | AssetDatabase.FindAssets |
| Does a ScriptableObject-driven system behave? | EditMode | ScriptableObject.CreateInstance<T>() |
| Does the character land on the floor / trigger fire? | PlayMode | load a test scene, WaitForFixedUpdate |
| Does pressing Jump jump? | PlayMode | InputTestFixture |
| Does the coroutine/Awaitable sequence finish? | PlayMode | [UnityTest] yielding frames |
{
"name": "Tests.EditMode",
"references": ["Game.Core", "Game.Runtime", "UnityEngine.TestRunner", "UnityEditor.TestRunner"],
"includePlatforms": ["Editor"],
"overrideReferences": true,
"precompiledReferences": ["nunit.framework.dll"],
"defineConstraints": ["UNITY_INCLUDE_TESTS"],
"autoReferenced": false
}
PlayMode assemblies leave includePlatforms empty (any platform) and drop UnityEditor.TestRunner unless they need editor APIs. Tests live where the repository keeps them (often Assets/Tests/EditMode and Assets/Tests/PlayMode); follow its naming — Method_Scenario_Expected when there is none.
public class InventoryTests {
[Test] public void Add_BeyondStackLimit_OverflowsToNewSlot() {
var potion = ScriptableObject.CreateInstance<ItemDefinition>();
potion.Configure(id: "potion", maxStack: 5);
var inv = new Inventory(slots: 4);
inv.Add(potion, 7);
Assert.That(inv.Slots[0].Count, Is.EqualTo(5));
Assert.That(inv.Slots[1].Count, Is.EqualTo(2));
Object.DestroyImmediate(potion);
}
[TestCase(0f, 100)] [TestCase(0.5f, 50)] [TestCase(1f, 0)]
public void Damage_ByArmorFraction_ReducesLinearly(float armor, int expected) =>
Assert.That(DamageMath.Apply(100, armor), Is.EqualTo(expected));
}
Destroy every object a test creates (DestroyImmediate in EditMode, Destroy in PlayMode, or in [TearDown]) — leaked objects leak into the next test.
public class PlayerPhysicsTests {
[UnitySetUp] public IEnumerator Load() { yield return SceneManager.LoadSceneAsync("Test_FlatFloor"); }
[UnityTest] public IEnumerator Player_DroppedAboveFloor_BecomesGrounded() {
var player = Object.Instantiate(TestPrefabs.Player, new Vector3(0, 3, 0), Quaternion.identity);
for (int i = 0; i < 100; i++) yield return new WaitForFixedUpdate();
Assert.That(player.GetComponent<GroundCheck>().IsGrounded, Is.True);
}
}
public class JumpInputTests : InputTestFixture {
[UnityTest] public IEnumerator PressingSpace_MakesPlayerJump() {
var keyboard = InputSystem.AddDevice<Keyboard>();
var player = Object.Instantiate(TestPrefabs.Player);
yield return null;
Press(keyboard.spaceKey);
yield return new WaitForFixedUpdate();
Assert.That(player.GetComponent<Rigidbody>().linearVelocity.y, Is.GreaterThan(0f));
}
}
Test_*.unity) added to the test build, not production levels.for up to N fixed updates) instead of WaitForSeconds guesses.Time.timeScale can speed slow sequences, but physics results change with the step — assert outcomes, not exact positions.UNITY="/Applications/Unity/Hub/Editor/$(sed -n 's/m_EditorVersion: //p' ProjectSettings/ProjectVersion.txt)/Unity.app/Contents/MacOS/Unity"
mkdir -p /tmp/tt-<task key>
"$UNITY" -batchmode -nographics -projectPath . -runTests -testPlatform EditMode \
-testResults /tmp/tt-<task key>/editmode.xml -logFile /tmp/tt-<task key>/editmode.log
"$UNITY" -batchmode -projectPath . -runTests -testPlatform PlayMode \
-testResults /tmp/tt-<task key>/playmode.xml -logFile /tmp/tt-<task key>/playmode.log
-quit with -runTests; the editor quits when the run ends.-nographics for PlayMode tests that render or capture (game-visual-self-review).-testFilter "Game.Tests.InventoryTests" or -testCategory narrows a run while iterating.grep -o 'result="[A-Za-z]*" total="[0-9]*" passed="[0-9]*" failed="[0-9]*"' editmode.xml | head -1, and grep 'error CS' editmode.log for compile errors (a compile error means zero tests ran, which is not a pass). A non-zero exit code is a failure.Coverage, when the Code Coverage package is installed: add -enableCodeCoverage -coverageResultsPath /tmp/tt-<task key>/coverage -coverageOptions "generateAdditionalMetrics;assemblyFilters:+Game.*".
Game.Core (noEngineReferences: true).<!-- /tmp/tt-<task key>/core-tests/CoreTests.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup><TargetFramework>net8.0</TargetFramework><Nullable>disable</Nullable></PropertyGroup>
<ItemGroup>
<Compile Include="<repo>/Assets/Scripts/Core/**/*.cs" />
<Compile Include="<repo>/Assets/Tests/EditMode/Core/**/*.cs" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.*" />
<PackageReference Include="NUnit" Version="3.*" />
<PackageReference Include="NUnit3TestAdapter" Version="4.*" />
</ItemGroup>
</Project>
dotnet test /tmp/tt-<task key>/core-tests — Unity's C# language version is older than .NET 8's default, so set <LangVersion>9.0</LangVersion> if the repo targets it, to avoid using features Unity cannot compile.RAN: dotnet test (Core) 18/18 and NOT RUN: EditMode/PlayMode — Unity <version> not installed.error CS.WaitForSeconds(2) as the synchronisation in a test.Game.UI to test gameplay.まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when the diff adds or changes an endpoint, resolver, RPC, job or query that takes an object id, a role check, a request binding or a tenant filter - BOLA/IDOR, function-level authorization, mass assignment and tenant scoping
日本語の概要は準備中です。原文の説明を表示しています。
Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal
日本語の概要は準備中です。原文の説明を表示しています。
Use when a task changes any screen, form, dialog, menu or control - Lighthouse/axe scan of the changed screens, a keyboard walk, and the thresholds that fail a task
日本語の概要は準備中です。原文の説明を表示しています。
How to work a task returned with review, QA or UAT findings. Use when a task is in need_revision or PR review comments are in your context.
日本語の概要は準備中です。原文の説明を表示しています。
Use when deciding whether a request needs an analiz task before implementation - the conditions that require the architect's analysis versus going straight to implementation
日本語の概要は準備中です。原文の説明を表示しています。