initial project folder
This commit is contained in:
@ -0,0 +1,11 @@
|
||||
namespace UnityEditor.TestTools.TestRunner.GUI
|
||||
{
|
||||
internal class AssetsDatabaseHelper : IAssetsDatabaseHelper
|
||||
{
|
||||
public void OpenAssetInItsDefaultExternalEditor(string assetPath, int line)
|
||||
{
|
||||
var asset = AssetDatabase.LoadMainAssetAtPath(assetPath);
|
||||
AssetDatabase.OpenAsset(asset, line);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 740b3785866edda4b8d1e1a05570a5f8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEditor.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.TestTools.TestRunner.GUI
|
||||
{
|
||||
internal class GuiHelper : IGuiHelper
|
||||
{
|
||||
public GuiHelper(IMonoCecilHelper monoCecilHelper, IAssetsDatabaseHelper assetsDatabaseHelper)
|
||||
{
|
||||
MonoCecilHelper = monoCecilHelper;
|
||||
AssetsDatabaseHelper = assetsDatabaseHelper;
|
||||
}
|
||||
|
||||
protected IMonoCecilHelper MonoCecilHelper { get; private set; }
|
||||
public IAssetsDatabaseHelper AssetsDatabaseHelper { get; private set; }
|
||||
|
||||
public void OpenScriptInExternalEditor(Type type, MethodInfo method)
|
||||
{
|
||||
var fileOpenInfo = GetFileOpenInfo(type, method);
|
||||
|
||||
if (string.IsNullOrEmpty(fileOpenInfo.FilePath))
|
||||
{
|
||||
Debug.LogWarning("Failed to open test method source code in external editor. Inconsistent filename and yield return operator in target method.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (fileOpenInfo.LineNumber == 1)
|
||||
{
|
||||
Debug.LogWarning("Failed to get a line number for unity test method. So please find it in opened file in external editor.");
|
||||
}
|
||||
|
||||
AssetsDatabaseHelper.OpenAssetInItsDefaultExternalEditor(fileOpenInfo.FilePath, fileOpenInfo.LineNumber);
|
||||
}
|
||||
|
||||
public IFileOpenInfo GetFileOpenInfo(Type type, MethodInfo method)
|
||||
{
|
||||
const string fileExtension = ".cs";
|
||||
|
||||
var fileOpenInfo = MonoCecilHelper.TryGetCecilFileOpenInfo(type, method);
|
||||
if (string.IsNullOrEmpty(fileOpenInfo.FilePath))
|
||||
{
|
||||
var dirPath = Paths.UnifyDirectorySeparator(Application.dataPath);
|
||||
var allCsFiles = Directory.GetFiles(dirPath, string.Format("*{0}", fileExtension), SearchOption.AllDirectories)
|
||||
.Select(Paths.UnifyDirectorySeparator);
|
||||
|
||||
var fileName = allCsFiles.FirstOrDefault(x =>
|
||||
x.Split(Path.DirectorySeparatorChar).Last().Equals(string.Concat(type.Name, fileExtension)));
|
||||
|
||||
fileOpenInfo.FilePath = fileName ?? string.Empty;
|
||||
}
|
||||
|
||||
fileOpenInfo.FilePath = FilePathToAssetsRelativeAndUnified(fileOpenInfo.FilePath);
|
||||
|
||||
return fileOpenInfo;
|
||||
}
|
||||
|
||||
public string FilePathToAssetsRelativeAndUnified(string filePath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(filePath))
|
||||
return string.Empty;
|
||||
|
||||
filePath = Paths.UnifyDirectorySeparator(filePath);
|
||||
var length = Paths.UnifyDirectorySeparator(Application.dataPath).Length - "Assets".Length;
|
||||
|
||||
return filePath.Substring(length);
|
||||
}
|
||||
|
||||
public bool OpenScriptInExternalEditor(string stacktrace)
|
||||
{
|
||||
if (string.IsNullOrEmpty(stacktrace))
|
||||
return false;
|
||||
|
||||
var regex = new Regex("in (?<path>.*):{1}(?<line>[0-9]+)");
|
||||
|
||||
var matchingLines = stacktrace.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Where(x => regex.IsMatch(x)).ToList();
|
||||
if (!matchingLines.Any())
|
||||
return false;
|
||||
|
||||
var fileOpenInfo = matchingLines
|
||||
.Select(x => regex.Match(x))
|
||||
.Select(x =>
|
||||
new FileOpenInfo
|
||||
{
|
||||
FilePath = x.Groups["path"].Value,
|
||||
LineNumber = int.Parse(x.Groups["line"].Value)
|
||||
})
|
||||
.First(openInfo => !string.IsNullOrEmpty(openInfo.FilePath) && File.Exists(openInfo.FilePath));
|
||||
|
||||
var filePath = FilePathToAssetsRelativeAndUnified(fileOpenInfo.FilePath);
|
||||
AssetsDatabaseHelper.OpenAssetInItsDefaultExternalEditor(filePath, fileOpenInfo.LineNumber);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d0138170d24533e47b8e6c250c6d7fbc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,7 @@
|
||||
namespace UnityEditor.TestTools.TestRunner.GUI
|
||||
{
|
||||
internal interface IAssetsDatabaseHelper
|
||||
{
|
||||
void OpenAssetInItsDefaultExternalEditor(string assetPath, int line);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 208e46d59ff6e304db0318377d20f5a1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace UnityEditor.TestTools.TestRunner.GUI
|
||||
{
|
||||
internal interface IGuiHelper
|
||||
{
|
||||
bool OpenScriptInExternalEditor(string stacktrace);
|
||||
void OpenScriptInExternalEditor(Type type, MethodInfo method);
|
||||
IFileOpenInfo GetFileOpenInfo(Type type, MethodInfo method);
|
||||
string FilePathToAssetsRelativeAndUnified(string filePath);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd57cf917f61bbb42b8f030436426ddd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07ea0326ed848fb4489187cb58f96113
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,12 @@
|
||||
namespace UnityEditor.TestTools.TestRunner.GUI
|
||||
{
|
||||
internal class RenderingOptions
|
||||
{
|
||||
public string nameFilter;
|
||||
public bool showSucceeded;
|
||||
public bool showFailed;
|
||||
public bool showIgnored;
|
||||
public bool showNotRunned;
|
||||
public string[] categories;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 87357ff0dec4ef348a295235835c6ee4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,175 @@
|
||||
// ****************************************************************
|
||||
// Based on nUnit 2.6.2 (http://www.nunit.org/)
|
||||
// ****************************************************************
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.TestTools.TestRunner.GUI;
|
||||
|
||||
namespace UnityEditor.TestTools.TestRunner.GUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for ResultSummarizer.
|
||||
/// </summary>
|
||||
internal class ResultSummarizer
|
||||
{
|
||||
private int m_ErrorCount = -1;
|
||||
private int m_FailureCount;
|
||||
private int m_IgnoreCount = -1;
|
||||
private int m_InconclusiveCount = -1;
|
||||
private int m_NotRunnable = -1;
|
||||
private int m_ResultCount;
|
||||
private int m_SkipCount;
|
||||
private int m_SuccessCount;
|
||||
private int m_TestsRun;
|
||||
|
||||
private TimeSpan m_Duration = TimeSpan.FromSeconds(0);
|
||||
|
||||
public ResultSummarizer(IEnumerable<TestRunnerResult> results)
|
||||
{
|
||||
foreach (var result in results)
|
||||
Summarize(result);
|
||||
}
|
||||
|
||||
public bool success
|
||||
{
|
||||
get { return m_FailureCount == 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of test cases for which results
|
||||
/// have been summarized. Any tests excluded by use of
|
||||
/// Category or Explicit attributes are not counted.
|
||||
/// </summary>
|
||||
public int ResultCount
|
||||
{
|
||||
get { return m_ResultCount; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of test cases actually run, which
|
||||
/// is the same as ResultCount, less any Skipped, Ignored
|
||||
/// or NonRunnable tests.
|
||||
/// </summary>
|
||||
public int TestsRun
|
||||
{
|
||||
get { return m_TestsRun; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of tests that passed
|
||||
/// </summary>
|
||||
public int Passed
|
||||
{
|
||||
get { return m_SuccessCount; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of test cases that had an error.
|
||||
/// </summary>
|
||||
public int errors
|
||||
{
|
||||
get { return m_ErrorCount; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of test cases that failed.
|
||||
/// </summary>
|
||||
public int failures
|
||||
{
|
||||
get { return m_FailureCount; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of test cases that failed.
|
||||
/// </summary>
|
||||
public int inconclusive
|
||||
{
|
||||
get { return m_InconclusiveCount; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of test cases that were not runnable
|
||||
/// due to errors in the signature of the class or method.
|
||||
/// Such tests are also counted as Errors.
|
||||
/// </summary>
|
||||
public int notRunnable
|
||||
{
|
||||
get { return m_NotRunnable; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of test cases that were skipped.
|
||||
/// </summary>
|
||||
public int Skipped
|
||||
{
|
||||
get { return m_SkipCount; }
|
||||
}
|
||||
|
||||
public int ignored
|
||||
{
|
||||
get { return m_IgnoreCount; }
|
||||
}
|
||||
|
||||
public double duration
|
||||
{
|
||||
get { return m_Duration.TotalSeconds; }
|
||||
}
|
||||
|
||||
public int testsNotRun
|
||||
{
|
||||
get { return m_SkipCount + m_IgnoreCount + m_NotRunnable; }
|
||||
}
|
||||
|
||||
public void Summarize(TestRunnerResult result)
|
||||
{
|
||||
m_Duration += TimeSpan.FromSeconds(result.duration);
|
||||
m_ResultCount++;
|
||||
|
||||
if (result.resultStatus != TestRunnerResult.ResultStatus.NotRun)
|
||||
{
|
||||
//TODO implement missing features
|
||||
// if(result.IsIgnored)
|
||||
// {
|
||||
// m_IgnoreCount++;
|
||||
// return;
|
||||
// }
|
||||
|
||||
m_SkipCount++;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (result.resultStatus)
|
||||
{
|
||||
case TestRunnerResult.ResultStatus.Passed:
|
||||
m_SuccessCount++;
|
||||
m_TestsRun++;
|
||||
break;
|
||||
case TestRunnerResult.ResultStatus.Failed:
|
||||
m_FailureCount++;
|
||||
m_TestsRun++;
|
||||
break;
|
||||
//TODO implement missing features
|
||||
// case TestResultState.Error:
|
||||
// case TestResultState.Cancelled:
|
||||
// m_ErrorCount++;
|
||||
// m_TestsRun++;
|
||||
// break;
|
||||
// case TestResultState.Inconclusive:
|
||||
// m_InconclusiveCount++;
|
||||
// m_TestsRun++;
|
||||
// break;
|
||||
// case TestResultState.NotRunnable:
|
||||
// m_NotRunnable++;
|
||||
// // errorCount++;
|
||||
// break;
|
||||
// case TestResultState.Ignored:
|
||||
// m_IgnoreCount++;
|
||||
// break;
|
||||
default:
|
||||
m_SkipCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 95a2914724952ef40bb590d0607fc878
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,105 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools.TestRunner.GUI;
|
||||
|
||||
namespace UnityEditor.TestTools.TestRunner.GUI
|
||||
{
|
||||
internal class TestFilterSettings
|
||||
{
|
||||
public bool showSucceeded;
|
||||
public bool showFailed;
|
||||
public bool showIgnored;
|
||||
public bool showNotRun;
|
||||
|
||||
public string filterByName;
|
||||
public int filterByCategory;
|
||||
|
||||
private GUIContent m_SucceededBtn;
|
||||
private GUIContent m_FailedBtn;
|
||||
private GUIContent m_IgnoredBtn;
|
||||
private GUIContent m_NotRunBtn;
|
||||
|
||||
public string[] availableCategories;
|
||||
|
||||
private readonly string m_PrefsKey;
|
||||
|
||||
public TestFilterSettings(string prefsKey)
|
||||
{
|
||||
availableCategories = null;
|
||||
m_PrefsKey = prefsKey;
|
||||
Load();
|
||||
UpdateCounters(Enumerable.Empty<TestRunnerResult>());
|
||||
}
|
||||
|
||||
public void Load()
|
||||
{
|
||||
showSucceeded = EditorPrefs.GetBool(m_PrefsKey + ".ShowSucceeded", true);
|
||||
showFailed = EditorPrefs.GetBool(m_PrefsKey + ".ShowFailed", true);
|
||||
showIgnored = EditorPrefs.GetBool(m_PrefsKey + ".ShowIgnored", true);
|
||||
showNotRun = EditorPrefs.GetBool(m_PrefsKey + ".ShowNotRun", true);
|
||||
filterByName = EditorPrefs.GetString(m_PrefsKey + ".FilterByName", string.Empty);
|
||||
filterByCategory = EditorPrefs.GetInt(m_PrefsKey + ".FilterByCategory", 0);
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
EditorPrefs.SetBool(m_PrefsKey + ".ShowSucceeded", showSucceeded);
|
||||
EditorPrefs.SetBool(m_PrefsKey + ".ShowFailed", showFailed);
|
||||
EditorPrefs.SetBool(m_PrefsKey + ".ShowIgnored", showIgnored);
|
||||
EditorPrefs.SetBool(m_PrefsKey + ".ShowNotRun", showNotRun);
|
||||
EditorPrefs.SetString(m_PrefsKey + ".FilterByName", filterByName);
|
||||
EditorPrefs.SetInt(m_PrefsKey + ".FilterByCategory", filterByCategory);
|
||||
}
|
||||
|
||||
public void UpdateCounters(IEnumerable<TestRunnerResult> results)
|
||||
{
|
||||
var summary = new ResultSummarizer(results);
|
||||
|
||||
m_SucceededBtn = new GUIContent(summary.Passed.ToString(), Icons.s_SuccessImg, "Show tests that succeeded");
|
||||
m_FailedBtn = new GUIContent((summary.errors + summary.failures + summary.inconclusive).ToString(), Icons.s_FailImg, "Show tests that failed");
|
||||
m_IgnoredBtn = new GUIContent((summary.ignored + summary.notRunnable).ToString(), Icons.s_IgnoreImg, "Show tests that are ignored");
|
||||
m_NotRunBtn = new GUIContent((summary.testsNotRun - summary.ignored - summary.notRunnable).ToString(), Icons.s_UnknownImg, "Show tests that didn't run");
|
||||
}
|
||||
|
||||
public string[] GetSelectedCategories()
|
||||
{
|
||||
if (availableCategories == null)
|
||||
return new string[0];
|
||||
|
||||
return availableCategories.Where((c, i) => (filterByCategory & (1 << i)) != 0).ToArray();
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
filterByName = GUILayout.TextField(filterByName, "ToolbarSeachTextField", GUILayout.MinWidth(100), GUILayout.MaxWidth(250), GUILayout.ExpandWidth(true));
|
||||
if (GUILayout.Button(GUIContent.none, string.IsNullOrEmpty(filterByName) ? "ToolbarSeachCancelButtonEmpty" : "ToolbarSeachCancelButton"))
|
||||
filterByName = string.Empty;
|
||||
|
||||
if (availableCategories != null && availableCategories.Length > 0)
|
||||
filterByCategory = EditorGUILayout.MaskField(filterByCategory, availableCategories, EditorStyles.toolbarDropDown, GUILayout.MaxWidth(90));
|
||||
|
||||
showSucceeded = GUILayout.Toggle(showSucceeded, m_SucceededBtn, EditorStyles.toolbarButton);
|
||||
showFailed = GUILayout.Toggle(showFailed, m_FailedBtn, EditorStyles.toolbarButton);
|
||||
showIgnored = GUILayout.Toggle(showIgnored, m_IgnoredBtn, EditorStyles.toolbarButton);
|
||||
showNotRun = GUILayout.Toggle(showNotRun, m_NotRunBtn, EditorStyles.toolbarButton);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
Save();
|
||||
}
|
||||
|
||||
public RenderingOptions BuildRenderingOptions()
|
||||
{
|
||||
var options = new RenderingOptions();
|
||||
options.showSucceeded = showSucceeded;
|
||||
options.showFailed = showFailed;
|
||||
options.showIgnored = showIgnored;
|
||||
options.showNotRunned = showNotRun;
|
||||
options.nameFilter = filterByName;
|
||||
options.categories = GetSelectedCategories();
|
||||
return options;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 046c3854296c5ec48bac50da6ca248ec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,111 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEditor.TestTools.TestRunner.Api;
|
||||
using UnityEngine.TestRunner.NUnitExtensions;
|
||||
using UnityEngine.TestTools.TestRunner.GUI;
|
||||
using UnityEngine.TestRunner.NUnitExtensions.Filters;
|
||||
|
||||
namespace UnityEditor.TestTools.TestRunner.GUI
|
||||
{
|
||||
internal class TestTreeViewBuilder
|
||||
{
|
||||
public List<TestRunnerResult> results = new List<TestRunnerResult>();
|
||||
private readonly List<TestRunnerResult> m_OldTestResultList;
|
||||
private readonly TestRunnerUIFilter m_UIFilter;
|
||||
private readonly ITestAdaptor m_TestListRoot;
|
||||
|
||||
private readonly List<string> m_AvailableCategories = new List<string>();
|
||||
|
||||
public string[] AvailableCategories
|
||||
{
|
||||
get { return m_AvailableCategories.Distinct().OrderBy(a => a).ToArray(); }
|
||||
}
|
||||
|
||||
public TestTreeViewBuilder(ITestAdaptor tests, List<TestRunnerResult> oldTestResultResults, TestRunnerUIFilter uiFilter)
|
||||
{
|
||||
m_AvailableCategories.Add(CategoryFilterExtended.k_DefaultCategory);
|
||||
m_OldTestResultList = oldTestResultResults;
|
||||
m_TestListRoot = tests;
|
||||
m_UIFilter = uiFilter;
|
||||
}
|
||||
|
||||
public TreeViewItem BuildTreeView(TestFilterSettings settings, bool sceneBased, string sceneName)
|
||||
{
|
||||
var rootItem = new TreeViewItem(int.MaxValue, 0, null, "Invisible Root Item");
|
||||
ParseTestTree(0, rootItem, m_TestListRoot);
|
||||
return rootItem;
|
||||
}
|
||||
|
||||
private bool IsFilteredOutByUIFilter(ITestAdaptor test, TestRunnerResult result)
|
||||
{
|
||||
if (m_UIFilter.PassedHidden && result.resultStatus == TestRunnerResult.ResultStatus.Passed)
|
||||
return true;
|
||||
if (m_UIFilter.FailedHidden && (result.resultStatus == TestRunnerResult.ResultStatus.Failed || result.resultStatus == TestRunnerResult.ResultStatus.Inconclusive))
|
||||
return true;
|
||||
if (m_UIFilter.NotRunHidden && (result.resultStatus == TestRunnerResult.ResultStatus.NotRun || result.resultStatus == TestRunnerResult.ResultStatus.Skipped))
|
||||
return true;
|
||||
if (m_UIFilter.CategoryFilter.Length > 0)
|
||||
return !test.Categories.Any(category => m_UIFilter.CategoryFilter.Contains(category));
|
||||
return false;
|
||||
}
|
||||
|
||||
private void ParseTestTree(int depth, TreeViewItem rootItem, ITestAdaptor testElement)
|
||||
{
|
||||
m_AvailableCategories.AddRange(testElement.Categories);
|
||||
|
||||
var testElementId = testElement.UniqueName;
|
||||
if (!testElement.HasChildren)
|
||||
{
|
||||
var result = m_OldTestResultList.FirstOrDefault(a => a.uniqueId == testElementId);
|
||||
|
||||
if (result != null &&
|
||||
(result.ignoredOrSkipped
|
||||
|| result.notRunnable
|
||||
|| testElement.RunState == RunState.NotRunnable
|
||||
|| testElement.RunState == RunState.Ignored
|
||||
|| testElement.RunState == RunState.Skipped
|
||||
)
|
||||
)
|
||||
{
|
||||
//if the test was or becomes ignored or not runnable, we recreate the result in case it has changed
|
||||
result = null;
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
result = new TestRunnerResult(testElement);
|
||||
}
|
||||
results.Add(result);
|
||||
|
||||
var test = new TestTreeViewItem(testElement, depth, rootItem);
|
||||
if (!IsFilteredOutByUIFilter(testElement, result))
|
||||
rootItem.AddChild(test);
|
||||
test.SetResult(result);
|
||||
return;
|
||||
}
|
||||
|
||||
var groupResult = m_OldTestResultList.FirstOrDefault(a => a.uniqueId == testElementId);
|
||||
if (groupResult == null)
|
||||
{
|
||||
groupResult = new TestRunnerResult(testElement);
|
||||
}
|
||||
|
||||
results.Add(groupResult);
|
||||
var group = new TestTreeViewItem(testElement, depth, rootItem);
|
||||
group.SetResult(groupResult);
|
||||
|
||||
depth++;
|
||||
foreach (var child in testElement.Children)
|
||||
{
|
||||
ParseTestTree(depth, group, child);
|
||||
}
|
||||
|
||||
|
||||
if (testElement.IsTestAssembly && !testElement.HasChildren)
|
||||
return;
|
||||
|
||||
if (group.hasChildren)
|
||||
rootItem.AddChild(group);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e17c88b021c2a4c409b3f15b0d80ac62
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,135 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEditor.ProjectWindowCallback;
|
||||
using UnityEditor.Scripting.ScriptCompilation;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.TestTools.TestRunner.GUI
|
||||
{
|
||||
internal class TestListGUIHelper
|
||||
{
|
||||
private const string kResourcesTemplatePath = "Resources/ScriptTemplates";
|
||||
private const string kAssemblyDefinitionTestTemplate = "92-Assembly Definition-NewTestAssembly.asmdef.txt";
|
||||
|
||||
private const string kAssemblyDefinitionEditModeTestTemplate =
|
||||
"92-Assembly Definition-NewEditModeTestAssembly.asmdef.txt";
|
||||
|
||||
private const string kTestScriptTemplate = "83-C# Script-NewTestScript.cs.txt";
|
||||
private const string kNewTestScriptName = "NewTestScript.cs";
|
||||
private const string kNunit = "nunit.framework.dll";
|
||||
|
||||
[MenuItem("Assets/Create/Testing/Tests Assembly Folder", false, 83)]
|
||||
public static void MenuItemAddFolderAndAsmDefForTesting()
|
||||
{
|
||||
AddFolderAndAsmDefForTesting();
|
||||
}
|
||||
|
||||
[MenuItem("Assets/Create/Testing/Tests Assembly Folder", true, 83)]
|
||||
public static bool MenuItemAddFolderAndAsmDefForTestingWithValidation()
|
||||
{
|
||||
return !SelectedFolderContainsTestAssembly();
|
||||
}
|
||||
|
||||
public static void AddFolderAndAsmDefForTesting(bool isEditorOnly = false)
|
||||
{
|
||||
ProjectWindowUtil.CreateFolderWithTemplates("Tests",
|
||||
isEditorOnly ? kAssemblyDefinitionEditModeTestTemplate : kAssemblyDefinitionTestTemplate);
|
||||
}
|
||||
|
||||
public static bool SelectedFolderContainsTestAssembly()
|
||||
{
|
||||
var theNearestCustomScriptAssembly = GetTheNearestCustomScriptAssembly();
|
||||
if (theNearestCustomScriptAssembly != null)
|
||||
{
|
||||
return theNearestCustomScriptAssembly.PrecompiledReferences != null && theNearestCustomScriptAssembly.PrecompiledReferences.Any(x => Path.GetFileName(x) == kNunit);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[MenuItem("Assets/Create/Testing/C# Test Script", false, 83)]
|
||||
public static void AddTest()
|
||||
{
|
||||
var basePath = Path.Combine(EditorApplication.applicationContentsPath, kResourcesTemplatePath);
|
||||
var destPath = Path.Combine(GetActiveFolderPath(), kNewTestScriptName);
|
||||
var templatePath = Path.Combine(basePath, kTestScriptTemplate);
|
||||
var icon = EditorGUIUtility.IconContent("cs Script Icon").image as Texture2D;
|
||||
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0,
|
||||
ScriptableObject.CreateInstance<DoCreateScriptAsset>(), destPath, icon, templatePath);
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
[MenuItem("Assets/Create/Testing/C# Test Script", true, 83)]
|
||||
public static bool CanAddScriptAndItWillCompile()
|
||||
{
|
||||
return CanAddEditModeTestScriptAndItWillCompile() || CanAddPlayModeTestScriptAndItWillCompile();
|
||||
}
|
||||
|
||||
public static bool CanAddEditModeTestScriptAndItWillCompile()
|
||||
{
|
||||
var theNearestCustomScriptAssembly = GetTheNearestCustomScriptAssembly();
|
||||
if (theNearestCustomScriptAssembly != null)
|
||||
{
|
||||
return (theNearestCustomScriptAssembly.AssemblyFlags & AssemblyFlags.EditorOnly) ==
|
||||
AssemblyFlags.EditorOnly;
|
||||
}
|
||||
|
||||
var activeFolderPath = GetActiveFolderPath();
|
||||
return activeFolderPath.ToLower().Contains("/editor");
|
||||
}
|
||||
|
||||
public static bool CanAddPlayModeTestScriptAndItWillCompile()
|
||||
{
|
||||
if (PlayerSettings.playModeTestRunnerEnabled)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var theNearestCustomScriptAssembly = GetTheNearestCustomScriptAssembly();
|
||||
|
||||
if (theNearestCustomScriptAssembly == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var hasTestAssemblyFlag = theNearestCustomScriptAssembly.PrecompiledReferences != null && theNearestCustomScriptAssembly.PrecompiledReferences.Any(x => Path.GetFileName(x) == kNunit);;
|
||||
var editorOnlyAssembly = (theNearestCustomScriptAssembly.AssemblyFlags & AssemblyFlags.EditorOnly) != 0;
|
||||
|
||||
return hasTestAssemblyFlag && !editorOnlyAssembly;
|
||||
}
|
||||
|
||||
public static string GetActiveFolderPath()
|
||||
{
|
||||
var path = "Assets";
|
||||
|
||||
foreach (var obj in Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Assets))
|
||||
{
|
||||
path = AssetDatabase.GetAssetPath(obj);
|
||||
if (!string.IsNullOrEmpty(path) && File.Exists(path))
|
||||
{
|
||||
path = Path.GetDirectoryName(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
private static CustomScriptAssembly GetTheNearestCustomScriptAssembly()
|
||||
{
|
||||
CustomScriptAssembly findCustomScriptAssemblyFromScriptPath;
|
||||
try
|
||||
{
|
||||
findCustomScriptAssemblyFromScriptPath =
|
||||
EditorCompilationInterface.Instance.FindCustomScriptAssemblyFromScriptPath(
|
||||
Path.Combine(GetActiveFolderPath(), "Foo.cs"));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return findCustomScriptAssemblyFromScriptPath;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 97a05971510726f438153cd4987526fb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68cb547af0187634aad591a09c01cd5b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,24 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace UnityEditor.TestTools.TestRunner.GUI
|
||||
{
|
||||
internal static class Icons
|
||||
{
|
||||
public static readonly Texture2D s_FailImg;
|
||||
public static readonly Texture2D s_IgnoreImg;
|
||||
public static readonly Texture2D s_SuccessImg;
|
||||
public static readonly Texture2D s_UnknownImg;
|
||||
public static readonly Texture2D s_InconclusiveImg;
|
||||
public static readonly Texture2D s_StopwatchImg;
|
||||
|
||||
static Icons()
|
||||
{
|
||||
s_FailImg = EditorGUIUtility.IconContent("TestFailed").image as Texture2D;
|
||||
s_IgnoreImg = EditorGUIUtility.IconContent("TestIgnored").image as Texture2D;
|
||||
s_SuccessImg = EditorGUIUtility.IconContent("TestPassed").image as Texture2D;
|
||||
s_UnknownImg = EditorGUIUtility.IconContent("TestNormal").image as Texture2D;
|
||||
s_InconclusiveImg = EditorGUIUtility.IconContent("TestInconclusive").image as Texture2D;
|
||||
s_StopwatchImg = EditorGUIUtility.IconContent("TestStopwatch").image as Texture2D;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 27769e9b00b038d47aefe306a4d20bec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,93 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEditor.TestTools.TestRunner.Api;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.TestTools.TestRunner;
|
||||
using UnityEngine.TestTools.TestRunner.GUI;
|
||||
|
||||
namespace UnityEditor.TestTools.TestRunner.GUI
|
||||
{
|
||||
internal class TestListTreeViewDataSource : TreeViewDataSource
|
||||
{
|
||||
private bool m_ExpandTreeOnCreation;
|
||||
private readonly TestListGUI m_TestListGUI;
|
||||
private ITestAdaptor m_RootTest;
|
||||
|
||||
public TestListTreeViewDataSource(TreeViewController testListTree, TestListGUI testListGUI, ITestAdaptor rootTest) : base(testListTree)
|
||||
{
|
||||
showRootItem = false;
|
||||
rootIsCollapsable = false;
|
||||
m_TestListGUI = testListGUI;
|
||||
m_RootTest = rootTest;
|
||||
}
|
||||
|
||||
public override void FetchData()
|
||||
{
|
||||
var sceneName = SceneManager.GetActiveScene().name;
|
||||
if (sceneName.StartsWith("InitTestScene"))
|
||||
sceneName = PlaymodeTestsController.GetController().settings.originalScene;
|
||||
|
||||
var testListBuilder = new TestTreeViewBuilder(m_RootTest, m_TestListGUI.newResultList, m_TestListGUI.m_TestRunnerUIFilter);
|
||||
|
||||
m_RootItem = testListBuilder.BuildTreeView(null, false, sceneName);
|
||||
SetExpanded(m_RootItem, true);
|
||||
if (m_RootItem.hasChildren && m_RootItem.children.Count == 1)
|
||||
SetExpanded(m_RootItem.children[0], true);
|
||||
|
||||
if (m_ExpandTreeOnCreation)
|
||||
SetExpandedWithChildren(m_RootItem, true);
|
||||
|
||||
m_TestListGUI.newResultList = new List<TestRunnerResult>(testListBuilder.results);
|
||||
m_TestListGUI.m_TestRunnerUIFilter.availableCategories = testListBuilder.AvailableCategories;
|
||||
m_NeedRefreshRows = true;
|
||||
}
|
||||
|
||||
public override bool IsRenamingItemAllowed(TreeViewItem item)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void ExpandTreeOnCreation()
|
||||
{
|
||||
m_ExpandTreeOnCreation = true;
|
||||
}
|
||||
|
||||
public override bool IsExpandable(TreeViewItem item)
|
||||
{
|
||||
if (item is TestTreeViewItem)
|
||||
return ((TestTreeViewItem)item).IsGroupNode;
|
||||
return base.IsExpandable(item);
|
||||
}
|
||||
|
||||
protected override List<TreeViewItem> Search(TreeViewItem rootItem, string search)
|
||||
{
|
||||
var result = new List<TreeViewItem>();
|
||||
|
||||
if (rootItem.hasChildren)
|
||||
{
|
||||
foreach (var child in rootItem.children)
|
||||
{
|
||||
SearchTestTree(child, search, result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void SearchTestTree(TreeViewItem item, string search, IList<TreeViewItem> searchResult)
|
||||
{
|
||||
var testItem = item as TestTreeViewItem;
|
||||
if (!testItem.IsGroupNode)
|
||||
{
|
||||
if (testItem.FullName.ToLower().Contains(search))
|
||||
{
|
||||
searchResult.Add(item);
|
||||
}
|
||||
}
|
||||
else if (item.children != null)
|
||||
{
|
||||
foreach (var child in item.children)
|
||||
SearchTestTree(child, search, searchResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce87c287371edde43a4b5fcfdee7b9ef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,11 @@
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
|
||||
namespace UnityEditor.TestTools.TestRunner.GUI
|
||||
{
|
||||
internal class TestListTreeViewGUI : TreeViewGUI
|
||||
{
|
||||
public TestListTreeViewGUI(TreeViewController testListTree) : base(testListTree)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 52c907c81459f324497af504b84fd557
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEditor.TestTools.TestRunner.Api;
|
||||
using UnityEngine.TestTools.TestRunner.GUI;
|
||||
|
||||
namespace UnityEditor.TestTools.TestRunner.GUI
|
||||
{
|
||||
internal sealed class TestTreeViewItem : TreeViewItem
|
||||
{
|
||||
public TestRunnerResult result;
|
||||
internal ITestAdaptor m_Test;
|
||||
|
||||
public Type type;
|
||||
public MethodInfo method;
|
||||
|
||||
private const int k_ResultTestMaxLength = 15000;
|
||||
|
||||
public bool IsGroupNode { get { return m_Test.IsSuite; } }
|
||||
|
||||
public string FullName { get { return m_Test.FullName; } }
|
||||
|
||||
public TestTreeViewItem(ITestAdaptor test, int depth, TreeViewItem parent)
|
||||
: base(GetId(test), depth, parent, test.Name)
|
||||
{
|
||||
m_Test = test;
|
||||
|
||||
if (test.TypeInfo != null)
|
||||
{
|
||||
type = test.TypeInfo.Type;
|
||||
}
|
||||
if (test.Method != null)
|
||||
{
|
||||
method = test.Method.MethodInfo;
|
||||
}
|
||||
|
||||
displayName = test.Name.Replace("\n", "");
|
||||
icon = Icons.s_UnknownImg;
|
||||
}
|
||||
|
||||
private static int GetId(ITestAdaptor test)
|
||||
{
|
||||
return test.UniqueName.GetHashCode();
|
||||
}
|
||||
|
||||
public void SetResult(TestRunnerResult testResult)
|
||||
{
|
||||
result = testResult;
|
||||
result.SetResultChangedCallback(ResultUpdated);
|
||||
ResultUpdated(result);
|
||||
}
|
||||
|
||||
public string GetResultText()
|
||||
{
|
||||
var durationString = String.Format("{0:0.000}", result.duration);
|
||||
var sb = new StringBuilder(string.Format("{0} ({1}s)", displayName.Trim(), durationString));
|
||||
if (!string.IsNullOrEmpty(result.description))
|
||||
{
|
||||
sb.AppendFormat("\n{0}", result.description);
|
||||
}
|
||||
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 (!string.IsNullOrEmpty(result.output))
|
||||
{
|
||||
sb.Append("\n---\n");
|
||||
sb.Append(result.output.Trim());
|
||||
}
|
||||
if (sb.Length > k_ResultTestMaxLength)
|
||||
{
|
||||
sb.Length = k_ResultTestMaxLength;
|
||||
sb.AppendFormat("...\n\n---MESSAGE TRUNCATED AT {0} CHARACTERS---", k_ResultTestMaxLength);
|
||||
}
|
||||
return sb.ToString().Trim();
|
||||
}
|
||||
|
||||
private void ResultUpdated(TestRunnerResult testResult)
|
||||
{
|
||||
switch (testResult.resultStatus)
|
||||
{
|
||||
case TestRunnerResult.ResultStatus.Passed:
|
||||
icon = Icons.s_SuccessImg;
|
||||
break;
|
||||
case TestRunnerResult.ResultStatus.Failed:
|
||||
icon = Icons.s_FailImg;
|
||||
break;
|
||||
case TestRunnerResult.ResultStatus.Inconclusive:
|
||||
icon = Icons.s_InconclusiveImg;
|
||||
break;
|
||||
case TestRunnerResult.ResultStatus.Skipped:
|
||||
icon = Icons.s_IgnoreImg;
|
||||
break;
|
||||
default:
|
||||
if (testResult.ignoredOrSkipped)
|
||||
{
|
||||
icon = Icons.s_IgnoreImg;
|
||||
}
|
||||
else if (testResult.notRunnable)
|
||||
{
|
||||
icon = Icons.s_FailImg;
|
||||
}
|
||||
else
|
||||
{
|
||||
icon = Icons.s_UnknownImg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce567ddbf30368344bc7b80e20cac36e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,149 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor.TestTools.TestRunner.Api;
|
||||
using UnityEngine.TestTools.TestRunner.GUI;
|
||||
|
||||
namespace UnityEditor.TestTools.TestRunner.GUI
|
||||
{
|
||||
[Serializable]
|
||||
internal class TestRunnerResult : TestRunnerFilter.IClearableResult
|
||||
{
|
||||
public string id;
|
||||
public string uniqueId;
|
||||
public string name;
|
||||
public string fullName;
|
||||
public ResultStatus resultStatus = ResultStatus.NotRun;
|
||||
public float duration;
|
||||
public string messages;
|
||||
public string output;
|
||||
public string stacktrace;
|
||||
public bool notRunnable;
|
||||
public bool ignoredOrSkipped;
|
||||
public string description;
|
||||
public bool isSuite;
|
||||
public List<string> categories;
|
||||
public string parentId;
|
||||
public string parentUniqueId;
|
||||
|
||||
//This field is suppose to mark results from before domain reload
|
||||
//Such result is outdated because the code might haev changed
|
||||
//This field will get reset every time a domain reload happens
|
||||
[NonSerialized]
|
||||
public bool notOutdated;
|
||||
|
||||
protected Action<TestRunnerResult> m_OnResultUpdate;
|
||||
|
||||
internal TestRunnerResult(ITestAdaptor test)
|
||||
{
|
||||
id = test.Id;
|
||||
uniqueId = test.UniqueName;
|
||||
|
||||
fullName = test.FullName;
|
||||
name = test.Name;
|
||||
description = test.Description;
|
||||
isSuite = test.IsSuite;
|
||||
|
||||
ignoredOrSkipped = test.RunState == RunState.Ignored || test.RunState == RunState.Skipped;
|
||||
notRunnable = test.RunState == RunState.NotRunnable;
|
||||
|
||||
if (ignoredOrSkipped)
|
||||
{
|
||||
messages = test.SkipReason;
|
||||
}
|
||||
if (notRunnable)
|
||||
{
|
||||
resultStatus = ResultStatus.Failed;
|
||||
messages = test.SkipReason;
|
||||
}
|
||||
categories = test.Categories.ToList();
|
||||
parentId = test.ParentId;
|
||||
parentUniqueId = test.ParentUniqueName;
|
||||
}
|
||||
|
||||
internal TestRunnerResult(ITestResultAdaptor testResult) : this(testResult.Test)
|
||||
{
|
||||
notOutdated = true;
|
||||
|
||||
messages = testResult.Message;
|
||||
output = testResult.Output;
|
||||
stacktrace = testResult.StackTrace;
|
||||
duration = (float)testResult.Duration;
|
||||
if (testResult.Test.IsSuite && testResult.ResultState == "Ignored")
|
||||
{
|
||||
resultStatus = ResultStatus.Passed;
|
||||
}
|
||||
else
|
||||
{
|
||||
resultStatus = ParseNUnitResultStatus(testResult.TestStatus);
|
||||
}
|
||||
}
|
||||
|
||||
public void Update(TestRunnerResult result)
|
||||
{
|
||||
if (ReferenceEquals(result, null))
|
||||
return;
|
||||
resultStatus = result.resultStatus;
|
||||
duration = result.duration;
|
||||
messages = result.messages;
|
||||
output = result.output;
|
||||
stacktrace = result.stacktrace;
|
||||
ignoredOrSkipped = result.ignoredOrSkipped;
|
||||
notRunnable = result.notRunnable;
|
||||
description = result.description;
|
||||
notOutdated = result.notOutdated;
|
||||
if (m_OnResultUpdate != null)
|
||||
m_OnResultUpdate(this);
|
||||
}
|
||||
|
||||
public void SetResultChangedCallback(Action<TestRunnerResult> resultUpdated)
|
||||
{
|
||||
m_OnResultUpdate = resultUpdated;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
internal enum ResultStatus
|
||||
{
|
||||
NotRun,
|
||||
Passed,
|
||||
Failed,
|
||||
Inconclusive,
|
||||
Skipped
|
||||
}
|
||||
|
||||
private static ResultStatus ParseNUnitResultStatus(TestStatus status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case TestStatus.Passed:
|
||||
return ResultStatus.Passed;
|
||||
case TestStatus.Failed:
|
||||
return ResultStatus.Failed;
|
||||
case TestStatus.Inconclusive:
|
||||
return ResultStatus.Inconclusive;
|
||||
case TestStatus.Skipped:
|
||||
return ResultStatus.Skipped;
|
||||
default:
|
||||
return ResultStatus.NotRun;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0} ({1})", name, fullName);
|
||||
}
|
||||
|
||||
public string Id { get { return uniqueId; } }
|
||||
public string FullName { get { return fullName; } }
|
||||
public string ParentId { get { return parentUniqueId; } }
|
||||
public bool IsSuite { get { return isSuite; } }
|
||||
public List<string> Categories { get { return categories; } }
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
resultStatus = ResultStatus.NotRun;
|
||||
if (m_OnResultUpdate != null)
|
||||
m_OnResultUpdate(this);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a04a45bbed9e1714f9902fc9443669b9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,167 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools.TestRunner.GUI;
|
||||
|
||||
namespace UnityEditor.TestTools.TestRunner.GUI
|
||||
{
|
||||
[Serializable]
|
||||
internal class TestRunnerUIFilter
|
||||
{
|
||||
private int m_PassedCount;
|
||||
private int m_FailedCount;
|
||||
private int m_NotRunCount;
|
||||
private int m_InconclusiveCount;
|
||||
private int m_SkippedCount;
|
||||
|
||||
public int PassedCount { get { return m_PassedCount; } }
|
||||
public int FailedCount { get { return m_FailedCount + m_InconclusiveCount; } }
|
||||
public int NotRunCount { get { return m_NotRunCount + m_SkippedCount; } }
|
||||
|
||||
[SerializeField]
|
||||
public bool PassedHidden;
|
||||
[SerializeField]
|
||||
public bool FailedHidden;
|
||||
[SerializeField]
|
||||
public bool NotRunHidden;
|
||||
|
||||
[SerializeField]
|
||||
private string m_SearchString;
|
||||
[SerializeField]
|
||||
private int selectedCategoryMask;
|
||||
|
||||
public string[] availableCategories = new string[0];
|
||||
|
||||
|
||||
private GUIContent m_SucceededBtn;
|
||||
private GUIContent m_FailedBtn;
|
||||
private GUIContent m_NotRunBtn;
|
||||
|
||||
public Action RebuildTestList;
|
||||
public Action<string> SearchStringChanged;
|
||||
public bool IsFiltering
|
||||
{
|
||||
get
|
||||
{
|
||||
return !string.IsNullOrEmpty(m_SearchString) || PassedHidden || FailedHidden || NotRunHidden ||
|
||||
selectedCategoryMask != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public string[] CategoryFilter
|
||||
{
|
||||
get
|
||||
{
|
||||
var list = new List<string>();
|
||||
for (int i = 0; i < availableCategories.Length; i++)
|
||||
{
|
||||
if ((selectedCategoryMask & (1 << i)) != 0)
|
||||
{
|
||||
list.Add(availableCategories[i]);
|
||||
}
|
||||
}
|
||||
return list.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateCounters(List<TestRunnerResult> resultList)
|
||||
{
|
||||
m_PassedCount = m_FailedCount = m_NotRunCount = m_InconclusiveCount = m_SkippedCount = 0;
|
||||
foreach (var result in resultList)
|
||||
{
|
||||
if (result.isSuite)
|
||||
continue;
|
||||
switch (result.resultStatus)
|
||||
{
|
||||
case TestRunnerResult.ResultStatus.Passed:
|
||||
m_PassedCount++;
|
||||
break;
|
||||
case TestRunnerResult.ResultStatus.Failed:
|
||||
m_FailedCount++;
|
||||
break;
|
||||
case TestRunnerResult.ResultStatus.Inconclusive:
|
||||
m_InconclusiveCount++;
|
||||
break;
|
||||
case TestRunnerResult.ResultStatus.Skipped:
|
||||
m_SkippedCount++;
|
||||
break;
|
||||
case TestRunnerResult.ResultStatus.NotRun:
|
||||
default:
|
||||
m_NotRunCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var succeededTooltip = string.Format("Show tests that succeeded\n{0} succeeded", m_PassedCount);
|
||||
m_SucceededBtn = new GUIContent(PassedCount.ToString(), Icons.s_SuccessImg, succeededTooltip);
|
||||
var failedTooltip = string.Format("Show tests that failed\n{0} failed\n{1} inconclusive", m_FailedCount, m_InconclusiveCount);
|
||||
m_FailedBtn = new GUIContent(FailedCount.ToString(), Icons.s_FailImg, failedTooltip);
|
||||
var notRunTooltip = string.Format("Show tests that didn't run\n{0} didn't run\n{1} skipped or ignored", m_NotRunCount, m_SkippedCount);
|
||||
m_NotRunBtn = new GUIContent(NotRunCount.ToString(), Icons.s_UnknownImg, notRunTooltip);
|
||||
}
|
||||
|
||||
public void Draw()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
m_SearchString = EditorGUILayout.ToolbarSearchField(m_SearchString);
|
||||
if (EditorGUI.EndChangeCheck() && SearchStringChanged != null)
|
||||
{
|
||||
SearchStringChanged(m_SearchString);
|
||||
}
|
||||
|
||||
if (availableCategories != null && availableCategories.Any())
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
selectedCategoryMask = EditorGUILayout.MaskField(selectedCategoryMask, availableCategories, EditorStyles.toolbarDropDown, GUILayout.MaxWidth(150));
|
||||
if (EditorGUI.EndChangeCheck() && RebuildTestList != null)
|
||||
{
|
||||
RebuildTestList();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.Popup(0, new[] { "<No categories available>" }, EditorStyles.toolbarDropDown, GUILayout.MaxWidth(150));
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
if (m_SucceededBtn != null)
|
||||
{
|
||||
PassedHidden = !GUILayout.Toggle(!PassedHidden, m_SucceededBtn, EditorStyles.toolbarButton, GUILayout.MaxWidth(GetMaxWidth(PassedCount)));
|
||||
}
|
||||
if (m_FailedBtn != null)
|
||||
{
|
||||
FailedHidden = !GUILayout.Toggle(!FailedHidden, m_FailedBtn, EditorStyles.toolbarButton, GUILayout.MaxWidth(GetMaxWidth(FailedCount)));
|
||||
}
|
||||
if (m_NotRunBtn != null)
|
||||
{
|
||||
NotRunHidden = !GUILayout.Toggle(!NotRunHidden, m_NotRunBtn, EditorStyles.toolbarButton, GUILayout.MaxWidth(GetMaxWidth(NotRunCount)));
|
||||
}
|
||||
|
||||
if (EditorGUI.EndChangeCheck() && RebuildTestList != null)
|
||||
{
|
||||
RebuildTestList();
|
||||
}
|
||||
}
|
||||
|
||||
private static int GetMaxWidth(int count)
|
||||
{
|
||||
if (count < 10)
|
||||
return 33;
|
||||
return count < 100 ? 40 : 47;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
PassedHidden = false;
|
||||
FailedHidden = false;
|
||||
NotRunHidden = false;
|
||||
selectedCategoryMask = 0;
|
||||
m_SearchString = "";
|
||||
if (SearchStringChanged != null)
|
||||
{
|
||||
SearchStringChanged(m_SearchString);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 15f870c6975ad6449b5b52514b90dc2b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c5535d742ea2e4941850b421f9c70a1f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEditor.TestTools.TestRunner.Api;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using UnityEngine.TestTools.TestRunner.GUI;
|
||||
|
||||
namespace UnityEditor.TestTools.TestRunner.GUI
|
||||
{
|
||||
[Serializable]
|
||||
internal class EditModeTestListGUI : TestListGUI
|
||||
{
|
||||
public override TestMode TestMode
|
||||
{
|
||||
get { return TestMode.EditMode; }
|
||||
}
|
||||
|
||||
public override void RenderNoTestsInfo()
|
||||
{
|
||||
if (!TestListGUIHelper.SelectedFolderContainsTestAssembly())
|
||||
{
|
||||
var noTestText = "No tests to show";
|
||||
|
||||
if (!PlayerSettings.playModeTestRunnerEnabled)
|
||||
{
|
||||
const string testsArePulledFromCustomAssemblies =
|
||||
"EditMode tests can be in Editor only Assemblies, either in the editor special folder or Editor only Assembly Definitions with added Unity References \"Test Assemblies\".";
|
||||
noTestText += Environment.NewLine + testsArePulledFromCustomAssemblies;
|
||||
}
|
||||
|
||||
EditorGUILayout.HelpBox(noTestText, MessageType.Info);
|
||||
if (GUILayout.Button("Create EditMode Test Assembly Folder"))
|
||||
{
|
||||
TestListGUIHelper.AddFolderAndAsmDefForTesting(isEditorOnly: true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!TestListGUIHelper.CanAddEditModeTestScriptAndItWillCompile())
|
||||
{
|
||||
UnityEngine.GUI.enabled = false;
|
||||
EditorGUILayout.HelpBox("EditMode test scripts can only be created in editor test assemblies.", MessageType.Warning);
|
||||
}
|
||||
if (GUILayout.Button("Create Test Script in current folder"))
|
||||
{
|
||||
TestListGUIHelper.AddTest();
|
||||
}
|
||||
UnityEngine.GUI.enabled = true;
|
||||
}
|
||||
|
||||
public override void PrintHeadPanel()
|
||||
{
|
||||
base.PrintHeadPanel();
|
||||
DrawFilters();
|
||||
}
|
||||
|
||||
protected override void RunTests(TestRunnerFilter filter)
|
||||
{
|
||||
if (EditorUtility.scriptCompilationFailed)
|
||||
{
|
||||
Debug.LogError("Fix compilation issues before running tests");
|
||||
return;
|
||||
}
|
||||
|
||||
filter.ClearResults(newResultList.OfType<TestRunnerFilter.IClearableResult>().ToList());
|
||||
|
||||
RerunCallbackData.instance.runFilter = filter;
|
||||
RerunCallbackData.instance.testMode = TestMode.EditMode;
|
||||
|
||||
var testRunnerApi = ScriptableObject.CreateInstance<TestRunnerApi>();
|
||||
testRunnerApi.Execute(new ExecutionSettings()
|
||||
{
|
||||
filter = new Filter()
|
||||
{
|
||||
categoryNames = filter.categoryNames,
|
||||
groupNames = filter.groupNames,
|
||||
testMode = TestMode,
|
||||
testNames = filter.testNames
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public override TestPlatform TestPlatform { get { return TestPlatform.EditMode; } }
|
||||
protected override bool IsBusy()
|
||||
{
|
||||
return EditModeLauncher.IsRunning || EditorApplication.isCompiling || EditorApplication.isPlaying;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0336a32a79bfaed43a3fd2d88b91e974
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEditor.TestTools.TestRunner.Api;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.TestTools.TestRunner;
|
||||
using UnityEngine.TestTools.TestRunner.GUI;
|
||||
|
||||
namespace UnityEditor.TestTools.TestRunner.GUI
|
||||
{
|
||||
[Serializable]
|
||||
internal class PlayModeTestListGUI : TestListGUI
|
||||
{
|
||||
public override TestMode TestMode
|
||||
{
|
||||
get { return TestMode.PlayMode; }
|
||||
}
|
||||
public override void PrintHeadPanel()
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal(GUILayout.ExpandHeight(false));
|
||||
base.PrintHeadPanel();
|
||||
if (GUILayout.Button("Run all in player (" + EditorUserBuildSettings.activeBuildTarget + ")", EditorStyles.toolbarButton))
|
||||
{
|
||||
RunTestsInPlayer(null);
|
||||
}
|
||||
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 where you add Unity References \"Test Assemblies\"";
|
||||
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(TestRunnerFilter filter)
|
||||
{
|
||||
// Give user chance to save the changes to their currently open scene because we close it and load our own
|
||||
var cancelled = !EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
|
||||
if (cancelled)
|
||||
return;
|
||||
|
||||
filter.ClearResults(newResultList.OfType<TestRunnerFilter.IClearableResult>().ToList());
|
||||
|
||||
RerunCallbackData.instance.runFilter = filter;
|
||||
RerunCallbackData.instance.testMode = TestMode.PlayMode;
|
||||
|
||||
var testRunnerApi = ScriptableObject.CreateInstance<TestRunnerApi>();
|
||||
testRunnerApi.Execute(new ExecutionSettings()
|
||||
{
|
||||
filter = new Filter()
|
||||
{
|
||||
categoryNames = filter.categoryNames,
|
||||
groupNames = filter.groupNames,
|
||||
testMode = TestMode,
|
||||
testNames = filter.testNames
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void RunTestsInPlayer(TestRunnerFilter filter)
|
||||
{
|
||||
var settings = PlaymodeTestsControllerSettings.CreateRunnerSettings(filter);
|
||||
var testExecutor = new PlayerLauncher(settings, null, null);
|
||||
testExecutor.Run();
|
||||
GUIUtility.ExitGUI();
|
||||
}
|
||||
|
||||
public override TestPlatform TestPlatform { get { return TestPlatform.PlayMode; } }
|
||||
protected override bool IsBusy()
|
||||
{
|
||||
return PlaymodeLauncher.IsRunning || EditorApplication.isCompiling || EditorApplication.isPlaying;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3efd39f2cfb43a4c830d4fd5689900f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,449 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEditor.TestTools.TestRunner.Api;
|
||||
using UnityEngine;
|
||||
using UnityEngine.TestTools.TestRunner.GUI;
|
||||
using UnityEngine.TestTools;
|
||||
|
||||
namespace UnityEditor.TestTools.TestRunner.GUI
|
||||
{
|
||||
internal abstract class TestListGUI
|
||||
{
|
||||
private static readonly GUIContent s_GUIRunSelectedTests = EditorGUIUtility.TrTextContent("Run Selected", "Run selected test(s)");
|
||||
private static readonly GUIContent s_GUIRunAllTests = EditorGUIUtility.TrTextContent("Run All", "Run all tests");
|
||||
private static readonly GUIContent s_GUIRerunFailedTests = EditorGUIUtility.TrTextContent("Rerun Failed", "Rerun all failed tests");
|
||||
private static readonly GUIContent s_GUIRun = EditorGUIUtility.TrTextContent("Run");
|
||||
private static readonly GUIContent s_GUIRunUntilFailed = EditorGUIUtility.TrTextContent("Run Until Failed");
|
||||
private static readonly GUIContent s_GUIRun100Times = EditorGUIUtility.TrTextContent("Run 100 times");
|
||||
private static readonly GUIContent s_GUIOpenTest = EditorGUIUtility.TrTextContent("Open source code");
|
||||
private static readonly GUIContent s_GUIOpenErrorLine = EditorGUIUtility.TrTextContent("Open error line");
|
||||
|
||||
[SerializeField]
|
||||
protected TestRunnerWindow m_Window;
|
||||
[SerializeField]
|
||||
public List<TestRunnerResult> newResultList = new List<TestRunnerResult>();
|
||||
[SerializeField]
|
||||
private string m_ResultText;
|
||||
[SerializeField]
|
||||
private string m_ResultStacktrace;
|
||||
|
||||
private TreeViewController m_TestListTree;
|
||||
[SerializeField]
|
||||
internal TreeViewState m_TestListState;
|
||||
[SerializeField]
|
||||
internal TestRunnerUIFilter m_TestRunnerUIFilter = new TestRunnerUIFilter();
|
||||
|
||||
private Vector2 m_TestInfoScroll, m_TestListScroll;
|
||||
private string m_PreviousProjectPath;
|
||||
private List<TestRunnerResult> m_QueuedResults = new List<TestRunnerResult>();
|
||||
|
||||
protected TestListGUI()
|
||||
{
|
||||
MonoCecilHelper = new MonoCecilHelper();
|
||||
AssetsDatabaseHelper = new AssetsDatabaseHelper();
|
||||
|
||||
GuiHelper = new GuiHelper(MonoCecilHelper, AssetsDatabaseHelper);
|
||||
}
|
||||
|
||||
protected IMonoCecilHelper MonoCecilHelper { get; private set; }
|
||||
protected IAssetsDatabaseHelper AssetsDatabaseHelper { get; private set; }
|
||||
protected IGuiHelper GuiHelper { get; private set; }
|
||||
|
||||
public abstract TestMode TestMode { get; }
|
||||
|
||||
public virtual void PrintHeadPanel()
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
|
||||
using (new EditorGUI.DisabledScope(IsBusy()))
|
||||
{
|
||||
if (GUILayout.Button(s_GUIRunAllTests, EditorStyles.toolbarButton))
|
||||
{
|
||||
var filter = new TestRunnerFilter {categoryNames = m_TestRunnerUIFilter.CategoryFilter};
|
||||
RunTests(filter);
|
||||
GUIUtility.ExitGUI();
|
||||
}
|
||||
}
|
||||
using (new EditorGUI.DisabledScope(m_TestListTree == null || !m_TestListTree.HasSelection() || IsBusy()))
|
||||
{
|
||||
if (GUILayout.Button(s_GUIRunSelectedTests, EditorStyles.toolbarButton))
|
||||
{
|
||||
RunTests(GetSelectedTestsAsFilter(m_TestListTree.GetSelection()));
|
||||
GUIUtility.ExitGUI();
|
||||
}
|
||||
}
|
||||
using (new EditorGUI.DisabledScope(m_TestRunnerUIFilter.FailedCount == 0 || IsBusy()))
|
||||
{
|
||||
if (GUILayout.Button(s_GUIRerunFailedTests, EditorStyles.toolbarButton))
|
||||
{
|
||||
var failedTestnames = new List<string>();
|
||||
foreach (var result in newResultList)
|
||||
{
|
||||
if (result.isSuite)
|
||||
continue;
|
||||
if (result.resultStatus == TestRunnerResult.ResultStatus.Failed ||
|
||||
result.resultStatus == TestRunnerResult.ResultStatus.Inconclusive)
|
||||
failedTestnames.Add(result.fullName);
|
||||
}
|
||||
RunTests(new TestRunnerFilter() {testNames = failedTestnames.ToArray(), categoryNames = m_TestRunnerUIFilter.CategoryFilter});
|
||||
GUIUtility.ExitGUI();
|
||||
}
|
||||
}
|
||||
GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
protected void DrawFilters()
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
|
||||
m_TestRunnerUIFilter.Draw();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
public bool HasTreeData()
|
||||
{
|
||||
return m_TestListTree != null;
|
||||
}
|
||||
|
||||
public virtual void RenderTestList()
|
||||
{
|
||||
if (m_TestListTree == null)
|
||||
{
|
||||
GUILayout.Label("Loading...");
|
||||
return;
|
||||
}
|
||||
|
||||
m_TestListScroll = EditorGUILayout.BeginScrollView(m_TestListScroll,
|
||||
GUILayout.ExpandWidth(true),
|
||||
GUILayout.MaxWidth(2000));
|
||||
|
||||
if (m_TestListTree.data.root == null || m_TestListTree.data.rowCount == 0 || (!m_TestListTree.isSearching && !m_TestListTree.data.GetItem(0).hasChildren))
|
||||
{
|
||||
if (m_TestRunnerUIFilter.IsFiltering)
|
||||
{
|
||||
if (GUILayout.Button("Clear filters"))
|
||||
{
|
||||
m_TestRunnerUIFilter.Clear();
|
||||
m_TestListTree.ReloadData();
|
||||
m_Window.Repaint();
|
||||
}
|
||||
}
|
||||
RenderNoTestsInfo();
|
||||
}
|
||||
else
|
||||
{
|
||||
var treeRect = EditorGUILayout.GetControlRect(GUILayout.ExpandHeight(true), GUILayout.ExpandWidth(true));
|
||||
var treeViewKeyboardControlId = GUIUtility.GetControlID(FocusType.Keyboard);
|
||||
|
||||
m_TestListTree.OnGUI(treeRect, treeViewKeyboardControlId);
|
||||
}
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
public virtual void RenderNoTestsInfo()
|
||||
{
|
||||
EditorGUILayout.HelpBox("No tests to show", MessageType.Info);
|
||||
}
|
||||
|
||||
public void RenderDetails()
|
||||
{
|
||||
m_TestInfoScroll = EditorGUILayout.BeginScrollView(m_TestInfoScroll);
|
||||
var resultTextSize = TestRunnerWindow.Styles.info.CalcSize(new GUIContent(m_ResultText));
|
||||
EditorGUILayout.SelectableLabel(m_ResultText, TestRunnerWindow.Styles.info,
|
||||
GUILayout.ExpandHeight(true),
|
||||
GUILayout.ExpandWidth(true),
|
||||
GUILayout.MinWidth(resultTextSize.x),
|
||||
GUILayout.MinHeight(resultTextSize.y));
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
public void Reload()
|
||||
{
|
||||
if (m_TestListTree != null)
|
||||
{
|
||||
m_TestListTree.ReloadData();
|
||||
UpdateQueuedResults();
|
||||
}
|
||||
}
|
||||
|
||||
public void Repaint()
|
||||
{
|
||||
if (m_TestListTree == null || m_TestListTree.data.root == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_TestListTree.Repaint();
|
||||
if (m_TestListTree.data.rowCount == 0)
|
||||
m_TestListTree.SetSelection(new int[0], false);
|
||||
TestSelectionCallback(m_TestListState.selectedIDs.ToArray());
|
||||
}
|
||||
|
||||
public void Init(TestRunnerWindow window, ITestAdaptor rootTest)
|
||||
{
|
||||
if (m_Window == null)
|
||||
{
|
||||
m_Window = window;
|
||||
}
|
||||
|
||||
if (m_TestListTree == null)
|
||||
{
|
||||
if (m_TestListState == null)
|
||||
{
|
||||
m_TestListState = new TreeViewState();
|
||||
}
|
||||
if (m_TestListTree == null)
|
||||
m_TestListTree = new TreeViewController(m_Window, m_TestListState);
|
||||
|
||||
m_TestListTree.deselectOnUnhandledMouseDown = false;
|
||||
|
||||
m_TestListTree.selectionChangedCallback += TestSelectionCallback;
|
||||
m_TestListTree.itemDoubleClickedCallback += TestDoubleClickCallback;
|
||||
m_TestListTree.contextClickItemCallback += TestContextClickCallback;
|
||||
|
||||
var testListTreeViewDataSource = new TestListTreeViewDataSource(m_TestListTree, this, rootTest);
|
||||
|
||||
if (!newResultList.Any())
|
||||
testListTreeViewDataSource.ExpandTreeOnCreation();
|
||||
|
||||
m_TestListTree.Init(new Rect(),
|
||||
testListTreeViewDataSource,
|
||||
new TestListTreeViewGUI(m_TestListTree),
|
||||
null);
|
||||
}
|
||||
|
||||
EditorApplication.update += RepaintIfProjectPathChanged;
|
||||
|
||||
m_TestRunnerUIFilter.UpdateCounters(newResultList);
|
||||
m_TestRunnerUIFilter.RebuildTestList = () => m_TestListTree.ReloadData();
|
||||
m_TestRunnerUIFilter.SearchStringChanged = s => m_TestListTree.searchString = s;
|
||||
}
|
||||
|
||||
public void UpdateResult(TestRunnerResult result)
|
||||
{
|
||||
if (!HasTreeData())
|
||||
{
|
||||
m_QueuedResults.Add(result);
|
||||
return;
|
||||
}
|
||||
|
||||
if (newResultList.All(x => x.uniqueId != result.uniqueId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var testRunnerResult = newResultList.FirstOrDefault(x => x.uniqueId == result.uniqueId);
|
||||
if (testRunnerResult != null)
|
||||
{
|
||||
testRunnerResult.Update(result);
|
||||
}
|
||||
|
||||
Repaint();
|
||||
m_Window.Repaint();
|
||||
}
|
||||
|
||||
private void UpdateQueuedResults()
|
||||
{
|
||||
foreach (var testRunnerResult in m_QueuedResults)
|
||||
{
|
||||
var existingResult = newResultList.FirstOrDefault(x => x.uniqueId == testRunnerResult.uniqueId);
|
||||
if (existingResult != null)
|
||||
{
|
||||
existingResult.Update(testRunnerResult);
|
||||
}
|
||||
}
|
||||
m_QueuedResults.Clear();
|
||||
TestSelectionCallback(m_TestListState.selectedIDs.ToArray());
|
||||
Repaint();
|
||||
m_Window.Repaint();
|
||||
}
|
||||
|
||||
internal void TestSelectionCallback(int[] selected)
|
||||
{
|
||||
if (m_TestListTree != null && selected.Length == 1)
|
||||
{
|
||||
if (m_TestListTree != null)
|
||||
{
|
||||
var node = m_TestListTree.FindItem(selected[0]);
|
||||
if (node is TestTreeViewItem)
|
||||
{
|
||||
var test = node as TestTreeViewItem;
|
||||
m_ResultText = test.GetResultText();
|
||||
m_ResultStacktrace = test.result.stacktrace;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (selected.Length == 0)
|
||||
{
|
||||
m_ResultText = "";
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void TestDoubleClickCallback(int id)
|
||||
{
|
||||
if (IsBusy())
|
||||
return;
|
||||
|
||||
RunTests(GetSelectedTestsAsFilter(new List<int> { id }));
|
||||
GUIUtility.ExitGUI();
|
||||
}
|
||||
|
||||
protected virtual void RunTests(TestRunnerFilter filter)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected virtual void TestContextClickCallback(int id)
|
||||
{
|
||||
if (id == 0)
|
||||
return;
|
||||
|
||||
var m = new GenericMenu();
|
||||
var testFilter = GetSelectedTestsAsFilter(m_TestListState.selectedIDs);
|
||||
var multilineSelection = m_TestListState.selectedIDs.Count > 1;
|
||||
|
||||
if (!multilineSelection)
|
||||
{
|
||||
var testNode = GetSelectedTest();
|
||||
var isNotSuite = !testNode.IsGroupNode;
|
||||
if (isNotSuite)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(m_ResultStacktrace))
|
||||
{
|
||||
m.AddItem(s_GUIOpenErrorLine,
|
||||
false,
|
||||
data =>
|
||||
{
|
||||
if (!GuiHelper.OpenScriptInExternalEditor(m_ResultStacktrace))
|
||||
{
|
||||
GuiHelper.OpenScriptInExternalEditor(testNode.type, testNode.method);
|
||||
}
|
||||
},
|
||||
"");
|
||||
}
|
||||
|
||||
m.AddItem(s_GUIOpenTest,
|
||||
false,
|
||||
data => GuiHelper.OpenScriptInExternalEditor(testNode.type, testNode.method),
|
||||
"");
|
||||
m.AddSeparator("");
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsBusy())
|
||||
{
|
||||
m.AddItem(multilineSelection ? s_GUIRunSelectedTests : s_GUIRun,
|
||||
false,
|
||||
data => RunTests(testFilter),
|
||||
"");
|
||||
|
||||
if (EditorPrefs.GetBool("DeveloperMode", false))
|
||||
{
|
||||
m.AddItem(multilineSelection ? s_GUIRunSelectedTests : s_GUIRunUntilFailed,
|
||||
false,
|
||||
data =>
|
||||
{
|
||||
testFilter.testRepetitions = int.MaxValue;
|
||||
RunTests(testFilter);
|
||||
},
|
||||
"");
|
||||
|
||||
m.AddItem(multilineSelection ? s_GUIRunSelectedTests : s_GUIRun100Times,
|
||||
false,
|
||||
data =>
|
||||
{
|
||||
testFilter.testRepetitions = 100;
|
||||
RunTests(testFilter);
|
||||
},
|
||||
"");
|
||||
}
|
||||
}
|
||||
else
|
||||
m.AddDisabledItem(multilineSelection ? s_GUIRunSelectedTests : s_GUIRun, false);
|
||||
|
||||
m.ShowAsContext();
|
||||
}
|
||||
|
||||
private TestRunnerFilter GetSelectedTestsAsFilter(IEnumerable<int> selectedIDs)
|
||||
{
|
||||
var namesToRun = new List<string>();
|
||||
var exactNamesToRun = new List<string>();
|
||||
var assembliesToRun = new List<string>();
|
||||
foreach (var lineId in selectedIDs)
|
||||
{
|
||||
var line = m_TestListTree.FindItem(lineId);
|
||||
if (line is TestTreeViewItem)
|
||||
{
|
||||
var testLine = line as TestTreeViewItem;
|
||||
if (testLine.IsGroupNode && !testLine.FullName.Contains("+"))
|
||||
{
|
||||
if (testLine.parent != null && testLine.parent.displayName == "Invisible Root Item")
|
||||
{
|
||||
//Root node selected. Use an empty TestRunnerFilter to run every test
|
||||
namesToRun.Clear();
|
||||
exactNamesToRun.Clear();
|
||||
assembliesToRun.Clear();
|
||||
break;
|
||||
}
|
||||
|
||||
if (testLine.FullName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
|
||||
assembliesToRun.Add(TestRunnerFilter.AssemblyNameFromPath(testLine.FullName));
|
||||
else
|
||||
namesToRun.Add(string.Format("^{0}$", testLine.FullName));
|
||||
}
|
||||
else
|
||||
exactNamesToRun.Add(testLine.FullName);
|
||||
}
|
||||
}
|
||||
|
||||
var filter = new TestRunnerFilter
|
||||
{
|
||||
assemblyNames = assembliesToRun.ToArray(),
|
||||
groupNames = namesToRun.ToArray(),
|
||||
testNames = exactNamesToRun.ToArray(),
|
||||
categoryNames = m_TestRunnerUIFilter.CategoryFilter
|
||||
};
|
||||
return filter;
|
||||
}
|
||||
|
||||
private TestTreeViewItem GetSelectedTest()
|
||||
{
|
||||
foreach (var lineId in m_TestListState.selectedIDs)
|
||||
{
|
||||
var line = m_TestListTree.FindItem(lineId);
|
||||
if (line is TestTreeViewItem)
|
||||
{
|
||||
return line as TestTreeViewItem;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract TestPlatform TestPlatform { get; }
|
||||
|
||||
public void RebuildUIFilter()
|
||||
{
|
||||
m_TestRunnerUIFilter.UpdateCounters(newResultList);
|
||||
if (m_TestRunnerUIFilter.IsFiltering)
|
||||
{
|
||||
m_TestListTree.ReloadData();
|
||||
}
|
||||
}
|
||||
|
||||
public void RepaintIfProjectPathChanged()
|
||||
{
|
||||
var path = TestListGUIHelper.GetActiveFolderPath();
|
||||
if (path != m_PreviousProjectPath)
|
||||
{
|
||||
m_PreviousProjectPath = path;
|
||||
TestRunnerWindow.s_Instance.Repaint();
|
||||
}
|
||||
|
||||
EditorApplication.update -= RepaintIfProjectPathChanged;
|
||||
}
|
||||
|
||||
protected abstract bool IsBusy();
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b8abb41ceb6f62c45a00197ae59224c1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user