12. Setup and cleanup at build time
Perform work before and after the Player build phase.
Read time 3 minutesLast updated 20 days ago
Learning objectives
This section will introduce you to the hooks in the test framework for before and after the player build.
Intro and motivation
Sometimes it's necessary to change settings or prepare assets before a build for Play Mode tests. Similarly, it might be relevant to clean up things after the build. For this the test framework has two hookup points called PrebuildSetup and PostBuildCleanup.
In the Editor, the is invoked before the build and test run and the is invoked after the tests are completely done. This happens for both Edit Mode and Play Mode tests. When running Play Mode tests on a device, the Cleanup is already run right after the build is done, as the tests are happening in parallel on the device.
PrebuildSetupPostBuildCleanupThe simplest way of ensuring a test has a and is by implementing and respectively in your test class.
PrebuildSetupPostBuildCleanupIPrebuildSetupIPostBuildCleanupOften the setup and cleanup will be interacting with code in the assemblies. These are not available when running on a device, but we want our built-in setup and cleanup code to stay in the test class. For this, it's recommended to wrap the Editor-related code lines in defines. For example:
UnityEditor#if UNITY_EDITORpublic class MyTestClass : IPrebuildSetup{ [Test] public void MyTest() { } public void Setup() { #if UNITY_EDITOR UnityEditor.EditorSettings.serializationMode = SerializationMode.ForceText; #endif }}
Exercise
The sample contains a Play Mode test for verifying the content of a scene. It is essentially the Play Mode version of the test from the previous exercise.
12_BuildSetupCleanupThe test fails because the scene can't be found. It could be solved by adding the scene to the build settings, but it's not good practise to add a test-related scene to the build settings, as it could get included when building for non-testing purposes.
Therefore the task is to create a that adds the scene to and a that removes it again.
PrebuildSetupEditorBuildSettingsPostBuildCleanupTest the solution by running the test both in the Editor and in a standalone player. You will need to use to make the code compile for the player.
#if UNITY_EDITORHints
- The interface requires a
IPrebuildSetupmethod, so be careful that there are noSetupmethods already called that.[SetUp]
Solution
A full solution is available in the sample .
12_BuildSetupCleanup_SolutionThe full test solution can be done like this:
using System.Collections;using System.Linq;using NUnit.Framework;#if UNITY_EDITORusing UnityEditor;#endifusing UnityEngine;using UnityEngine.SceneManagement;using UnityEngine.TestTools;namespace Tests{ public class SceneTests : IPrebuildSetup, IPostBuildCleanup { private string originalScene; private const string k_SceneName = "Assets/MyGameScene.unity"; public void Setup() {#if UNITY_EDITOR if (EditorBuildSettings.scenes.Any(scene => scene.path == k_SceneName)) { return; } var includedScenes = EditorBuildSettings.scenes.ToList(); includedScenes.Add(new EditorBuildSettingsScene(k_SceneName, true)); EditorBuildSettings.scenes = includedScenes.ToArray();#endif } [UnitySetUp] public IEnumerator SetupBeforeTest() { originalScene = SceneManager.GetActiveScene().path; SceneManager.LoadScene(k_SceneName); yield return null; // Skip a frame } [Test] public void VerifyScene() { var gameObject = GameObject.Find("GameObjectToTestFor"); Assert.That(gameObject, Is.Not.Null, $"GameObjectToTestFor not found in {SceneManager.GetActiveScene().path}."); } [TearDown] public void TeardownAfterTest() { SceneManager.LoadScene(originalScene); } public void Cleanup() {#if UNITY_EDITOR EditorBuildSettings.scenes = EditorBuildSettings.scenes.Where(scene => scene.path != k_SceneName).ToArray();#endif } }}
Note that is also used among the using statements, to allow for a using reference to .
#if UNITY_EDITORUnityEditor