using System; using System.Collections; using UnityEditor; namespace UnityEngine.TestTools { /// /// `RecompileScripts` is an that you can yield in Edit Mode tests. It lets you trigger a recompilation of scripts in the Unity Editor. /// public class RecompileScripts : IEditModeTestYieldInstruction { /// /// Creates a new instance of the `RecompileScripts` yield instruction. /// /// /// [UnitySetUp] /// public IEnumerator SetUp() /// { /// using (var file = File.CreateText("Assets/temp/myScript.cs")) /// { /// file.Write("public class ATempClass { }"); /// } /// AssetDatabase.Refresh(); /// yield return new RecompileScripts(); /// } /// /// /// public RecompileScripts() : this(true) { } /// /// Creates a new instance of the `RecompileScripts` yield instruction. /// /// This parameter indicates if you expect a script compilation to start (defaults to true). If a script compilation does not start and `expectScriptCompilation` is true, then it throws an exception. public RecompileScripts(bool expectScriptCompilation) : this(expectScriptCompilation, true) { } /// /// Creates a new instance of the `RecompileScripts` yield instruction. /// /// This parameter indicates if you expect a script compilation to start (defaults to true). If a script compilation does not start and `expectScriptCompilation` is `true`, then it throws an exception. /// This parameter indicates if you expect a script compilation to succeed. If not succeeded then an exception will be thrown. public RecompileScripts(bool expectScriptCompilation, bool expectScriptCompilationSuccess) { ExpectScriptCompilation = expectScriptCompilation; ExpectScriptCompilationSuccess = expectScriptCompilationSuccess; ExpectDomainReload = true; } /// /// Returns true if the instruction expects a domain reload to occur. /// public bool ExpectDomainReload { get; private set; } /// /// Returns true if the instruction expects the Unity Editor to be in **Play Mode**. /// public bool ExpectedPlaymodeState { get; } /// /// Indicates whether a script compilation is expected. /// public bool ExpectScriptCompilation { get; private set; } /// /// Indicates whether the expected script compilation is expected to succeed. /// public bool ExpectScriptCompilationSuccess { get; private set; } /// /// The current active instance of the RecompileScripts yield instruction. /// public static RecompileScripts Current { get; private set; } /// /// Perform the multi step instruction of triggering a recompilation of scripts and waiting for its completion. /// /// An IEnumerator with the async steps. /// Throws an exception if the editor does not need to recompile scripts or if the script compilation failed when expected to succeed. public IEnumerator Perform() { Current = this; // We need to yield, to give the test runner a chance to prepare for the domain reload // If the script compilation happens very fast, then EditModeRunner.MoveNextAndUpdateYieldObject will not have a chance to set m_CurrentYieldObject // This really should be fixed in EditModeRunner.MoveNextAndUpdateYieldObject yield return null; AssetDatabase.Refresh(); if (ExpectScriptCompilation && !EditorApplication.isCompiling) { Current = null; throw new Exception("Editor does not need to recompile scripts"); } EditorApplication.UnlockReloadAssemblies(); while (EditorApplication.isCompiling) { yield return null; } Current = null; if (ExpectScriptCompilationSuccess && EditorUtility.scriptCompilationFailed) { EditorApplication.LockReloadAssemblies(); throw new Exception("Script compilation failed"); } } } }