using System; using System.Linq; using UnityEditor.Callbacks; using UnityEditor.Scripting.ScriptCompilation; using UnityEditor.TestTools.TestRunner.Api; using UnityEditor.TestTools.TestRunner.GUI; using UnityEngine; namespace UnityEditor.TestTools.TestRunner { /// /// The TestRunnerWindow class is repsonsible for drawing the Test Runner window. /// [Serializable] public class TestRunnerWindow : EditorWindow, IHasCustomMenu { private const string WindowTitle = "Test Runner"; internal static class Styles { public static GUIStyle info; public static GUIStyle testList; static Styles() { info = new GUIStyle("CN Message"); info.wordWrap = true; info.stretchHeight = true; info.margin.right = 15; testList = new GUIStyle("CN Box"); testList.margin.top = 0; testList.padding.left = 3; } } private readonly GUIContent m_GUIHorizontalSplit = EditorGUIUtility.TrTextContent("Horizontal layout"); private readonly GUIContent m_GUIVerticalSplit = EditorGUIUtility.TrTextContent("Vertical layout"); private readonly GUIContent m_GUIDisablePlaymodeTestsRunner = EditorGUIUtility.TrTextContent("Disable playmode tests for all assemblies"); private readonly GUIContent m_GUIRunPlayModeTestAsEditModeTests = EditorGUIUtility.TrTextContent("Run playmode tests as editmode tests"); internal static TestRunnerWindow s_Instance; private bool m_IsBuilding; [NonSerialized] private bool m_Enabled; //internal TestFilterSettings filterSettings; [SerializeField] private SplitterState m_Spl = new SplitterState(new float[] { 75, 25 }, new[] { 32, 32 }, null); private TestRunnerWindowSettings m_Settings; private enum TestRunnerMenuLabels { EditMode = 0, PlayMode, Player } [SerializeField] private TestRunnerMenuLabels m_TestTypeToolbarIndex = TestRunnerMenuLabels.EditMode; internal TestListGUI m_SelectedTestTypes; [SerializeField] private TestListGUI[] m_TestListGUIs; private ITestRunnerApi m_testRunnerApi; private WindowResultUpdater m_WindowResultUpdater; /// /// Launches the Test Runner window. /// [MenuItem("Window/General/Test Runner", false, 201, false)] public static void ShowWindow() { s_Instance = GetWindow(WindowTitle); s_Instance.Show(); } static TestRunnerWindow() { InitBackgroundRunners(); } private static void InitBackgroundRunners() { EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; EditorApplication.playModeStateChanged += OnPlayModeStateChanged; } [DidReloadScripts] private static void CompilationCallback() { UpdateWindow(); } private static void OnPlayModeStateChanged(PlayModeStateChange state) { if (s_Instance && state == PlayModeStateChange.EnteredEditMode) { var testListGUI = s_Instance.m_SelectedTestTypes; if (testListGUI.HasTreeData()) { //repaint message details after exit playmode testListGUI.TestSelectionCallback(testListGUI.m_TestListState.selectedIDs.ToArray()); s_Instance.Repaint(); } } } internal void OnDestroy() { EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; } private void OnEnable() { s_Instance = this; titleContent = new GUIContent(WindowTitle, "Test framework for running Edit mode and Play mode tests in Unity. Part of the com.unity.test-framework package."); SelectTestListGUI(m_TestTypeToolbarIndex); m_testRunnerApi = CreateInstance(); m_WindowResultUpdater = new WindowResultUpdater(); m_testRunnerApi.RegisterCallbacks(m_WindowResultUpdater); } private void Enable() { m_Settings = new TestRunnerWindowSettings("UnityEditor.PlaymodeTestsRunnerWindow"); if (m_SelectedTestTypes == null) { SelectTestListGUI(m_TestTypeToolbarIndex); } StartRetrieveTestList(); m_SelectedTestTypes.Reload(); m_Enabled = true; } private void SelectTestListGUI(TestRunnerMenuLabels testTypeToolbarIndex) { if (m_TestListGUIs == null) { m_TestListGUIs = new TestListGUI[] { new TestListGUI() { m_TestMode = TestMode.EditMode, }, new TestListGUI() { m_TestMode = TestMode.PlayMode, }, new TestListGUI() { m_TestMode = TestMode.PlayMode, m_RunOnPlatform = true } }; } m_TestListGUIs[0].m_TestMode = TestMode.EditMode; m_TestListGUIs[0].m_RunOnPlatform = false; m_TestListGUIs[1].m_TestMode = TestMode.PlayMode; m_TestListGUIs[1].m_RunOnPlatform = false; m_TestListGUIs[2].m_TestMode = TestMode.PlayMode; m_TestListGUIs[2].m_RunOnPlatform = true; m_SelectedTestTypes = m_TestListGUIs[(int)testTypeToolbarIndex]; } private void StartRetrieveTestList() { var listToInit = m_SelectedTestTypes; m_testRunnerApi.RetrieveTestList(listToInit.m_TestMode, rootTest => { listToInit.Init(this, rootTest); listToInit.Reload(); }); } internal void OnGUI() { if (!m_Enabled) { Enable(); } if (BuildPipeline.isBuildingPlayer) { m_IsBuilding = true; } else if (m_IsBuilding) { m_IsBuilding = false; Repaint(); } EditorGUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); var selectedIndex = m_TestTypeToolbarIndex; m_TestTypeToolbarIndex = (TestRunnerMenuLabels)GUILayout.Toolbar((int)m_TestTypeToolbarIndex, Enum.GetNames(typeof(TestRunnerMenuLabels)), "LargeButton", UnityEngine.GUI.ToolbarButtonSize.FitToContents); GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); if (selectedIndex != m_TestTypeToolbarIndex) { SelectTestListGUI(m_TestTypeToolbarIndex); StartRetrieveTestList(); } EditorGUILayout.BeginVertical(); using (new EditorGUI.DisabledScope(EditorApplication.isPlayingOrWillChangePlaymode)) { m_SelectedTestTypes.PrintHeadPanel(); } EditorGUILayout.EndVertical(); if (m_Settings.verticalSplit) SplitterGUILayout.BeginVerticalSplit(m_Spl); else SplitterGUILayout.BeginHorizontalSplit(m_Spl); EditorGUILayout.BeginVertical(); EditorGUILayout.BeginVertical(Styles.testList); m_SelectedTestTypes.RenderTestList(); EditorGUILayout.EndVertical(); EditorGUILayout.EndVertical(); m_SelectedTestTypes.RenderDetails(position.width); if (m_Settings.verticalSplit) SplitterGUILayout.EndVerticalSplit(); else SplitterGUILayout.EndHorizontalSplit(); m_SelectedTestTypes.PrintProgressBar(position); EditorGUILayout.BeginVertical(); using (new EditorGUI.DisabledScope(EditorApplication.isPlayingOrWillChangePlaymode)) { m_SelectedTestTypes.PrintBottomPanel(); } EditorGUILayout.EndVertical(); } /// /// Adds additional menu items to the Test Runner window. /// /// The public void AddItemsToMenu(GenericMenu menu) { menu.AddItem(m_GUIVerticalSplit, m_Settings.verticalSplit, m_Settings.ToggleVerticalSplit); menu.AddItem(m_GUIHorizontalSplit, !m_Settings.verticalSplit, m_Settings.ToggleVerticalSplit); menu.AddSeparator(null); if (EditorPrefs.GetBool("InternalMode", false)) { menu.AddItem(m_GUIRunPlayModeTestAsEditModeTests, PlayerSettings.runPlayModeTestAsEditModeTest, () => { PlayerSettings.runPlayModeTestAsEditModeTest = !PlayerSettings.runPlayModeTestAsEditModeTest; }); } if (PlayerSettings.playModeTestRunnerEnabled) { PlayerSettings.playModeTestRunnerEnabled = false; EditorUtility.DisplayDialog(m_GUIDisablePlaymodeTestsRunner.text, "You need to restart the editor now", "Ok"); } } internal void RebuildUIFilter() { if (m_SelectedTestTypes != null && m_SelectedTestTypes.HasTreeData()) { m_SelectedTestTypes.RebuildUIFilter(); } } internal static void UpdateWindow() { if (s_Instance != null && s_Instance.m_SelectedTestTypes != null) { s_Instance.m_SelectedTestTypes.Repaint(); s_Instance.Repaint(); } } } }