Search code examples
c#unity-game-engineenumerator

How to detect empty IEnumerator function calls during unit testing?


I'm working with Unity's play mode test unit that run on Enumerator function (aka. Coroutine).

Inside the test, they will call more sub routines, some of them are ordinary function, some of them are IEnumerator function, thus allowing the test to run and span over several frames.

[UnityTest]
public IEnumerator Test1( )
{
    SubAction1( );
    yield return SubAction2( );
}

void SubAction1( ) // A sub function that does not need to run over several frames
{ 
}

IEnumerator SubAction2( ) // A sub function that need to span over several frames
{
    ... // More code
    yield return WaitForSeconds( 1 );

    ... // More code
    while( condition == false )
        yield return null; // Wait until condition becomes true to continue

    ... // More code
}

If I misuse the SubAction2 and call it just like ordinary function:

SubAction2( ); // without yield return, this is misuse

it would still compile and run silently! This will make SubAction2 does not execute all of its code. It is just a small typo, but this one could cause the entire test to fail silently! SubAction2 is an IEnumerator function, and meant to be called with yield return.

Do I have some way to sanity check, or enforce that this function should be called with 'yield return'?

I'm looking for any possible solution of:

  • Some C# language pattern to prevent such misuse, either on runtime or compile time.
  • OR some magic attribute that will help checking this misuse?
  • OR an editor warning that help detecting such misuse (Such as option in VisualStudio intellisense?)

My solution for now is to name all IEnumerator function with some prefix like "DoSubAction2" and then do a regular expression search to find the occurrence of "Do" function calls without "yield return" to manually check for misuse.


Solution

  • After checking with available options, I decided to go with Visual Studio VSIX extension and write a Roslyn analyzer. Such misuse will be prompted in IDE as warning.

    enter image description here

    For the sake of completion, I have uploaded all analyzer/fixer code there: Github

    These are guides I used:

    Other relevant stuff

    • According to @derHugo. Looks like Resharper (requires paid subscription) will also warn about this pattern.
    • There is also an open source project Roslynator2019 which bundle tons of code analyzers which focus on code design in general C# and it is free. But sadly it does not include my case.
    • Looks like C# async-await could also be used with Unity unit test. It just need some enclosure like what UniTask provided.

    I would like to thank everyone in the discussion. And for readers, I hope you learned something new today.