Write your first automated test for your own behaviour
How to write a real Play Mode test against your own TsvrcBehaviour subclass, once
the testing assemblies are wired into your project, using
TsPlayModeTestBase.
Steps
-
Extend
TsPlayModeTestBaseand start ClientSim in a[UnityTest]:public class RoundRefereeTests : TsPlayModeTestBase{[UnityTest]public IEnumerator RoundReferee_StartsOnBegin(){yield return StartClientSim(); -
Build your project's generated root from code instead of loading a saved scene, and attach a fresh instance of the behaviour under test:
var builder = BuildTsRoot<TsGenerated>();var referee = builder.WithNew<RoundReferee>("RoundReferee");builder.Build();Any root field your test never touches (a Global, a Pool slot) is auto-filled with a bare stand-in before
Build()runs, so a generated stage that unconditionally iterates every field of its module never throws on one your test doesn't care about. -
Drive the behaviour and assert on it:
referee.BeginRound();Assert.IsTrue(referee.IsProcessRunning());}}
Reaching a private field or method
Use PrivateFieldAccess instead of making something
public just so a test can see it:
int remaining = PrivateFieldAccess.GetField<int>(referee, "_remainingMilliseconds");
Asserting an event actually fired
Wire a TsCallbackRecorder as the subscriber instead of
writing a one-off listener class for every test:
var recorder = builder.WithNew<TsCallbackRecorder>("Recorder");
referee.TsSubscribe(recorder, RoundReferee.OnRoundEndedEvent, nameof(TsCallbackRecorder.CallbackA));
// ...drive the round to completion...
Assert.AreEqual(1, recorder.CallbackACount);
Why this shape
See Testing your world for the full reasoning behind
building a root from code instead of a saved scene, the two Play Mode testing defects
patched automatically for any TsPlayModeTestBase subclass, and why the three testing
assemblies are split the way they are.