|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Text;
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
using UnityEditor;
|
|
|
|
using UnityEngine;
|
|
|
|
using UnityTest.IntegrationTestRunner;
|
|
|
|
|
|
|
|
namespace UnityTest
|
|
|
|
{
|
|
|
|
[Serializable]
|
|
|
|
public class IntegrationTestsRunnerWindow : EditorWindow, IHasCustomMenu
|
|
|
|
{
|
|
|
|
#region GUI Contents
|
|
|
|
private readonly GUIContent m_GUICreateNewTest = new GUIContent("Create", "Create new test");
|
|
|
|
private readonly GUIContent m_GUIRunSelectedTests = new GUIContent("Run Selected", "Run selected test(s)");
|
|
|
|
private readonly GUIContent m_GUIRunAllTests = new GUIContent("Run All", "Run all tests");
|
|
|
|
private readonly GUIContent m_GUIBlockUI = new GUIContent("Block UI when running", "Block UI when running tests");
|
|
|
|
private readonly GUIContent m_GUIPauseOnFailure = new GUIContent("Pause on test failure");
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region runner steerign vars
|
|
|
|
private static IntegrationTestsRunnerWindow s_Instance;
|
|
|
|
[SerializeField] private List<GameObject> m_TestsToRun;
|
|
|
|
[SerializeField] private List<string> m_DynamicTestsToRun;
|
|
|
|
[SerializeField] private bool m_ReadyToRun;
|
|
|
|
private bool m_IsBuilding;
|
|
|
|
public static bool selectedInHierarchy;
|
|
|
|
private float m_HorizontalSplitBarPosition = 200;
|
|
|
|
private Vector2 m_TestInfoScroll, m_TestListScroll;
|
|
|
|
private IntegrationTestRendererBase[] m_TestLines;
|
|
|
|
private string m_CurrectSceneName;
|
|
|
|
private TestFilterSettings m_FilterSettings;
|
|
|
|
|
|
|
|
Vector2 m_resultTextSize;
|
|
|
|
string m_resultText;
|
|
|
|
GameObject m_lastSelectedGO;
|
|
|
|
int m_resultTestMaxLength = 15000;
|
|
|
|
|
|
|
|
[SerializeField] private GameObject m_SelectedLine;
|
|
|
|
[SerializeField] private List<TestResult> m_ResultList = new List<TestResult>();
|
|
|
|
[SerializeField] private List<GameObject> m_FoldMarkers = new List<GameObject>();
|
|
|
|
|
|
|
|
private IntegrationTestsRunnerSettings m_Settings;
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
static IntegrationTestsRunnerWindow()
|
|
|
|
{
|
|
|
|
InitBackgroundRunners();
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void InitBackgroundRunners()
|
|
|
|
{
|
|
|
|
EditorApplication.hierarchyWindowItemOnGUI -= OnHierarchyWindowItemDraw;
|
|
|
|
EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyWindowItemDraw;
|
|
|
|
EditorApplication.hierarchyWindowChanged -= OnHierarchyChangeUpdate;
|
|
|
|
EditorApplication.hierarchyWindowChanged += OnHierarchyChangeUpdate;
|
|
|
|
EditorApplication.update -= BackgroundSceneChangeWatch;
|
|
|
|
EditorApplication.update += BackgroundSceneChangeWatch;
|
|
|
|
EditorApplication.playmodeStateChanged -= OnPlaymodeStateChanged;
|
|
|
|
EditorApplication.playmodeStateChanged += OnPlaymodeStateChanged;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void OnPlaymodeStateChanged()
|
|
|
|
{
|
|
|
|
if (s_Instance && EditorApplication.isPlaying == EditorApplication.isPlayingOrWillChangePlaymode)
|
|
|
|
s_Instance.RebuildTestList();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void OnDestroy()
|
|
|
|
{
|
|
|
|
EditorApplication.hierarchyWindowItemOnGUI -= OnHierarchyWindowItemDraw;
|
|
|
|
EditorApplication.update -= BackgroundSceneChangeWatch;
|
|
|
|
EditorApplication.hierarchyWindowChanged -= OnHierarchyChangeUpdate;
|
|
|
|
EditorApplication.playmodeStateChanged -= OnPlaymodeStateChanged;
|
|
|
|
|
|
|
|
TestComponent.DestroyAllDynamicTests();
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void BackgroundSceneChangeWatch()
|
|
|
|
{
|
|
|
|
if (!s_Instance) return;
|
|
|
|
if (s_Instance.m_CurrectSceneName != null && s_Instance.m_CurrectSceneName == EditorApplication.currentScene) return;
|
|
|
|
if (EditorApplication.isPlayingOrWillChangePlaymode) return;
|
|
|
|
TestComponent.DestroyAllDynamicTests();
|
|
|
|
s_Instance.m_CurrectSceneName = EditorApplication.currentScene;
|
|
|
|
s_Instance.m_ResultList.Clear();
|
|
|
|
s_Instance.RebuildTestList();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void OnEnable()
|
|
|
|
{
|
|
|
|
titleContent = new GUIContent("Integration Tests");
|
|
|
|
s_Instance = this;
|
|
|
|
|
|
|
|
m_Settings = ProjectSettingsBase.Load<IntegrationTestsRunnerSettings>();
|
|
|
|
m_FilterSettings = new TestFilterSettings("UnityTest.IntegrationTestsRunnerWindow");
|
|
|
|
|
|
|
|
InitBackgroundRunners();
|
|
|
|
if (!EditorApplication.isPlayingOrWillChangePlaymode && !m_ReadyToRun) RebuildTestList();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void OnSelectionChange()
|
|
|
|
{
|
|
|
|
if (EditorApplication.isPlayingOrWillChangePlaymode
|
|
|
|
|| Selection.objects == null
|
|
|
|
|| Selection.objects.Length == 0) return;
|
|
|
|
|
|
|
|
if (Selection.gameObjects.Length == 1)
|
|
|
|
{
|
|
|
|
var go = Selection.gameObjects.Single();
|
|
|
|
var temp = go.transform;
|
|
|
|
while (temp != null)
|
|
|
|
{
|
|
|
|
var tc = temp.GetComponent<TestComponent>();
|
|
|
|
if (tc != null) break;
|
|
|
|
temp = temp.parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (temp != null)
|
|
|
|
{
|
|
|
|
SelectInHierarchy(temp.gameObject);
|
|
|
|
Selection.activeGameObject = temp.gameObject;
|
|
|
|
m_SelectedLine = temp.gameObject;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void OnHierarchyChangeUpdate()
|
|
|
|
{
|
|
|
|
if (!s_Instance || s_Instance.m_TestLines == null || EditorApplication.isPlayingOrWillChangePlaymode) return;
|
|
|
|
|
|
|
|
// create a test runner if it doesn't exist
|
|
|
|
TestRunner.GetTestRunner();
|
|
|
|
|
|
|
|
// make tests are not places under a go that is not a test itself
|
|
|
|
foreach (var test in TestComponent.FindAllTestsOnScene())
|
|
|
|
{
|
|
|
|
if (test.gameObject.transform.parent != null && test.gameObject.transform.parent.gameObject.GetComponent<TestComponent>() == null)
|
|
|
|
{
|
|
|
|
test.gameObject.transform.parent = null;
|
|
|
|
Debug.LogWarning("Tests need to be on top of the hierarchy or directly under another test.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (selectedInHierarchy) selectedInHierarchy = false;
|
|
|
|
else s_Instance.RebuildTestList();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static TestResult GetResultForTest(TestComponent tc)
|
|
|
|
{
|
|
|
|
if(!s_Instance) return new TestResult(tc);
|
|
|
|
return s_Instance.m_ResultList.FirstOrDefault(r => r.GameObject == tc.gameObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void OnHierarchyWindowItemDraw(int id, Rect rect)
|
|
|
|
{
|
|
|
|
var o = EditorUtility.InstanceIDToObject(id);
|
|
|
|
if (o is GameObject)
|
|
|
|
{
|
|
|
|
var go = o as GameObject;
|
|
|
|
|
|
|
|
if (Event.current.type == EventType.MouseDown
|
|
|
|
&& Event.current.button == 0
|
|
|
|
&& rect.Contains(Event.current.mousePosition))
|
|
|
|
{
|
|
|
|
var temp = go.transform;
|
|
|
|
while (temp != null)
|
|
|
|
{
|
|
|
|
var c = temp.GetComponent<TestComponent>();
|
|
|
|
if (c != null) break;
|
|
|
|
temp = temp.parent;
|
|
|
|
}
|
|
|
|
if (temp != null) SelectInHierarchy(temp.gameObject);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void SelectInHierarchy(GameObject gameObject)
|
|
|
|
{
|
|
|
|
if (!s_Instance) return;
|
|
|
|
if (gameObject == s_Instance.m_SelectedLine && gameObject.activeInHierarchy) return;
|
|
|
|
if (EditorApplication.isPlayingOrWillChangePlaymode) return;
|
|
|
|
if (!gameObject.activeSelf)
|
|
|
|
{
|
|
|
|
selectedInHierarchy = true;
|
|
|
|
gameObject.SetActive(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
var tests = TestComponent.FindAllTestsOnScene();
|
|
|
|
var skipList = gameObject.GetComponentsInChildren(typeof(TestComponent), true).ToList();
|
|
|
|
tests.RemoveAll(skipList.Contains);
|
|
|
|
foreach (var test in tests)
|
|
|
|
{
|
|
|
|
var enable = test.GetComponentsInChildren(typeof(TestComponent), true).Any(c => c.gameObject == gameObject);
|
|
|
|
if (test.gameObject.activeSelf != enable) test.gameObject.SetActive(enable);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void RunTests(IList<ITestComponent> tests)
|
|
|
|
{
|
|
|
|
if (!tests.Any() || EditorApplication.isCompiling || EditorApplication.isPlayingOrWillChangePlaymode)
|
|
|
|
return;
|
|
|
|
FocusWindowIfItsOpen(GetType());
|
|
|
|
|
|
|
|
var testComponents = tests.Where(t => t is TestComponent).Cast<TestComponent>().ToList();
|
|
|
|
var dynaminTests = testComponents.Where(t => t.dynamic).ToList();
|
|
|
|
m_DynamicTestsToRun = dynaminTests.Select(c => c.dynamicTypeName).ToList();
|
|
|
|
testComponents.RemoveAll(dynaminTests.Contains);
|
|
|
|
|
|
|
|
m_TestsToRun = testComponents.Select( tc => tc.gameObject ).ToList();
|
|
|
|
|
|
|
|
m_ReadyToRun = true;
|
|
|
|
TestComponent.DisableAllTests();
|
|
|
|
|
|
|
|
EditorApplication.isPlaying = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Update()
|
|
|
|
{
|
|
|
|
if (m_ReadyToRun && EditorApplication.isPlaying)
|
|
|
|
{
|
|
|
|
m_ReadyToRun = false;
|
|
|
|
var testRunner = TestRunner.GetTestRunner();
|
|
|
|
testRunner.TestRunnerCallback.Add(new RunnerCallback(this));
|
|
|
|
var testComponents = m_TestsToRun.Select(go => go.GetComponent<TestComponent>()).ToList();
|
|
|
|
testRunner.InitRunner(testComponents, m_DynamicTestsToRun);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void RebuildTestList()
|
|
|
|
{
|
|
|
|
m_TestLines = null;
|
|
|
|
if (!TestComponent.AnyTestsOnScene()
|
|
|
|
&& !TestComponent.AnyDynamicTestForCurrentScene()) return;
|
|
|
|
|
|
|
|
if (!EditorApplication.isPlayingOrWillChangePlaymode)
|
|
|
|
{
|
|
|
|
var dynamicTestsOnScene = TestComponent.FindAllDynamicTestsOnScene();
|
|
|
|
var dynamicTestTypes = TestComponent.GetTypesWithHelpAttribute(EditorApplication.currentScene);
|
|
|
|
|
|
|
|
foreach (var dynamicTestType in dynamicTestTypes)
|
|
|
|
{
|
|
|
|
var existingTests = dynamicTestsOnScene.Where(component => component.dynamicTypeName == dynamicTestType.AssemblyQualifiedName);
|
|
|
|
if (existingTests.Any())
|
|
|
|
{
|
|
|
|
var testComponent = existingTests.Single();
|
|
|
|
foreach (var c in testComponent.gameObject.GetComponents<Component>())
|
|
|
|
{
|
|
|
|
var type = Type.GetType(testComponent.dynamicTypeName);
|
|
|
|
if (c is TestComponent || c is Transform || type.IsInstanceOfType(c)) continue;
|
|
|
|
DestroyImmediate(c);
|
|
|
|
}
|
|
|
|
dynamicTestsOnScene.Remove(existingTests.Single());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
TestComponent.CreateDynamicTest(dynamicTestType);
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach (var testComponent in dynamicTestsOnScene)
|
|
|
|
DestroyImmediate(testComponent.gameObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
var topTestList = TestComponent.FindAllTopTestsOnScene();
|
|
|
|
|
|
|
|
var newResultList = new List<TestResult>();
|
|
|
|
m_TestLines = ParseTestList(topTestList, newResultList);
|
|
|
|
|
|
|
|
var oldDynamicResults = m_ResultList.Where(result => result.dynamicTest);
|
|
|
|
foreach (var oldResult in m_ResultList)
|
|
|
|
{
|
|
|
|
var result = newResultList.Find(r => r.Id == oldResult.Id);
|
|
|
|
if (result == null) continue;
|
|
|
|
result.Update(oldResult);
|
|
|
|
}
|
|
|
|
newResultList.AddRange(oldDynamicResults.Where(r => !newResultList.Contains(r)));
|
|
|
|
m_ResultList = newResultList;
|
|
|
|
|
|
|
|
IntegrationTestRendererBase.RunTest = RunTests;
|
|
|
|
IntegrationTestGroupLine.FoldMarkers = m_FoldMarkers;
|
|
|
|
IntegrationTestLine.Results = m_ResultList;
|
|
|
|
|
|
|
|
m_FilterSettings.UpdateCounters(m_ResultList.Cast<ITestResult>());
|
|
|
|
|
|
|
|
m_FoldMarkers.RemoveAll(o => o == null);
|
|
|
|
|
|
|
|
selectedInHierarchy = true;
|
|
|
|
Repaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private IntegrationTestRendererBase[] ParseTestList(List<TestComponent> testList, List<TestResult> results)
|
|
|
|
{
|
|
|
|
var tempList = new List<IntegrationTestRendererBase>();
|
|
|
|
foreach (var testObject in testList)
|
|
|
|
{
|
|
|
|
if (!testObject.IsTestGroup())
|
|
|
|
{
|
|
|
|
var result = new TestResult(testObject);
|
|
|
|
if (results != null)
|
|
|
|
results.Add(result);
|
|
|
|
tempList.Add(new IntegrationTestLine(testObject.gameObject, result));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
var group = new IntegrationTestGroupLine(testObject.gameObject);
|
|
|
|
var children = testObject.gameObject.GetComponentsInChildren(typeof(TestComponent), true).Cast<TestComponent>().ToList();
|
|
|
|
children = children.Where(c => c.gameObject.transform.parent == testObject.gameObject.transform).ToList();
|
|
|
|
group.AddChildren(ParseTestList(children, results));
|
|
|
|
tempList.Add(group);
|
|
|
|
}
|
|
|
|
tempList.Sort();
|
|
|
|
return tempList.ToArray();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void OnGUI()
|
|
|
|
{
|
|
|
|
if (BuildPipeline.isBuildingPlayer)
|
|
|
|
{
|
|
|
|
m_IsBuilding = true;
|
|
|
|
}
|
|
|
|
else if (m_IsBuilding)
|
|
|
|
{
|
|
|
|
m_IsBuilding = false;
|
|
|
|
Repaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
PrintHeadPanel();
|
|
|
|
|
|
|
|
EditorGUILayout.BeginVertical(Styles.testList);
|
|
|
|
m_TestListScroll = EditorGUILayout.BeginScrollView(m_TestListScroll);
|
|
|
|
bool repaint = PrintTestList(m_TestLines);
|
|
|
|
GUILayout.FlexibleSpace();
|
|
|
|
EditorGUILayout.EndScrollView();
|
|
|
|
EditorGUILayout.EndVertical();
|
|
|
|
|
|
|
|
RenderDetails();
|
|
|
|
|
|
|
|
if (repaint) Repaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void PrintHeadPanel()
|
|
|
|
{
|
|
|
|
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
|
|
|
|
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
|
|
|
|
if (GUILayout.Button(m_GUIRunAllTests, EditorStyles.toolbarButton))
|
|
|
|
{
|
|
|
|
RunTests(TestComponent.FindAllTestsOnScene().Cast<ITestComponent>().ToList());
|
|
|
|
}
|
|
|
|
EditorGUI.BeginDisabledGroup(!Selection.gameObjects.Any (t => t.GetComponent(typeof(ITestComponent))));
|
|
|
|
if (GUILayout.Button(m_GUIRunSelectedTests, EditorStyles.toolbarButton))
|
|
|
|
{
|
|
|
|
RunTests(Selection.gameObjects.Select(t => t.GetComponent(typeof(TestComponent))).Cast<ITestComponent>().ToList());
|
|
|
|
}
|
|
|
|
EditorGUI.EndDisabledGroup();
|
|
|
|
if (GUILayout.Button(m_GUICreateNewTest, EditorStyles.toolbarButton))
|
|
|
|
{
|
|
|
|
var test = TestComponent.CreateTest();
|
|
|
|
if (Selection.gameObjects.Length == 1
|
|
|
|
&& Selection.activeGameObject != null
|
|
|
|
&& Selection.activeGameObject.GetComponent<TestComponent>())
|
|
|
|
{
|
|
|
|
test.transform.parent = Selection.activeGameObject.transform.parent;
|
|
|
|
}
|
|
|
|
Selection.activeGameObject = test;
|
|
|
|
RebuildTestList();
|
|
|
|
}
|
|
|
|
EditorGUI.EndDisabledGroup();
|
|
|
|
|
|
|
|
GUILayout.FlexibleSpace ();
|
|
|
|
|
|
|
|
m_FilterSettings.OnGUI ();
|
|
|
|
|
|
|
|
EditorGUILayout.EndHorizontal ();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void AddItemsToMenu(GenericMenu menu)
|
|
|
|
{
|
|
|
|
menu.AddItem(m_GUIBlockUI, m_Settings.blockUIWhenRunning, m_Settings.ToggleBlockUIWhenRunning);
|
|
|
|
menu.AddItem(m_GUIPauseOnFailure, m_Settings.pauseOnTestFailure, m_Settings.TogglePauseOnTestFailure);
|
|
|
|
}
|
|
|
|
|
|
|
|
private bool PrintTestList(IntegrationTestRendererBase[] renderedLines)
|
|
|
|
{
|
|
|
|
if (renderedLines == null) return false;
|
|
|
|
|
|
|
|
var filter = m_FilterSettings.BuildRenderingOptions();
|
|
|
|
|
|
|
|
bool repaint = false;
|
|
|
|
foreach (var renderedLine in renderedLines)
|
|
|
|
{
|
|
|
|
repaint |= renderedLine.Render(filter);
|
|
|
|
}
|
|
|
|
return repaint;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void RenderDetails()
|
|
|
|
{
|
|
|
|
var ctrlId = GUIUtility.GetControlID(FocusType.Passive);
|
|
|
|
|
|
|
|
Rect rect = GUILayoutUtility.GetLastRect();
|
|
|
|
rect.y = rect.height + rect.y - 1;
|
|
|
|
rect.height = 3;
|
|
|
|
|
|
|
|
EditorGUIUtility.AddCursorRect(rect, MouseCursor.ResizeVertical);
|
|
|
|
var e = Event.current;
|
|
|
|
switch (e.type)
|
|
|
|
{
|
|
|
|
case EventType.MouseDown:
|
|
|
|
if (GUIUtility.hotControl == 0 && rect.Contains(e.mousePosition))
|
|
|
|
GUIUtility.hotControl = ctrlId;
|
|
|
|
break;
|
|
|
|
case EventType.MouseDrag:
|
|
|
|
if (GUIUtility.hotControl == ctrlId)
|
|
|
|
{
|
|
|
|
m_HorizontalSplitBarPosition -= e.delta.y;
|
|
|
|
if (m_HorizontalSplitBarPosition < 20) m_HorizontalSplitBarPosition = 20;
|
|
|
|
Repaint();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EventType.MouseUp:
|
|
|
|
if (GUIUtility.hotControl == ctrlId)
|
|
|
|
GUIUtility.hotControl = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_TestInfoScroll = EditorGUILayout.BeginScrollView(m_TestInfoScroll, GUILayout.MinHeight(m_HorizontalSplitBarPosition));
|
|
|
|
|
|
|
|
if (m_SelectedLine != null)
|
|
|
|
UpdateResultText(m_SelectedLine);
|
|
|
|
|
|
|
|
EditorGUILayout.SelectableLabel(m_resultText, Styles.info,
|
|
|
|
GUILayout.ExpandHeight(true),
|
|
|
|
GUILayout.ExpandWidth(true),
|
|
|
|
GUILayout.MinWidth(m_resultTextSize.x),
|
|
|
|
GUILayout.MinHeight(m_resultTextSize.y));
|
|
|
|
EditorGUILayout.EndScrollView();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void UpdateResultText(GameObject go)
|
|
|
|
{
|
|
|
|
if(go == m_lastSelectedGO) return;
|
|
|
|
m_lastSelectedGO = go;
|
|
|
|
var result = m_ResultList.Find(r => r.GameObject == go);
|
|
|
|
if (result == null)
|
|
|
|
{
|
|
|
|
m_resultText = string.Empty;
|
|
|
|
m_resultTextSize = Styles.info.CalcSize(new GUIContent(string.Empty));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var sb = new StringBuilder(result.Name.Trim());
|
|
|
|
if (!string.IsNullOrEmpty(result.messages))
|
|
|
|
{
|
|
|
|
sb.Append("\n---\n");
|
|
|
|
sb.Append(result.messages.Trim());
|
|
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(result.stacktrace))
|
|
|
|
{
|
|
|
|
sb.Append("\n---\n");
|
|
|
|
sb.Append(result.stacktrace.Trim());
|
|
|
|
}
|
|
|
|
if(sb.Length>m_resultTestMaxLength)
|
|
|
|
{
|
|
|
|
sb.Length = m_resultTestMaxLength;
|
|
|
|
sb.AppendFormat("...\n\n---MESSAGE TRUNCATED AT {0} CHARACTERS---", m_resultTestMaxLength);
|
|
|
|
}
|
|
|
|
m_resultText = sb.ToString().Trim();
|
|
|
|
m_resultTextSize = Styles.info.CalcSize(new GUIContent(m_resultText));
|
|
|
|
}
|
|
|
|
|
|
|
|
public void OnInspectorUpdate()
|
|
|
|
{
|
|
|
|
if (focusedWindow != this) Repaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void SetCurrentTest(TestComponent tc)
|
|
|
|
{
|
|
|
|
foreach (var line in m_TestLines)
|
|
|
|
line.SetCurrentTest(tc);
|
|
|
|
}
|
|
|
|
|
|
|
|
class RunnerCallback : ITestRunnerCallback
|
|
|
|
{
|
|
|
|
private readonly IntegrationTestsRunnerWindow m_Window;
|
|
|
|
private int m_TestNumber;
|
|
|
|
private int m_CurrentTestNumber;
|
|
|
|
|
|
|
|
private readonly bool m_ConsoleErrorOnPauseValue;
|
|
|
|
private readonly bool m_RunInBackground;
|
|
|
|
private TestComponent m_CurrentTest;
|
|
|
|
|
|
|
|
public RunnerCallback(IntegrationTestsRunnerWindow window)
|
|
|
|
{
|
|
|
|
m_Window = window;
|
|
|
|
|
|
|
|
m_ConsoleErrorOnPauseValue = GuiHelper.GetConsoleErrorPause();
|
|
|
|
GuiHelper.SetConsoleErrorPause(false);
|
|
|
|
m_RunInBackground = PlayerSettings.runInBackground;
|
|
|
|
PlayerSettings.runInBackground = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void RunStarted(string platform, List<TestComponent> testsToRun)
|
|
|
|
{
|
|
|
|
EditorApplication.update += OnEditorUpdate;
|
|
|
|
m_TestNumber = testsToRun.Count;
|
|
|
|
foreach (var test in testsToRun)
|
|
|
|
{
|
|
|
|
var result = m_Window.m_ResultList.Find(r => r.TestComponent == test);
|
|
|
|
if (result != null) result.Reset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void RunFinished(List<TestResult> testResults)
|
|
|
|
{
|
|
|
|
m_Window.SetCurrentTest(null);
|
|
|
|
m_CurrentTest = null;
|
|
|
|
EditorApplication.update -= OnEditorUpdate;
|
|
|
|
EditorApplication.isPlaying = false;
|
|
|
|
EditorUtility.ClearProgressBar();
|
|
|
|
GuiHelper.SetConsoleErrorPause(m_ConsoleErrorOnPauseValue);
|
|
|
|
PlayerSettings.runInBackground = m_RunInBackground;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void AllScenesFinished()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public void TestStarted(TestResult test)
|
|
|
|
{
|
|
|
|
m_Window.SetCurrentTest(test.TestComponent);
|
|
|
|
m_CurrentTest = test.TestComponent;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void TestFinished(TestResult test)
|
|
|
|
{
|
|
|
|
m_CurrentTestNumber++;
|
|
|
|
|
|
|
|
var result = m_Window.m_ResultList.Find(r => r.Id == test.Id);
|
|
|
|
if (result != null)
|
|
|
|
result.Update(test);
|
|
|
|
else
|
|
|
|
m_Window.m_ResultList.Add(test);
|
|
|
|
|
|
|
|
if(test.IsFailure && m_Window.m_Settings.pauseOnTestFailure)
|
|
|
|
{
|
|
|
|
EditorUtility.ClearProgressBar();
|
|
|
|
EditorApplication.isPaused = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void TestRunInterrupted(List<ITestComponent> testsNotRun)
|
|
|
|
{
|
|
|
|
Debug.Log("Test run interrupted");
|
|
|
|
RunFinished(new List<TestResult>());
|
|
|
|
}
|
|
|
|
|
|
|
|
private void OnEditorUpdate()
|
|
|
|
{
|
|
|
|
if(!EditorApplication.isPlaying)
|
|
|
|
{
|
|
|
|
TestRunInterrupted(null);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_Window.m_Settings.blockUIWhenRunning
|
|
|
|
&& m_CurrentTest != null
|
|
|
|
&& !EditorApplication.isPaused
|
|
|
|
&& EditorUtility.DisplayCancelableProgressBar("Integration Test Runner",
|
|
|
|
"Running " + m_CurrentTest.Name,
|
|
|
|
(float)m_CurrentTestNumber / m_TestNumber))
|
|
|
|
{
|
|
|
|
TestRunInterrupted(null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[MenuItem("Unity Test Tools/Integration Test Runner %#&t")]
|
|
|
|
public static IntegrationTestsRunnerWindow ShowWindow()
|
|
|
|
{
|
|
|
|
var w = GetWindow(typeof(IntegrationTestsRunnerWindow));
|
|
|
|
w.Show();
|
|
|
|
return w as IntegrationTestsRunnerWindow;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|