Handling inaccuracies between update loop and time in playmode tests.
Hello, I have very simple test where I need to move back and forth and assert position. However after couple of iterations, the inaccuracies between time and update loop always make the test fail. I even tried adding offset to each assert, so that the inaccuracies would be accounted for, but without success.
It also happens in both cases when my movement logic is in Update and when it is in FixedUpdate
The issue also comes up in earlier iterations when I change time scale like this, but it does happen even without it (not as much with lower time scales and FixedUpdate).
[ OneTimeSetUp ]
public void OneTimeSetUp () {
Application.targetFrameRate = 60;
Time.timeScale = 10.0f;
}
I tried googling but could not find anything related. How can I deal with this issue? Relevant code:
var maxToleranceDiff = Time.fixedDeltaTime * movement.Speed + 0.001f;
Debug.Log("Tolerance: " + maxToleranceDiff.ToString());
var offBy = 0f;
for (int i = 0; i < 100; i++)
{
movement.Direction = new Vector3(-1, 0, 0);
yield return new WaitForSeconds(1);
Assert.AreApproximatelyEqual(
-1 * movement.Speed + offBy,
movement.transform.position.x,
maxToleranceDiff
);
offBy = -1 * movement.Speed - movement.transform.position.x;
movement.Direction = new Vector3(1, 0, 0);
yield return new WaitForSeconds(1);
Assert.AreApproximatelyEqual(
0f - offBy,
movement.transform.position.x,
maxToleranceDiff
);
offBy = movement.transform.position.x;
}
Edit: I came to a solution where instead of WaitForSeconds I used WaitForFixedUpdate for N times and then counted with fixedDeltaTime * N.
My conclusion is that having the logic inside Update loop is very bad for testing because it may be impossible to handle the inacurracies. And FixedUpdate loop, while it may be fine in normal time scales, it will fail in sped up tests if mixed with yielding for seconds because you may miss some updates due to performance reasons and thus assert "too early".
After some testing I found out that WaitForSeconds(1) can easily take 2 seconds and thus be 1 second late. Takeaway is: do not use WaitForSeconds if you need something to be exact.