Skip to content

t1k:unity:dots-testing:unit-testing

FieldValue
Moduledots-testing
Version2.1.7
Efforthigh
Tools

Keywords: DOTS, ECS testing, NUnit, unit testing

/t1k:unity:dots-testing:unit-testing

Foundation: /dots-ecs-core (ISystem, components, queries). Combat formulas: see shared constants in your core module.

File: Packages/[your-package]/Tests/EditMode/[YourTestBase].cs

Base class for all DOTS package tests. Creates isolated World with full system pipeline:

public abstract class DOTSTestBase
{
protected World m_World;
protected EntityManager m_Manager;
[SetUp] → new World("TestWorld"), registers ALL system groups + systems in order
[TearDown] → World.Dispose()
protected void Update() → SimulationSystemGroup.Update() (runs full pipeline)
protected Entity CreateStatsEntity(str, vit, intel) → entity with BaseStats + derived
protected Entity CreateCombatEntity(hp) → stats + Health/Mana/DamageEvent/DeadTag/etc
protected Entity CreateFullEntity(position, teamId) → combat + LocalTransform/MoveSpeed/Nav
}

Key: Update() runs the FULL system pipeline (Stats → Combat → AI → Nav → Skills → Inventory → Spawning). To isolate a single system, override SetUp() and register only the system under test.

File: Packages/[your-package]/Tests/EditMode/[YourPackage].Tests.EditMode.asmdef

Required settings:

  • allowUnsafeCode: true
  • overrideReferences: true with nunit.framework.dll
  • defineConstraints: ["UNITY_INCLUDE_TESTS"]
  • includePlatforms: ["Editor"]
  • References: ALL your package modules + Unity.Entities, Unity.Transforms, Unity.Mathematics, Unity.Collections, Unity.Burst, Unity.Jobs
CategoryFixturePattern
Pure utility (SpatialHashGrid)None neededDirect struct tests, Allocator.Temp
Component data validationNone neededAssert default values, factory methods
Single system (isolated)DOTSTestBase + override SetUpRegister one system, create minimal entities
Integration (multi-system)DOTSTestBaseUse Update() for full pipeline
PerformanceDOTSTestBaseStopwatch around Update() with N entities

Rule: ALL test files MUST be placed in a subfolder matching their library module. Never leave test files at the root EditMode/ level (except DOTSTestBase.cs and cross-cutting integration/performance tests).

Packages/<package>/Tests/
├── EditMode/
│ ├── <Package>.Tests.EditMode.asmdef
│ ├── <TestBase>.cs # Shared fixture (ONLY base class at root)
│ ├── AI/ # AI module tests
│ │ └── <SystemName>Tests.cs
│ ├── Boss/ # Boss module tests
│ ├── Combat/ # Combat module tests
│ ├── Core/ # Core module tests (sprites, lifetime, etc.)
│ ├── Inventory/ # Inventory module tests
│ ├── Navigation/ # Navigation module tests (crowds, sideview)
│ ├── Skills/ # Skills module tests (projectiles, AoE, etc.)
│ ├── Spawning/ # Spawning module tests
│ ├── Stats/ # Stats module tests
│ ├── Structures/ # Structures module tests (tower, barracks)
│ ├── SpawnIntegrationTests.cs # Cross-module integration (root OK)
│ ├── CombatIntegrationTests.cs # Cross-module integration (root OK)
│ └── PerformanceTests.cs # Scalability benchmarks (root OK)
└── PlayMode/
└── <Package>.Tests.PlayMode.asmdef

Naming: <SystemName>Tests.cs — matches the system under test. One file per system. Folder: Must match library module path (e.g., Runtime/Combat/Systems/X.cs → Tests/EditMode/Combat/XTests.cs).

Target ratio: 95% EditMode, 5% PlayMode.

EditMode DOTSTestBase creates a full ECS world and runs World.Update() synchronously — it tests ALL system logic including ordering, ECB flush, and multi-system integration. No rendering or frame timing required.

When to use PlayMode (only these 3 scenarios)

Section titled “When to use PlayMode (only these 3 scenarios)”
  1. Rendering verification — entities visible on screen, frustum culling, ChunkWorldRenderBounds integrity
  2. Multi-frame time progression — BDP throttling over real frames, spawn timers depending on real Time.DeltaTime accumulation
  3. SubScene baking integration — verifying baked entities match authoring after full SubScene load
  • Individual system logic → EditMode
  • Component data validation → EditMode
  • System ordering → EditMode (World.Update() respects [UpdateBefore/After])
  • Entity queries and filters → EditMode
  • 10-20x slower than EditMode (scene load + frame waits)
  • CI/CD friction: requires GPU or xvfb virtual framebuffer on Linux
  • Flaky: timing-sensitive, frame-dependent
  • MCP alternative: dots-validator agent + validation_snapshot tool does live Play mode verification without test framework overhead — prefer this for rendering/runtime checks

MANDATORY: Play Mode Validation After Implementation

Section titled “MANDATORY: Play Mode Validation After Implementation”
  • ALWAYS run Play mode validation (via MCP manage_editor enter Play or dots-validator) after implementing new systems
  • EditMode tests verify logic only — they do NOT catch: SubScene baking failures, system ordering bugs in real SimulationSystemGroup, rendering issues, missing components from bakers, ECB playback timing
  • Minimum check: Enter Play → read_console → zero errors → exit Play
  • Full check: Use /gk:playtest (dots-validator agent) for entity spawn, movement, combat, rendering verification
  • EnabledRefRW<T> in SystemAPI.Query generics implicitly filters to enabled-only — use .WithPresent<T>() to include disabled entities
  • SystemAPI.GetSingletonEntity<T>() throws for IEnableableComponent types — use Query<T>().WithEntityAccess() iteration instead
  • manifest.json needs "testables": ["com.the1studio.dots-puzzle"] for UPM package test discovery in Test Runner
  • ECB-spawned entities need TWO Update() calls in tests: first creates via ECB, EndSimECB playback makes them exist for second update
  • Assert.Ignore stubs give false coverage confidence — 3 test files in dots-progression use Assert.Ignore("TODO") for every method; these show green in Test Runner but cover nothing. Any method body that is ONLY Assert.Ignore(...) must be filed as a tracked issue, not silently committed. Source: review-260520-round6-test-coverage.md §T3
Terminal window
# EditMode (fast, no play mode)
unity-editor -batchmode -nographics -projectPath "<path>" \
-runTests -testPlatform EditMode -testResults ./TestResults.xml
# In Editor: Window > General > Test Runner > EditMode tab
TopicReference File
ISystem testing, ECB flush, EnableableComponent, DynamicBuffer, float comparisontest-patterns-guide.md
24 common gotchas (incl. buffer-handle invalidation) + what NOT to testgotchas-guide.md