How to run Editor testing in multiple scene

Hello guys,
I have a quick question.
I wrote a couple of tests using the unity test runner tool. All of them are Editor testing, so no need to run in play mode.

Now I was wondering if is possible to run those testing in multiple scenes. Because now, when I press play, only the loaded scene is been tested, but I want to run those test on multiple scenes instead of manually switch scene every time.

Maybe by using some terminal tool is possible to tell Unity to do us… any ideas?

Thanks

In editor mode you can write an editor script that changes the scene using: Unity - Scripting API: SceneManagement.EditorSceneManager.OpenScene

Thanks, but how do I use it?
Assume I have 10 scene to test, I load one scene and the test starts automatically. But when the test is finished, how do i move to next scene to test?

I need something that can iterate through a list of scenes and run the test in each scene.

Thanks.

I’m not sure how you’re running your tests. Do you use an editor script to do that or some kind of external tool?

You can use ValueSource attribute like this:

    public class LevelValidationTests
    {
        public static IEnumerable<string> LevelTestCases
        {
            get { return new List<string> {"Level-1", "Level-2"}; }
        }

        [UnityTest]
        public IEnumerator LevelIsValid([ValueSource("LevelTestCases")] string levelName)
        {
            yield return LoadLevel(levelName);

            Assert.IsTrue(true);
        }
   
        [TearDown]
        public void UnloadLevel()
        {
            SceneManager.UnloadSceneAsync(sceneToUnload);
        }

        private string sceneToUnload;

        private IEnumerator LoadLevel(string levelName)
        {
            sceneToUnload = levelName;

            var loadSceneOperation = SceneManager.LoadSceneAsync(levelName);
            loadSceneOperation.allowSceneActivation = true;

            while (!loadSceneOperation.isDone)
                yield return null;
        }
    }

The code should run fine in both edit and play modes.

Also scene names doesn’t have to be hardcoded, LevelTestCases can contain any code you wish. I am for example getting my scene names from scriptable object.

1 Like

Thanks again for the answer

I run my test through an editor script, here a simple example class:

using UnityEngine;
using NUnit.Framework;

public class PlayerTester
{

    [Test]
    public void OnlyOnePlayerInTheScene()
    {
        Assert.IsTrue(GameObject.FindGameObjectsWithTag(ProjectIds.TagIDs.Player).Length == 1, "There are " + GameObject.FindGameObjectsWithTag(ProjectIds.TagIDs.Player).Length + " player in the scene");
    }

    [Test]
    public void OnlyOnePlayerMoving()
    {
        Assert.IsTrue(GameObject.FindObjectsOfType<PlayerMoving>().Length == 1, "Error: There are " + GameObject.FindObjectsOfType<PlayerMoving>().Length + " player in the scene");
    }
}

Then I use test runner in edit mode to run the test

Any idea how to run this code in every scene and in case something fails, how to know which one is the scene who failed?
Thanks again

Thanks for the answer, I see your point on load one or more scene, but the question is how can I run my tests on the scenes that I’ve loaded?
I have 5 classes for example, and each one performs some kind of test. I want to load a scene and run those test, then if everything is all right, move to the next scene an do the same.

Can’t you change your flow and run one test on every scene and then move to the next test?

Assume I have 50 scenes, is an incredible waste of time to run all the tests manually XD.
There must be a way to automate the workflow…

You CAN run all the tests on all the scenes automatically using the solution I sent you. You just have to at the start of each test to load a scene and after the test is finished to unload it. And that is all right, because each test should be atomic.

3317191--257936--test runner.png

Hello,
si I finally manage to try your code, but I have an error:

EditMode test can only yield null
UnityEditor.EditorApplication:Internal_CallUpdateFunctions()

Maybe is not possible in edit mode?
I just found this article: https://blogs.unity3d.com/2017/08/18/verifying-the-scripting-docs-fun-with-editortests/

Maybe we have to use the [TestCaseSource] directive

It should be possible. There is nothing in my code that yields anything else than null. Could you post your test code?

Found the solution, here an example that works in editor mode:

public static readonly string[] ScenesToTest = new string[]
   {
        "Assets/SquareMaze/Scene/TestScene/TestGameScene.unity", "Assets/SquareMaze/Scene/TestScene/TestGameScene2TMP.unity"
   };

[TearDown]
    public void UnloadLevel()
    {
        EditorSceneManager.UnloadSceneAsync(sceneToUnload);
    }

    string sceneToUnload;

    void LoadLevel(string levelName)
    {
        sceneToUnload = levelName;
        EditorSceneManager.OpenScene(sceneToUnload);
    }

public void ObjectAreCenteredInCell([ValueSource("ScenesToTest")] string levelName)
{
        LoadLevel(levelName);
       ///DO YOUR TESR HERE
}

Ok, glad you got it working.

Note that this code:

        public class LevelValidationTests
        {
            public static IEnumerable<string> LevelTestCases
            {
                get { return new List<string> {"Level-1", "Level-2"}; }
            }
    
            [UnityTest]
            public IEnumerator LevelIsValid([ValueSource("LevelTestCases")] string levelName)
            {
                yield return LoadLevel(levelName);
    
                Assert.IsTrue(true);
            }
      
            [TearDown]
            public void UnloadLevel()
            {
                SceneManager.UnloadSceneAsync(sceneToUnload);
            }
    
            private string sceneToUnload;
    
            private IEnumerator LoadLevel(string levelName)
            {
                sceneToUnload = levelName;
    
                var loadSceneOperation = SceneManager.LoadSceneAsync(levelName);
                loadSceneOperation.allowSceneActivation = true;
    
                while (!loadSceneOperation.isDone)
                    yield return null;
            }
        }

doesnt work with Unity 5.6.4f1
but works fine with Unity2017.3