Unit Test : How to create a custom Test Attribute that creates Edit & Play Unit test?

Hi,

I’m working on a big project and I have a few hundred play mode tests. Recently I decided to do a big refactor and I should now be able to convert many of my play mode tests to edit mode tests. My understanding is that EditMode tests are much faster compared to playmode tests.

But instead of converting the tests completely to EditMode I thought I could make them both PlayMode and EditMode test.

My solution was to do this In the play mode assembly:

[UnityTest] public virtual IEnumerator MyTestFunction_Unity() {
    yield return Utility.LoadNoDatabaseTestScene();
    MyTestFunction (Utility.GetInventorySystemManager());//gets it from the loaded scene its a Monobehavior singleton
}
[Test] public void MyTestFunction () { MyTestFunction (new UnitTestInventorySystemManager()); }
public void MyTestFunction (IInventorySystemManager manager){...}

Then in the edit mode assembly I inherit the class and override the function with the [UnityTest] attribute so that it can hide it. This way I am left only with the test with [Test] attribute.

So that works… but its a lot of clutter especially if I’ll be doing this for 100+ tests, and I could technically make a human error by testing the wrong function if I’m not careful when copy pasting the two test functions.

I was wondering if there was a way for me to create a custom attribute that would essentially do all of that for me.

So that I could be left with

[MyCustomInventorySystemManagerTest]
public void MyTestFunction (IInventorySystemManager manager){...}

I tried inheriting from UnityTestAttribute and I played around a bit but I do not know enough about Unit test building to get anything I want working.

So I was wondering if any of you would be able to help me with this.
Thanks for your time

I’m not clear on what problem you’re trying to solve by having the two functions. You’re trying to make it so that in playmode the scene gets loaded, but in edit mode it doesn’t, and you want to just use the singleton from the currently loaded/active scene?

So the play mode test should load a scene and get the singleton, Then it uses that as parameter for the test

The edit mode test creates a new object which inherits the same interface as the singleton so that I can also use it as a parameter for my test.

This allows me to test the Monobehavior singleton as parameter in play mode and in edit mode I can test using a custom object used purely for testing as paramter.

I hope that makes sense

In that case, I would unify the two in a SetUp and use a bit of conditional logic. Maybe something like:

[UnitySetUp]
public IEnumerator SetupInventorySystemManager()
{
    if (Application.isPlaying) {
       yield return Utility.LoadNoDatabaseTestScene();
       _inventorySystemManager = Utility.GetInventorySystemManager();
    }
    else
    {
       _inventorySystemManager = new UnitTestInventorySystemManager();
    }
}

You could also do #if UNITY_EDITOR around the else-block if that test class cannot exist in a player build. Would that solve your problem?

Oh, I didn’t know UnitySetUp was a thing I thought you could only do [SetUp].
I probably should have thought about using if(Application.isPlaying)
That might just work for me Thank you!