using System; using System.IO; using System.Linq; using UnityEditor.SceneManagement; using UnityEditor.TestTools.TestRunner.Api; using UnityEngine; using UnityEngine.TestTools; namespace UnityEditor.TestTools.TestRunner.GUI { [Serializable] internal class PlayModeTestListGUI : TestListGUI { private struct PlayerMenuItem { public GUIContent name; public bool filterSelectedTestsOnly; public bool buildOnly; } [SerializeField] private int m_SelectedOption; public override TestMode TestMode { get { return TestMode.PlayMode; } } private string GetBuildText() { switch (EditorUserBuildSettings.activeBuildTarget) { case BuildTarget.Android: if (EditorUserBuildSettings.exportAsGoogleAndroidProject) return "Export"; break; case BuildTarget.iOS: return "Export"; } return "Build"; } private string PickBuildLocation() { var target = EditorUserBuildSettings.activeBuildTarget; var targetGroup = BuildPipeline.GetBuildTargetGroup(target); var lastLocation = EditorUserBuildSettings.GetBuildLocation(target); var extension = PostprocessBuildPlayer.GetExtensionForBuildTarget(targetGroup, target, BuildOptions.None); var defaultName = FileUtil.GetLastPathNameComponent(lastLocation); lastLocation = string.IsNullOrEmpty(lastLocation) ? string.Empty : Path.GetDirectoryName(lastLocation); bool updateExistingBuild; var location = EditorUtility.SaveBuildPanel(target, $"{GetBuildText()} {target}", lastLocation, defaultName, extension, out updateExistingBuild); if (!string.IsNullOrEmpty(location)) EditorUserBuildSettings.SetBuildLocation(target, location); return location; } private void ExecuteAction(PlayerMenuItem item) { var runSettings = new PlayerLauncherTestRunSettings(); runSettings.buildOnly = item.buildOnly; if (runSettings.buildOnly) { runSettings.buildOnlyLocationPath = PickBuildLocation(); if (string.IsNullOrEmpty(runSettings.buildOnlyLocationPath)) { Debug.LogWarning("Aborting, build selection was canceled."); return; } } if (item.filterSelectedTestsOnly) RunTestsInPlayer(runSettings, SelectedTestsFilter); else { var filter = new UITestRunnerFilter { categoryNames = m_TestRunnerUIFilter.CategoryFilter }; RunTestsInPlayer(runSettings, filter); } } public override void PrintHeadPanel() { EditorGUILayout.BeginHorizontal(GUILayout.ExpandHeight(false)); base.PrintHeadPanel(); PlayerMenuItem[] menuItems; if (EditorUserBuildSettings.installInBuildFolder) { menuItems = new [] { // Note: We select here buildOnly = false, so build location dialog won't show up // The player won't actually be ran when using together with EditorUserBuildSettings.installInBuildFolder new PlayerMenuItem() { name = new GUIContent("Install All Tests In Build Folder"), buildOnly = false, filterSelectedTestsOnly = false }, new PlayerMenuItem() { name = new GUIContent("Install Selected Tests In Build Folder"), buildOnly = false, filterSelectedTestsOnly = true } }; } else { menuItems = new [] { new PlayerMenuItem() { name = new GUIContent("Run All Tests"), buildOnly = false, filterSelectedTestsOnly = false }, new PlayerMenuItem() { name = new GUIContent("Run Selected Tests"), buildOnly = false, filterSelectedTestsOnly = true }, new PlayerMenuItem() { name = new GUIContent($"{GetBuildText()} All Tests"), buildOnly = true, filterSelectedTestsOnly = false }, new PlayerMenuItem() { name = new GUIContent($"{GetBuildText()} Selected Tests"), buildOnly = true, filterSelectedTestsOnly = true }, }; } m_SelectedOption = Math.Min(m_SelectedOption, menuItems.Length - 1); var selectedMenuItem = menuItems[m_SelectedOption]; if (GUILayout.Button( new GUIContent($"{selectedMenuItem.name.text} ({EditorUserBuildSettings.activeBuildTarget})"), EditorStyles.toolbarButton)) { ExecuteAction(selectedMenuItem); } if (GUILayout.Button(GUIContent.none, EditorStyles.toolbarDropDown)) { Vector2 mousePos = Event.current.mousePosition; EditorUtility.DisplayCustomMenu(new Rect(mousePos.x, mousePos.y, 0, 0), menuItems.Select(m => m.name).ToArray(), -1, (object userData, string[] options, int selected) => m_SelectedOption = selected, menuItems); } EditorGUILayout.EndHorizontal(); DrawFilters(); EditorGUILayout.BeginHorizontal(GUILayout.ExpandHeight(false)); EditorGUILayout.EndHorizontal(); } public override void RenderNoTestsInfo() { if (!TestListGUIHelper.SelectedFolderContainsTestAssembly()) { var noTestText = "No tests to show"; if (!PlayerSettings.playModeTestRunnerEnabled) { const string testsArePulledFromCustomAssemblues = "Test Assemblies are defined by Assembly Definitions that references the \"nunit.framework.dll\" Assembly Reference or the Assembly Definition Reference \"UnityEngine.TestRunner\"."; const string infoTextAboutTestsInAllAssemblies = "To have tests in all assemblies enable it in the Test Runner window context menu"; noTestText += Environment.NewLine + testsArePulledFromCustomAssemblues + Environment.NewLine + infoTextAboutTestsInAllAssemblies; } EditorGUILayout.HelpBox(noTestText, MessageType.Info); if (GUILayout.Button("Create PlayMode Test Assembly Folder")) { TestListGUIHelper.AddFolderAndAsmDefForTesting(); } } if (!TestListGUIHelper.CanAddPlayModeTestScriptAndItWillCompile()) { UnityEngine.GUI.enabled = false; EditorGUILayout.HelpBox("PlayMode test scripts can only be created in non editor test assemblies.", MessageType.Warning); } if (GUILayout.Button("Create Test Script in current folder")) { TestListGUIHelper.AddTest(); } UnityEngine.GUI.enabled = true; } protected override void RunTests(UITestRunnerFilter[] filters) { foreach (var filter in filters) { filter.ClearResults(newResultList.OfType().ToList()); } RerunCallbackData.instance.runFilters = filters; RerunCallbackData.instance.testMode = TestMode.PlayMode; var testRunnerApi = ScriptableObject.CreateInstance(); testRunnerApi.Execute(new ExecutionSettings() { filters = filters.Select(filter => new Filter() { assemblyNames = filter.assemblyNames, categoryNames = filter.categoryNames, groupNames = filter.groupNames, testMode = TestMode, testNames = filter.testNames }).ToArray() }); } protected void RunTestsInPlayer(PlayerLauncherTestRunSettings runSettings, params UITestRunnerFilter[] filters) { foreach (var filter in filters) { filter.ClearResults(newResultList.OfType().ToList()); } var testRunnerApi = ScriptableObject.CreateInstance(); testRunnerApi.Execute(new ExecutionSettings() { overloadTestRunSettings = runSettings, filters = filters.Select(filter => new Filter() { assemblyNames = filter.assemblyNames, categoryNames = filter.categoryNames, groupNames = filter.groupNames, testMode = TestMode, testNames = filter.testNames }).ToArray(), targetPlatform = EditorUserBuildSettings.activeBuildTarget }); } public override TestPlatform TestPlatform { get { return TestPlatform.PlayMode; } } protected override bool IsBusy() { return TestRunnerApi.IsRunActive() || PlaymodeLauncher.IsRunning || EditorApplication.isCompiling || EditorApplication.isPlaying; } } }