initial project folder

This commit is contained in:
ToAallonranta
2020-01-29 10:05:38 +02:00
parent e6d2f9b9ca
commit 837543ed9a
3804 changed files with 100819 additions and 0 deletions

View File

@ -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);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 740b3785866edda4b8d1e1a05570a5f8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d0138170d24533e47b8e6c250c6d7fbc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,7 @@
namespace UnityEditor.TestTools.TestRunner.GUI
{
internal interface IAssetsDatabaseHelper
{
void OpenAssetInItsDefaultExternalEditor(string assetPath, int line);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 208e46d59ff6e304db0318377d20f5a1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fd57cf917f61bbb42b8f030436426ddd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 07ea0326ed848fb4489187cb58f96113
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 87357ff0dec4ef348a295235835c6ee4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 95a2914724952ef40bb590d0607fc878
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 046c3854296c5ec48bac50da6ca248ec
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e17c88b021c2a4c409b3f15b0d80ac62
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 97a05971510726f438153cd4987526fb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 68cb547af0187634aad591a09c01cd5b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 27769e9b00b038d47aefe306a4d20bec
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ce87c287371edde43a4b5fcfdee7b9ef
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,11 @@
using UnityEditor.IMGUI.Controls;
namespace UnityEditor.TestTools.TestRunner.GUI
{
internal class TestListTreeViewGUI : TreeViewGUI
{
public TestListTreeViewGUI(TreeViewController testListTree) : base(testListTree)
{
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 52c907c81459f324497af504b84fd557
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ce567ddbf30368344bc7b80e20cac36e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a04a45bbed9e1714f9902fc9443669b9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 15f870c6975ad6449b5b52514b90dc2b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c5535d742ea2e4941850b421f9c70a1f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0336a32a79bfaed43a3fd2d88b91e974
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c3efd39f2cfb43a4c830d4fd5689900f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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();
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b8abb41ceb6f62c45a00197ae59224c1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: