# 7. Test Framework Pitfalls
Part of [[Unity Test Framework]]. Previous: [[6. Performance Tests Coverage and Command Line]].
> [!note] Verification status
> Pitfalls below are drawn from the Test Framework changelog (deprecated "Play Mode tests for all assemblies", log handling, batchmode `WaitForEndOfFrame`, domain-reload fixture resets) and from standard Unity test practice. UI Test Framework (`com.unity.ui.test-framework`) is listed as a **core package** on 6000.5; its APIs are **not verified** in this series and are not used in the examples. **Code not compiled in Unity.**
## 7.1 Pitfalls
1. **Putting tests in a regular asmdef (or in `Assets/` with no asmdef and hoping the old project setting saves you).** The "Enable Play Mode tests for all assemblies" switch is deprecated and was removed from the Test Runner UI. Use test assemblies (part 1).
2. **Testing `MonoBehaviour` logic that could have been a plain C# type.** If `Update` is a five-line call into `StatStack.Evaluate()`, test `StatStack`. Leave `[UnityTest]` for the part that truly needs a frame.
3. **Shared static state.** A singleton `GameSession.Instance` that is not reset in `[TearDown]` makes tests depend on run order. `-randomOrderSeed` will eventually expose this. Prefer constructor injection, or reset the singleton in teardown, or both.
4. **Leaking scenes and GameObjects.** Always destroy what you create. Load fixture scenes additively and unload them in `[UnityTearDown]`. A cancelled run should restore scene setup (Test Framework 1.4.5), but do not rely on that instead of writing teardown.
5. **`Destroy` vs `DestroyImmediate`.** In Edit Mode, `Destroy` does not destroy until later (and there may be no later). Use `DestroyImmediate` in Edit Mode. In Play Mode, `Destroy` is the right default.
6. **Unexpected `Debug.LogError`.** An error log fails the test unless you `LogAssert.Expect` it. A leftover error from a previous test, or from a shader compile, can also fail you. `[TestMustExpectAllLogs]` makes the contract even tighter — use it when you mean it.
7. **Waiting forever.** Prefer `for (int i = 0; i < 30; i++) { if (condition) break; yield return null; }` plus `Assert.Fail` to an unbounded `while`. `WaitForEndOfFrame` in batchmode has hung Player runs in the past.
8. **Domain reload amnesia.** After `RecompileScripts` / `WaitForDomainReload`, instance fields are gone. So are `static` fields. Do not "remember" data across a reload in a field.
9. **Asserting floats without a delta.** Physics, animation and even simple `v^2/2g` will flake.
10. **Running performance tests in the same job as correctness tests** on a noisy machine, then treating a spike as a product bug.
11. **Touching real production scenes.** A test that opens `Level03` will break when a designer moves a prop. Use a fixture scene.
12. **Async test return types.** `async Task` is supported. `async Awaitable` as the test method itself is not a documented Test Framework return type. Await production `Awaitable` methods from a `Task` test only if you have a verified conversion; otherwise use `[UnityTest]` and yield.
13. **Quest / Android Player timeouts.** If the Player never starts, it may be the connection or a pre-run timeout (the 1.4.4 changelog calls out Quest headsets), not your first assertion. Confirm the device connection the same way you would for a regular development build ([[4.Quest 2 Testing and Deployment]]).
14. **Edit Mode tests that write assets and forget to clean them up.** If you `CreateAsset` in a test, delete it in teardown or you will dirty the repo. Prefer `ScriptableObject.CreateInstance` without saving.
## 7.2 Flaky-test protocol (for class and for CI)
When a test fails only sometimes:
1. Run it 20 times with `-repeat 20`.
2. Run the suite with `-randomOrderSeed` (try a few seeds).
3. Ask: is this timing, static state, or a real race in production code?
4. If it is timing, wait for a condition with a frame cap, not a magic `WaitForSeconds(0.2f)`.
5. If it is production, fix production. Do not sprinkle `yield return null` until CI goes green.
## 7.3 UI Test Framework
Unity 6000.5 also ships **UI Test Framework** (`com.unity.ui.test-framework`) as a core package, aimed at UI Toolkit. It is the right place to look once you want to query a visual tree and click a button in a test, especially with [[UI Toolkit and Diegetic UI]] and [[7.UI Toolkit Pitfalls and Performance]]. This series does not document its API — open the package manual in your Editor before you teach it, and treat any sample you find online as version-sensitive.
Until then, test the *model* behind the HUD (health, inventory counts, quest flags) in Edit Mode, and keep UI tests off the critical CI path until they are stable.
## 7.4 A small checklist before you call the suite "done"
- [ ] Edit Mode tests live in an Editor-only test asmdef
- [ ] Play Mode tests live in a test asmdef that can also build to a Player
- [ ] Categories distinguish `Performance` from correctness
- [ ] A command-line Edit Mode run produces XML on a failing test
- [ ] Fixture scenes are not in the production Build Profile scene list
- [ ] No test depends on the currently open scene or on run order
## Official docs
- Running tests: https://docs.unity.com/en-us/engine/6000.5/manual/scripting/test-framework-introduction/running-tests
- Core packages (Test Framework, UI Test Framework): https://docs.unity.com/en-us/engine/6000.5/manual/packages-list/packages-all/pack-core
- Test Framework 1.7 changelog: https://docs.unity3d.com/Packages/
[email protected]/changelog/CHANGELOG.html