暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

TestRunnerWindow.cs 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. using System;
  2. using System.Linq;
  3. using UnityEditor.Callbacks;
  4. using UnityEditor.Scripting.ScriptCompilation;
  5. using UnityEditor.TestTools.TestRunner.Api;
  6. using UnityEditor.TestTools.TestRunner.GUI;
  7. using UnityEngine;
  8. namespace UnityEditor.TestTools.TestRunner
  9. {
  10. /// <summary>
  11. /// The TestRunnerWindow class is repsonsible for drawing the Test Runner window.
  12. /// </summary>
  13. [Serializable]
  14. public class TestRunnerWindow : EditorWindow, IHasCustomMenu
  15. {
  16. private const string WindowTitle = "Test Runner";
  17. internal static class Styles
  18. {
  19. public static GUIStyle info;
  20. public static GUIStyle testList;
  21. static Styles()
  22. {
  23. info = new GUIStyle("CN Message");
  24. info.wordWrap = true;
  25. info.stretchHeight = true;
  26. info.margin.right = 15;
  27. testList = new GUIStyle("CN Box");
  28. testList.margin.top = 0;
  29. testList.padding.left = 3;
  30. }
  31. }
  32. private readonly GUIContent m_GUIHorizontalSplit = EditorGUIUtility.TrTextContent("Horizontal layout");
  33. private readonly GUIContent m_GUIVerticalSplit = EditorGUIUtility.TrTextContent("Vertical layout");
  34. private readonly GUIContent m_GUIDisablePlaymodeTestsRunner = EditorGUIUtility.TrTextContent("Disable playmode tests for all assemblies");
  35. private readonly GUIContent m_GUIRunPlayModeTestAsEditModeTests = EditorGUIUtility.TrTextContent("Run playmode tests as editmode tests");
  36. internal static TestRunnerWindow s_Instance;
  37. private bool m_IsBuilding;
  38. [NonSerialized]
  39. private bool m_Enabled;
  40. //internal TestFilterSettings filterSettings;
  41. [SerializeField]
  42. private SplitterState m_Spl = new SplitterState(new float[] { 75, 25 }, new[] { 32, 32 }, null);
  43. private TestRunnerWindowSettings m_Settings;
  44. private enum TestRunnerMenuLabels
  45. {
  46. EditMode = 0,
  47. PlayMode,
  48. Player
  49. }
  50. [SerializeField]
  51. private TestRunnerMenuLabels m_TestTypeToolbarIndex = TestRunnerMenuLabels.EditMode;
  52. internal TestListGUI m_SelectedTestTypes;
  53. [SerializeField]
  54. private TestListGUI[] m_TestListGUIs;
  55. private ITestRunnerApi m_testRunnerApi;
  56. private WindowResultUpdater m_WindowResultUpdater;
  57. /// <summary>
  58. /// Launches the Test Runner window.
  59. /// </summary>
  60. [MenuItem("Window/General/Test Runner", false, 201, false)]
  61. public static void ShowWindow()
  62. {
  63. s_Instance = GetWindow<TestRunnerWindow>(WindowTitle);
  64. s_Instance.Show();
  65. }
  66. static TestRunnerWindow()
  67. {
  68. InitBackgroundRunners();
  69. TestRunnerApi.runProgressChanged.AddListener(UpdateProgressStatus);
  70. var isRunFromCommandLine = Environment.GetCommandLineArgs().Any(arg => arg == "-runTests");
  71. if (!isRunFromCommandLine)
  72. {
  73. EditorApplication.update += UpdateProgressBar;
  74. }
  75. }
  76. private static void InitBackgroundRunners()
  77. {
  78. EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
  79. EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
  80. }
  81. [DidReloadScripts]
  82. private static void CompilationCallback()
  83. {
  84. UpdateWindow();
  85. }
  86. private static void OnPlayModeStateChanged(PlayModeStateChange state)
  87. {
  88. if (s_Instance && state == PlayModeStateChange.EnteredEditMode)
  89. {
  90. var testListGUI = s_Instance.m_SelectedTestTypes;
  91. if (testListGUI.HasTreeData())
  92. {
  93. //repaint message details after exit playmode
  94. testListGUI.TestSelectionCallback(testListGUI.m_TestListState.selectedIDs.ToArray());
  95. s_Instance.Repaint();
  96. }
  97. }
  98. }
  99. internal void OnDestroy()
  100. {
  101. EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
  102. }
  103. private void OnEnable()
  104. {
  105. s_Instance = this;
  106. titleContent = new GUIContent(WindowTitle, "Test framework for running Edit mode and Play mode tests in Unity. Part of the com.unity.test-framework package.");
  107. SelectTestListGUI(m_TestTypeToolbarIndex);
  108. m_testRunnerApi = CreateInstance<TestRunnerApi>();
  109. m_WindowResultUpdater = new WindowResultUpdater();
  110. m_testRunnerApi.RegisterCallbacks(m_WindowResultUpdater);
  111. }
  112. private void Enable()
  113. {
  114. m_Settings = new TestRunnerWindowSettings("UnityEditor.PlaymodeTestsRunnerWindow");
  115. if (m_SelectedTestTypes == null)
  116. {
  117. SelectTestListGUI(m_TestTypeToolbarIndex);
  118. }
  119. StartRetrieveTestList();
  120. m_SelectedTestTypes.Reload();
  121. m_Enabled = true;
  122. }
  123. private void SelectTestListGUI(TestRunnerMenuLabels testTypeToolbarIndex)
  124. {
  125. if (m_TestListGUIs == null)
  126. {
  127. m_TestListGUIs = new TestListGUI[]
  128. {
  129. new TestListGUI()
  130. {
  131. m_TestMode = TestMode.EditMode,
  132. },
  133. new TestListGUI()
  134. {
  135. m_TestMode = TestMode.PlayMode,
  136. },
  137. new TestListGUI()
  138. {
  139. m_TestMode = TestMode.PlayMode,
  140. m_RunOnPlatform = true
  141. }
  142. };
  143. }
  144. m_TestListGUIs[0].m_TestMode = TestMode.EditMode;
  145. m_TestListGUIs[0].m_RunOnPlatform = false;
  146. m_TestListGUIs[1].m_TestMode = TestMode.PlayMode;
  147. m_TestListGUIs[1].m_RunOnPlatform = false;
  148. m_TestListGUIs[2].m_TestMode = TestMode.PlayMode;
  149. m_TestListGUIs[2].m_RunOnPlatform = true;
  150. m_SelectedTestTypes = m_TestListGUIs[(int)testTypeToolbarIndex];
  151. }
  152. private void StartRetrieveTestList()
  153. {
  154. var listToInit = m_SelectedTestTypes;
  155. m_testRunnerApi.RetrieveTestList(listToInit.m_TestMode, rootTest =>
  156. {
  157. listToInit.Init(this, rootTest);
  158. listToInit.Reload();
  159. });
  160. }
  161. internal void OnGUI()
  162. {
  163. if (!m_Enabled)
  164. {
  165. Enable();
  166. }
  167. if (BuildPipeline.isBuildingPlayer)
  168. {
  169. m_IsBuilding = true;
  170. }
  171. else if (m_IsBuilding)
  172. {
  173. m_IsBuilding = false;
  174. Repaint();
  175. }
  176. EditorGUILayout.BeginHorizontal();
  177. GUILayout.FlexibleSpace();
  178. var selectedIndex = m_TestTypeToolbarIndex;
  179. m_TestTypeToolbarIndex = (TestRunnerMenuLabels)GUILayout.Toolbar((int)m_TestTypeToolbarIndex, Enum.GetNames(typeof(TestRunnerMenuLabels)), "LargeButton", UnityEngine.GUI.ToolbarButtonSize.FitToContents);
  180. GUILayout.FlexibleSpace();
  181. EditorGUILayout.EndHorizontal();
  182. if (selectedIndex != m_TestTypeToolbarIndex)
  183. {
  184. SelectTestListGUI(m_TestTypeToolbarIndex);
  185. StartRetrieveTestList();
  186. }
  187. EditorGUILayout.BeginVertical();
  188. using (new EditorGUI.DisabledScope(EditorApplication.isPlayingOrWillChangePlaymode))
  189. {
  190. m_SelectedTestTypes.PrintHeadPanel();
  191. }
  192. EditorGUILayout.EndVertical();
  193. if (m_Settings.verticalSplit)
  194. SplitterGUILayout.BeginVerticalSplit(m_Spl);
  195. else
  196. SplitterGUILayout.BeginHorizontalSplit(m_Spl);
  197. EditorGUILayout.BeginVertical();
  198. EditorGUILayout.BeginVertical(Styles.testList);
  199. m_SelectedTestTypes.RenderTestList();
  200. EditorGUILayout.EndVertical();
  201. EditorGUILayout.EndVertical();
  202. m_SelectedTestTypes.RenderDetails(position.width);
  203. if (m_Settings.verticalSplit)
  204. SplitterGUILayout.EndVerticalSplit();
  205. else
  206. SplitterGUILayout.EndHorizontalSplit();
  207. EditorGUILayout.BeginVertical();
  208. using (new EditorGUI.DisabledScope(EditorApplication.isPlayingOrWillChangePlaymode))
  209. {
  210. m_SelectedTestTypes.PrintBottomPanel();
  211. }
  212. EditorGUILayout.EndVertical();
  213. }
  214. /// <summary>
  215. /// Adds additional menu items to the Test Runner window.
  216. /// </summary>
  217. /// <param name="menu">The <see cref="GenericMenu"/></param>
  218. public void AddItemsToMenu(GenericMenu menu)
  219. {
  220. menu.AddItem(m_GUIVerticalSplit, m_Settings.verticalSplit, m_Settings.ToggleVerticalSplit);
  221. menu.AddItem(m_GUIHorizontalSplit, !m_Settings.verticalSplit, m_Settings.ToggleVerticalSplit);
  222. menu.AddSeparator(null);
  223. if (EditorPrefs.GetBool("InternalMode", false))
  224. {
  225. menu.AddItem(m_GUIRunPlayModeTestAsEditModeTests, PlayerSettings.runPlayModeTestAsEditModeTest, () =>
  226. {
  227. PlayerSettings.runPlayModeTestAsEditModeTest = !PlayerSettings.runPlayModeTestAsEditModeTest;
  228. });
  229. }
  230. if (PlayerSettings.playModeTestRunnerEnabled)
  231. {
  232. PlayerSettings.playModeTestRunnerEnabled = false;
  233. EditorUtility.DisplayDialog(m_GUIDisablePlaymodeTestsRunner.text, "You need to restart the editor now", "Ok");
  234. }
  235. }
  236. private static TestRunProgress runProgress;
  237. private static void UpdateProgressStatus(TestRunProgress progress)
  238. {
  239. runProgress = progress;
  240. }
  241. private static void UpdateProgressBar()
  242. {
  243. if (runProgress == null)
  244. {
  245. return;
  246. }
  247. if (runProgress.HasFinished)
  248. {
  249. runProgress = null;
  250. EditorUtility.ClearProgressBar();
  251. return;
  252. }
  253. var cancel = EditorUtility.DisplayCancelableProgressBar($"Test Runner - {runProgress.CurrentStageName}", runProgress.CurrentStepName, runProgress.Progress);
  254. if (cancel)
  255. {
  256. TestRunnerApi.CancelTestRun(runProgress.RunGuid);
  257. }
  258. }
  259. internal void RebuildUIFilter()
  260. {
  261. if (m_SelectedTestTypes != null && m_SelectedTestTypes.HasTreeData())
  262. {
  263. m_SelectedTestTypes.RebuildUIFilter();
  264. }
  265. }
  266. internal static void UpdateWindow()
  267. {
  268. if (s_Instance != null && s_Instance.m_SelectedTestTypes != null)
  269. {
  270. s_Instance.m_SelectedTestTypes.Repaint();
  271. s_Instance.Repaint();
  272. }
  273. }
  274. }
  275. }