Search Unity

How do I setup and teardown asset prefabs?

Discussion in 'Testing & Automation' started by StewedHarry, Jul 31, 2020.

  1. StewedHarry

    StewedHarry

    Joined:
    Jan 20, 2020
    Posts:
    45
    I'm new to unity and i'm trying to generate some playmode tests.

    The tests work individually, but when run in sequence they all fail. This is due to the instantiated prefabs overlapping and messing with the tests.

    The prefabs constitute the level and ai in the scene.

    A general outline of my test is as follows:

    Code (CSharp):
    1. public class Test
    2.     {
    3.         private GameObject prefab =
    4.             AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Prefabs/prefab.prefab");
    5.  
    6.         [UnityTest]
    7.         public IEnumerator Do_Test()
    8.         {
    9.             var prefabInstance =
    10.                 Object.Instantiate(prefab, new Vector3(0, 0, 0), Quaternion.identity);
    11.             yield return null;
    12.             var Component = prefabInstance.GetComponent<Component>();
    13.             // Assert some stuff with component, etc...
    14.         }
    15.      
    16.         [UnityTest]
    17.         public IEnumerator Do_Test_two()
    18.         {
    19.             var prefabInstance =
    20.                 Object.Instantiate(prefab, new Vector3(0, 0, 0), Quaternion.identity);
    21.             yield return null;
    22.             var Component = prefabInstance.GetComponent<Component>();
    23.             // Assert some other stuff with component, etc... (this will fail)
    24.         }
    25.     }
    I have tried to add setup and teardown methods to delete the prefabs but they don't work:

    Code (CSharp):
    1.  public class Test
    2.     {
    3.         private GameObject prefab;
    4.          
    5.         private GameObject prefabInstance;
    6.      
    7.         [UnitySetUp]
    8.         public IEnumerator Init()
    9.         {
    10.             prefab =
    11.                 AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Prefabs/prefab.prefab");
    12.             yield return null;
    13.             prefabInstance =
    14.                 GameObject.Instantiate(prefab, new Vector3(0, 0, 0), Quaternion.identity);
    15.             yield return null;
    16.         }
    17.      
    18.         [TearDown]
    19.         public void Dispose()
    20.         {
    21.            // how can I delete the prefabs here?
    22.         }
    23. }
    If I try to add an Object.Destroy method in the teardown section I get the error:

    '[Error] Destroying assets is not permitted to avoid data loss.'

    Is there a proper way to setup and teardown GameObjects while testing?
     
  2. MajeureX

    MajeureX

    Joined:
    May 4, 2020
    Posts:
    13
    Do you need all the `yield return null` statements? If you change the [UnityTest] and [UnitySetUp] attributes to [Test] and [SetUp] respectively you can run your tests as normal methods rather than as coroutines.
     
  3. StewedHarry

    StewedHarry

    Joined:
    Jan 20, 2020
    Posts:
    45
    These are to make sure that the GameObjects are instantiated. Also, as far as i'm aware [UnityTest] is required to run tests in playmode. The coroutine is used to skip frames at runtime
     
  4. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,656
    UnityTest is not required for playmode, but indeed it is needed if you want to actually skip frames.

    When you did the Object.Destroy() call, you were applying that to the prefab, or the prefabInstance? You should only do it to the prefabInstance.
     
  5. StewedHarry

    StewedHarry

    Joined:
    Jan 20, 2020
    Posts:
    45
    I found the solution to my problem. It was a test for a scene using Unity's ML Agents machine learning framework. Training is coordinated by a singleton class and this meant there was some continuity between tests behind the scenes (I'm not sure what). I fixed it using:

    Code (CSharp):
    1. [TearDown]
    2.         public void TearDown()
    3.         {
    4.             Academy.Instance.Dispose();
    5.         }
     
  6. MajeureX

    MajeureX

    Joined:
    May 4, 2020
    Posts:
    13
    Glad you figured it out :)