Author and run the Unity game-engine Test Framework (`com.unity.test-framework`, currently v1.8). Distinct from the ThrowTheSwitch Unity C testing library at throwtheswitch.org/unity - the two tools share only a name. Covers package install via Package Manager, the EditMode vs PlayMode split, the [Test] / [UnityTest] / [SetUp] / [TearDown] / [UnityPlatform] attributes, assembly-definition setup (Editor folder vs asmdef with `includePlatforms` / `optionalUnityReferences: [TestAssemblies]`), Test Runner window, command-line batch invocation with `-runTests` / `-testPlatform` / `-testResults` / `-testFilter` / `-testCategory`, NUnit 3.5 assertion API, and CI integration. Use when the unit under test is C# Unity code that needs to exercise the Unity runtime or editor.
70
88%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
Disambiguation up front. This skill covers the
Unity game-engine Test Framework - the official Unity package
com.unity.test-framework documented at
docs.unity3d.com/Packages/com.unity.test-framework@latest.
It is distinct from the ThrowTheSwitch Unity C testing library at
throwtheswitch.org/unity (a
single-C-file unit-test framework for bare-metal MCUs). The two tools share
only a name; they have unrelated origins, APIs, and consumers. For the C
unit-test library, see the sibling skill unity-test-framework-c in the
qa-embedded plugin.
UTF is built on NUnit 3.5 and supports both Edit Mode and Play Mode across Standalone, Android, and iOS target platforms (per the package overview).
Versioning. UTF is currently v1.8; the stable doc links below pin to the v1.4 manual snapshot for durable URLs. Both describe the same package.
Composes with:
game-test-categories-reference
for what category of test each Unity test belongs to (functional
/ performance / etc.).platform-cert-overview-reference
for cert-gated requirements UTF tests should cover (XR-001
Title Stability, XR-074 Service Loss, XR-115 Controller add /
remove).multiplayer-state-machine-coverage
and
gameplay-recording-replay
for state-machine and replay-driven test patterns inside UTF
PlayMode tests.MonoBehaviour, GameObject, coroutines, scenes) or
editor (AssetDatabase, EditorWindow) APIs available.For C unit tests on the firmware side of a hybrid game build,
use unity-test-framework-c instead.
UTF "is shipped with the Unity Editor and should be automatically included in
any project created with Unity 2019.2 or later" (per the package overview). For
manual install, open Package Manager → + → "Add package by name…" →
com.unity.test-framework.
The Test Runner window is at Window → General → Test Runner (may be Window → Test Runner depending on Editor version).
Per the Edit Mode vs Play Mode tests page, Edit Mode tests "are only run in the Unity Editor and have access to the Editor code in addition to the game code".
Layout (two options):
Editor/.
Unity auto-scopes them to the Editor platform..asmdef with
"includePlatforms": ["Editor"].Minimal example:
using NUnit.Framework;
using UnityEngine;
namespace MyGame.Tests.EditMode
{
public class HealthComponentTests
{
[Test]
public void Damage_DeductsCorrectAmount()
{
var go = new GameObject();
var health = go.AddComponent<HealthComponent>();
health.Initialize(maxHealth: 100);
health.ApplyDamage(35);
Assert.AreEqual(65, health.Current);
}
[TearDown]
public void Cleanup()
{
// EditMode tests must clean up created GameObjects;
// they don't auto-tear-down between cases.
}
}
}The docs recommend the NUnit Test attribute rather than UnityTest unless
you need to yield special instructions in Edit Mode, or skip a frame / wait for
an amount of time in Play Mode.
PlayMode tests "execute as coroutines within the game runtime and can run standalone in a Player or within the Editor". Assembly definition:
{
"name": "MyGame.Tests.PlayMode",
"references": ["MyGame.Runtime"],
"optionalUnityReferences": ["TestAssemblies"],
"includePlatforms": []
}Per the edit-mode-vs-play-mode docs, the .asmdef must reference the code
under test ("references": ["NewAssembly"]), optionally include
"optionalUnityReferences": ["TestAssemblies"], and leave
"includePlatforms": [] empty to allow multiple target platforms.
Minimal example:
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace MyGame.Tests.PlayMode
{
public class EnemyAITests
{
[UnityTest]
public IEnumerator Enemy_PursuesPlayer_WithinRange()
{
var player = new GameObject("Player");
var enemy = Object.Instantiate(Resources.Load<GameObject>("Enemy"));
enemy.transform.position = new Vector3(10f, 0f, 0f);
yield return new WaitForSeconds(2f);
var distance = Vector3.Distance(player.transform.position,
enemy.transform.position);
Assert.Less(distance, 5f, "Enemy did not close on player");
}
}
}The [UnityTest] attribute, returning IEnumerator, lets the test yield
frames (yield return null), seconds (yield return new WaitForSeconds(2f)),
or custom yield instructions - necessary for any frame-driven behaviour.
The common attributes are [Test] (synchronous NUnit), [UnityTest]
(coroutine, yields frames/seconds), [SetUp] / [TearDown],
[OneTimeSetUp] / [OneTimeTearDown], [Category("Smoke")] (CLI-selectable),
and [UnityPlatform(...)]. The full cheatsheet with sources and the
ValueSource parameterisation note is in
references/attributes.md.
UTF is built on NUnit 3.5, so the full NUnit 3 assertion model applies -
Assert.AreEqual, Assert.Throws<T>(() => ...),
Assert.That(actual, Is.EqualTo(expected).Within(0.01f)), etc. Prefer the
NUnit Test attribute over UnityTest unless you need to yield special
instructions.
Window → General → Test Runner (path may be Window → Test Runner in older Editor versions). The window shows two tabs:
Click Run All, Run Selected, or right-click a fixture → Run to execute. Results display inline with stack traces on failure.
Invoke Unity in batch mode and treat the -testResults XML as the source of
truth (Unity has no common exit-code definition):
Unity \
-batchmode \
-projectPath "$PWD" \
-runTests \
-testPlatform PlayMode \
-testResults artifacts/playmode-results.xml \
-testCategory "Smoke" \
-logFile artifacts/unity.logThe full batch-mode flag table (-testFilter, -testPlatform,
-assemblyNames, ordering / retry flags), the Windows invocation, and the
exit-code caveat are in references/cli.md.
The -testResults XML is NUnit 3 result format. Surface result="Failed"
at the <test-run> level for the overall verdict, then enumerate
<test-case result="Failed"> for per-test detail; nunit-junit-xml
converters exist for JUnit consumers. The full schema example is in
references/results-and-ci.md.
Run UTF in CI via game-ci/unity-test-runner (or the bare batch-mode CLI),
upload the -testResults XML as an artifact, and cache the Library/ folder
across runs - Unity re-imports all assets without it, adding 5 - 15 min per
run. A complete GitHub Actions workflow is in
references/results-and-ci.md.
| Anti-pattern | Why it fails | Fix |
|---|---|---|
Using [UnityTest] everywhere | Slower than [Test] because each test enters play mode | Use [Test] unless you need to yield (per the edit-mode-vs-play-mode docs) |
Forgetting optionalUnityReferences: ["TestAssemblies"] | Test assembly isn't picked up by Test Runner | Add it per the PlayMode asmdef block above |
| Test asmdef references production asmdef but production has no public types | Tests can't compile | Use InternalsVisibleTo on production asmdef or expose minimal public surface |
Not cleaning up GameObjects between EditMode tests | Cross-test contamination | [TearDown] Object.DestroyImmediate(go) on every fixture |
| Trusting Unity process exit code in CI | No common definition for exit codes | Parse -testResults XML in CI |
Skipping the Library/ cache | 5 - 15 min asset reimport per CI run | actions/cache@v4 with the Library/ path |
| Confusing this skill with ThrowTheSwitch Unity (C) | Different tool with the same name | See unity-test-framework-c |
Known constraints (per the v1.4 manual index):
UnityTest - Windows Store Apps cannot run
[UnityTest] coroutine-style tests.ValueSource) - NUnit
[TestCase], [TestCaseSource] have historical caveats in UTF.[Repeat] attribute incompatibility - listed as a known limitation.[Retry] attribute causes InvalidCastException in PlayMode tests.Other practical limitations:
com.unity.testtools.codecoverage
package; not included by default.-username -password -serial) or a manual .ulf
license file; consult Unity's documentation for the current activation flow
before standing up CI.