Search Unity

Question What's the most performant way to reset a scene?

Discussion in 'Testing & Automation' started by AcademyOfFetishes, Mar 3, 2019.

  1. AcademyOfFetishes

    AcademyOfFetishes

    Joined:
    Nov 16, 2018
    Posts:
    219
    I have a bunch of Editor Tests. At the start of each one, it runs this code:

    Code (CSharp):
    1.     public static void ReloadLevelScene()
    2.     {
    3.         var scene = EditorSceneManager.GetSceneByPath("Assets/Scenes/Level.unity");
    4.         Assert.True(scene != null);
    5.         EditorSceneManager.OpenScene("Assets/Scenes/Level.unity");
    6.     }
    That last line takes 100ms and I think it's the slowest part of my tests.

    My question is, is there a more efficient way to reset a scene? The only reason I'm calling this is because I don't want test pollution.
     
  2. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    I don't think Unity has any out-of-the-box solution fo resetting a scene (well, perhaps using the Undo mechanism, but I am not sure that will work in this case).

    Depending on the changes that are done to the scene, you may be able to "work around" the issue by structuring it in a particular way maybe so that you can later wipe all new game objects that are not under a particular root object, or some system similar to that.
     
    AcademyOfFetishes likes this.
  3. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,332
    Does the scene need to be open for your tests to work? The test runner does make an empty scene for you for every test.

    There's a quite large overhead with loading scenes. If you need some setup objects, creating them from script instead of loading the scene will probably be faster.
     
    AcademyOfFetishes likes this.
  4. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,655
    You could also look into loading the scene once per fixture, rather than once per test - if your tests are just checking things about the scene, or making very limited modifications that they can clean up themselves, then reloading the whole scene is likely to be overkill.

    Reloading the whole scene for each test is the best strategy from a test isolation point of view, but you will always need to balance that against other concerns, like test execution time. Perfectly isolated tests will not be much use if they are so slow that nobody ever bothers to run them :)
     
    AcademyOfFetishes likes this.
  5. AcademyOfFetishes

    AcademyOfFetishes

    Joined:
    Nov 16, 2018
    Posts:
    219
    Yes and no. The tests assume there's a GO in the scene named Level with some objects under it. It would be really easy to turn that into a prefab and just create it in a blank scene. But how would I prevent the next test from being polluted from creating the Level in the previous test?
     
  6. AcademyOfFetishes

    AcademyOfFetishes

    Joined:
    Nov 16, 2018
    Posts:
    219
    In my case, I'm mutating the scene on almost every test, so they almost all fail if I do that.
     
  7. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,655
    Are they mutating the scene in ways that you could clean up? For example, if they're just adding new objects, you could make the test add the objects via a helper method which records the new object into a list, and then in the Teardown method you delete all the objects on the list.
     
  8. AcademyOfFetishes

    AcademyOfFetishes

    Joined:
    Nov 16, 2018
    Posts:
    219
    With enough effort, I could reverse everything. I actually tried to go down this route: In my case, it should be as simple as copying an object called
    Level
    at the start of my test, then replacing the mutated one with the copy at the end of the test. Unfortunately, this "didn't work." After the 3rd test ran, I got errors about fields not being populated. I don't know why it was always the 3rd one that failed. This even happened when I commented out tests to have a different 3rd one... Depending on what I tried, sometimes it would say my copy of
    Level
    was already destroyed, even though I had no code anywhere trying to destroy it.

    I wasn't able to figure out why this was happening and I don't think I'd ever be able to without this feature existing: https://forum.unity.com/threads/is-...t-and-explore-the-scene-in-the-editor.638221/