Commit af571a61 authored by BlackAngle233's avatar BlackAngle233
Browse files

212

parent 1d9b5391
using System; using System;
using System.IO; using System.IO;
using System.Xml; using System.Xml;
using NUnit.Framework.Interfaces; using NUnit.Framework.Interfaces;
using UnityEditor.TestTools.TestRunner.Api; using UnityEditor.TestTools.TestRunner.Api;
using UnityEngine; using UnityEngine;
namespace UnityEditor.TestTools.TestRunner.CommandLineTest namespace UnityEditor.TestTools.TestRunner.CommandLineTest
{ {
internal class ResultsWriter internal class ResultsWriter
{ {
private const string k_nUnitVersion = "3.5.0.0"; private const string k_nUnitVersion = "3.5.0.0";
private const string k_TestRunNode = "test-run"; private const string k_TestRunNode = "test-run";
private const string k_Id = "id"; private const string k_Id = "id";
private const string k_Testcasecount = "testcasecount"; private const string k_Testcasecount = "testcasecount";
private const string k_Result = "result"; private const string k_Result = "result";
private const string k_Total = "total"; private const string k_Total = "total";
private const string k_Passed = "passed"; private const string k_Passed = "passed";
private const string k_Failed = "failed"; private const string k_Failed = "failed";
private const string k_Inconclusive = "inconclusive"; private const string k_Inconclusive = "inconclusive";
private const string k_Skipped = "skipped"; private const string k_Skipped = "skipped";
private const string k_Asserts = "asserts"; private const string k_Asserts = "asserts";
private const string k_EngineVersion = "engine-version"; private const string k_EngineVersion = "engine-version";
private const string k_ClrVersion = "clr-version"; private const string k_ClrVersion = "clr-version";
private const string k_StartTime = "start-time"; private const string k_StartTime = "start-time";
private const string k_EndTime = "end-time"; private const string k_EndTime = "end-time";
private const string k_Duration = "duration"; private const string k_Duration = "duration";
private const string k_TimeFormat = "u"; private const string k_TimeFormat = "u";
public void WriteResultToFile(ITestResultAdaptor result, string filePath) public void WriteResultToFile(ITestResultAdaptor result, string filePath)
{ {
Debug.LogFormat(LogType.Log, LogOption.NoStacktrace, null, "Saving results to: {0}", filePath); Debug.LogFormat(LogType.Log, LogOption.NoStacktrace, null, "Saving results to: {0}", filePath);
try try
{ {
if (!Directory.Exists(filePath)) if (!Directory.Exists(filePath))
{ {
CreateDirectory(filePath); CreateDirectory(filePath);
} }
using (var fileStream = File.CreateText(filePath)) using (var fileStream = File.CreateText(filePath))
{ {
WriteResultToStream(result, fileStream); WriteResultToStream(result, fileStream);
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Debug.LogError("Saving result file failed."); Debug.LogError("Saving result file failed.");
Debug.LogException(ex); Debug.LogException(ex);
} }
} }
void CreateDirectory(string filePath) void CreateDirectory(string filePath)
{ {
var driectoryPath = Path.GetDirectoryName(filePath); var driectoryPath = Path.GetDirectoryName(filePath);
if (!String.IsNullOrEmpty(driectoryPath)) if (!String.IsNullOrEmpty(driectoryPath))
{ {
Directory.CreateDirectory(driectoryPath); Directory.CreateDirectory(driectoryPath);
} }
} }
public void WriteResultToStream(ITestResultAdaptor result, StreamWriter streamWriter, XmlWriterSettings settings = null) public void WriteResultToStream(ITestResultAdaptor result, StreamWriter streamWriter, XmlWriterSettings settings = null)
{ {
settings = settings ?? new XmlWriterSettings(); settings = settings ?? new XmlWriterSettings();
settings.Indent = true; settings.Indent = true;
settings.NewLineOnAttributes = false; settings.NewLineOnAttributes = false;
using (var xmlWriter = XmlWriter.Create(streamWriter, settings)) using (var xmlWriter = XmlWriter.Create(streamWriter, settings))
{ {
WriteResultsToXml(result, xmlWriter); WriteResultsToXml(result, xmlWriter);
} }
} }
void WriteResultsToXml(ITestResultAdaptor result, XmlWriter xmlWriter) void WriteResultsToXml(ITestResultAdaptor result, XmlWriter xmlWriter)
{ {
// XML format as specified at https://github.com/nunit/docs/wiki/Test-Result-XML-Format // XML format as specified at https://github.com/nunit/docs/wiki/Test-Result-XML-Format
var testRunNode = new TNode(k_TestRunNode); var testRunNode = new TNode(k_TestRunNode);
testRunNode.AddAttribute(k_Id, "2"); testRunNode.AddAttribute(k_Id, "2");
testRunNode.AddAttribute(k_Testcasecount, (result.PassCount + result.FailCount + result.SkipCount + result.InconclusiveCount).ToString()); testRunNode.AddAttribute(k_Testcasecount, (result.PassCount + result.FailCount + result.SkipCount + result.InconclusiveCount).ToString());
testRunNode.AddAttribute(k_Result, result.ResultState.ToString()); testRunNode.AddAttribute(k_Result, result.ResultState.ToString());
testRunNode.AddAttribute(k_Total, (result.PassCount + result.FailCount + result.SkipCount + result.InconclusiveCount).ToString()); testRunNode.AddAttribute(k_Total, (result.PassCount + result.FailCount + result.SkipCount + result.InconclusiveCount).ToString());
testRunNode.AddAttribute(k_Passed, result.PassCount.ToString()); testRunNode.AddAttribute(k_Passed, result.PassCount.ToString());
testRunNode.AddAttribute(k_Failed, result.FailCount.ToString()); testRunNode.AddAttribute(k_Failed, result.FailCount.ToString());
testRunNode.AddAttribute(k_Inconclusive, result.InconclusiveCount.ToString()); testRunNode.AddAttribute(k_Inconclusive, result.InconclusiveCount.ToString());
testRunNode.AddAttribute(k_Skipped, result.SkipCount.ToString()); testRunNode.AddAttribute(k_Skipped, result.SkipCount.ToString());
testRunNode.AddAttribute(k_Asserts, result.AssertCount.ToString()); testRunNode.AddAttribute(k_Asserts, result.AssertCount.ToString());
testRunNode.AddAttribute(k_EngineVersion, k_nUnitVersion); testRunNode.AddAttribute(k_EngineVersion, k_nUnitVersion);
testRunNode.AddAttribute(k_ClrVersion, Environment.Version.ToString()); testRunNode.AddAttribute(k_ClrVersion, Environment.Version.ToString());
testRunNode.AddAttribute(k_StartTime, result.StartTime.ToString(k_TimeFormat)); testRunNode.AddAttribute(k_StartTime, result.StartTime.ToString(k_TimeFormat));
testRunNode.AddAttribute(k_EndTime, result.EndTime.ToString(k_TimeFormat)); testRunNode.AddAttribute(k_EndTime, result.EndTime.ToString(k_TimeFormat));
testRunNode.AddAttribute(k_Duration, result.Duration.ToString()); testRunNode.AddAttribute(k_Duration, result.Duration.ToString());
var resultNode = result.ToXml(); var resultNode = result.ToXml();
testRunNode.ChildNodes.Add(resultNode); testRunNode.ChildNodes.Add(resultNode);
testRunNode.WriteTo(xmlWriter); testRunNode.WriteTo(xmlWriter);
} }
} }
} }
fileFormatVersion: 2 fileFormatVersion: 2
guid: 29d603e0a726a9043b3503112271844a guid: 29d603e0a726a9043b3503112271844a
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
defaultReferences: [] defaultReferences: []
executionOrder: 0 executionOrder: 0
icon: {instanceID: 0} icon: {instanceID: 0}
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:
namespace UnityEditor.TestTools.TestRunner.CommandLineTest namespace UnityEditor.TestTools.TestRunner.CommandLineTest
{ {
internal class RunData : ScriptableSingleton<RunData> internal class RunData : ScriptableSingleton<RunData>
{ {
public bool isRunning; public bool isRunning;
public ExecutionSettings executionSettings; public ExecutionSettings executionSettings;
} }
} }
fileFormatVersion: 2 fileFormatVersion: 2
guid: 3f8c1075884df0249b80e23a0598f9c1 guid: 3f8c1075884df0249b80e23a0598f9c1
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
defaultReferences: [] defaultReferences: []
executionOrder: 0 executionOrder: 0
icon: {instanceID: 0} icon: {instanceID: 0}
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:
using UnityEditor.TestTools.TestRunner.Api; using UnityEditor.TestTools.TestRunner.Api;
namespace UnityEditor.TestTools.TestRunner.CommandLineTest namespace UnityEditor.TestTools.TestRunner.CommandLineTest
{ {
internal class RunSettings : ITestRunSettings internal class RunSettings : ITestRunSettings
{ {
private ITestSettings m_TestSettings; private ITestSettings m_TestSettings;
public RunSettings(ITestSettings testSettings) public RunSettings(ITestSettings testSettings)
{ {
this.m_TestSettings = testSettings; this.m_TestSettings = testSettings;
} }
public void Apply() public void Apply()
{ {
if (m_TestSettings != null) if (m_TestSettings != null)
{ {
m_TestSettings.SetupProjectParameters(); m_TestSettings.SetupProjectParameters();
} }
} }
public void Dispose() public void Dispose()
{ {
if (m_TestSettings != null) if (m_TestSettings != null)
{ {
m_TestSettings.Dispose(); m_TestSettings.Dispose();
} }
} }
} }
} }
fileFormatVersion: 2 fileFormatVersion: 2
guid: 59d3f5586b341a74c84c8f72144a4568 guid: 59d3f5586b341a74c84c8f72144a4568
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
defaultReferences: [] defaultReferences: []
executionOrder: 0 executionOrder: 0
icon: {instanceID: 0} icon: {instanceID: 0}
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:
using System; using System;
using System.IO; using System.IO;
using UnityEditor.TestRunner.CommandLineParser; using UnityEditor.TestRunner.CommandLineParser;
using UnityEditor.TestTools.TestRunner.Api; using UnityEditor.TestTools.TestRunner.Api;
using UnityEngine.TestTools.TestRunner.GUI; using UnityEngine.TestTools.TestRunner.GUI;
namespace UnityEditor.TestTools.TestRunner.CommandLineTest namespace UnityEditor.TestTools.TestRunner.CommandLineTest
{ {
internal class SettingsBuilder : ISettingsBuilder internal class SettingsBuilder : ISettingsBuilder
{ {
private ITestSettingsDeserializer m_TestSettingsDeserializer; private ITestSettingsDeserializer m_TestSettingsDeserializer;
private Action<string> m_LogAction; private Action<string> m_LogAction;
private Action<string> m_LogWarningAction; private Action<string> m_LogWarningAction;
private Func<string, bool> m_FileExistsCheck; private Func<string, bool> m_FileExistsCheck;
private Func<bool> m_ScriptCompilationFailedCheck; private Func<bool> m_ScriptCompilationFailedCheck;
public SettingsBuilder(ITestSettingsDeserializer testSettingsDeserializer, Action<string> logAction, Action<string> logWarningAction, Func<string, bool> fileExistsCheck, Func<bool> scriptCompilationFailedCheck) public SettingsBuilder(ITestSettingsDeserializer testSettingsDeserializer, Action<string> logAction, Action<string> logWarningAction, Func<string, bool> fileExistsCheck, Func<bool> scriptCompilationFailedCheck)
{ {
m_LogAction = logAction; m_LogAction = logAction;
m_LogWarningAction = logWarningAction; m_LogWarningAction = logWarningAction;
m_FileExistsCheck = fileExistsCheck; m_FileExistsCheck = fileExistsCheck;
m_ScriptCompilationFailedCheck = scriptCompilationFailedCheck; m_ScriptCompilationFailedCheck = scriptCompilationFailedCheck;
m_TestSettingsDeserializer = testSettingsDeserializer; m_TestSettingsDeserializer = testSettingsDeserializer;
} }
public Api.ExecutionSettings BuildApiExecutionSettings(string[] commandLineArgs) public Api.ExecutionSettings BuildApiExecutionSettings(string[] commandLineArgs)
{ {
var quit = false; var quit = false;
string testPlatform = TestMode.EditMode.ToString(); string testPlatform = TestMode.EditMode.ToString();
string[] testFilters = null; string[] testFilters = null;
string[] testCategories = null; string[] testCategories = null;
string testSettingsFilePath = null; string testSettingsFilePath = null;
int testRepetitions = 1; int testRepetitions = 1;
int? playerHeartbeatTimeout = null; int? playerHeartbeatTimeout = null;
bool runSynchronously = false; bool runSynchronously = false;
string[] testAssemblyNames = null; string[] testAssemblyNames = null;
var optionSet = new CommandLineOptionSet( var optionSet = new CommandLineOptionSet(
new CommandLineOption("quit", () => { quit = true; }), new CommandLineOption("quit", () => { quit = true; }),
new CommandLineOption("testPlatform", platform => { testPlatform = platform; }), new CommandLineOption("testPlatform", platform => { testPlatform = platform; }),
new CommandLineOption("editorTestsFilter", filters => { testFilters = filters; }), new CommandLineOption("editorTestsFilter", filters => { testFilters = filters; }),
new CommandLineOption("testFilter", filters => { testFilters = filters; }), new CommandLineOption("testFilter", filters => { testFilters = filters; }),
new CommandLineOption("editorTestsCategories", catagories => { testCategories = catagories; }), new CommandLineOption("editorTestsCategories", catagories => { testCategories = catagories; }),
new CommandLineOption("testCategory", catagories => { testCategories = catagories; }), new CommandLineOption("testCategory", catagories => { testCategories = catagories; }),
new CommandLineOption("testSettingsFile", settingsFilePath => { testSettingsFilePath = settingsFilePath; }), new CommandLineOption("testSettingsFile", settingsFilePath => { testSettingsFilePath = settingsFilePath; }),
new CommandLineOption("testRepetitions", reps => { testRepetitions = int.Parse(reps); }), new CommandLineOption("testRepetitions", reps => { testRepetitions = int.Parse(reps); }),
new CommandLineOption("playerHeartbeatTimeout", timeout => { playerHeartbeatTimeout = int.Parse(timeout); }), new CommandLineOption("playerHeartbeatTimeout", timeout => { playerHeartbeatTimeout = int.Parse(timeout); }),
new CommandLineOption("runSynchronously", () => { runSynchronously = true; }), new CommandLineOption("runSynchronously", () => { runSynchronously = true; }),
new CommandLineOption("assemblyNames", assemblyNames => { testAssemblyNames = assemblyNames; }) new CommandLineOption("assemblyNames", assemblyNames => { testAssemblyNames = assemblyNames; })
); );
optionSet.Parse(commandLineArgs); optionSet.Parse(commandLineArgs);
DisplayQuitWarningIfQuitIsGiven(quit); DisplayQuitWarningIfQuitIsGiven(quit);
CheckForScriptCompilationErrors(); CheckForScriptCompilationErrors();
LogParametersForRun(testPlatform, testFilters, testCategories, testSettingsFilePath); LogParametersForRun(testPlatform, testFilters, testCategories, testSettingsFilePath);
var testSettings = GetTestSettings(testSettingsFilePath); var testSettings = GetTestSettings(testSettingsFilePath);
var filter = new Filter() var filter = new Filter()
{ {
groupNames = testFilters, groupNames = testFilters,
categoryNames = testCategories, categoryNames = testCategories,
assemblyNames = testAssemblyNames assemblyNames = testAssemblyNames
}; };
var buildTarget = SetFilterAndGetBuildTarget(testPlatform, filter); var buildTarget = SetFilterAndGetBuildTarget(testPlatform, filter);
RerunCallbackData.instance.runFilters = new []{new TestRunnerFilter() RerunCallbackData.instance.runFilters = new []{new TestRunnerFilter()
{ {
categoryNames = filter.categoryNames, categoryNames = filter.categoryNames,
groupNames = filter.groupNames, groupNames = filter.groupNames,
testRepetitions = testRepetitions testRepetitions = testRepetitions
}}; }};
RerunCallbackData.instance.testMode = filter.testMode; RerunCallbackData.instance.testMode = filter.testMode;
var settings = new Api.ExecutionSettings() var settings = new Api.ExecutionSettings()
{ {
filters = new []{filter}, filters = new []{filter},
overloadTestRunSettings = new RunSettings(testSettings), overloadTestRunSettings = new RunSettings(testSettings),
targetPlatform = buildTarget, targetPlatform = buildTarget,
runSynchronously = runSynchronously runSynchronously = runSynchronously
}; };
if (playerHeartbeatTimeout != null) if (playerHeartbeatTimeout != null)
{ {
settings.playerHeartbeatTimeout = playerHeartbeatTimeout.Value; settings.playerHeartbeatTimeout = playerHeartbeatTimeout.Value;
} }
return settings; return settings;
} }
public ExecutionSettings BuildExecutionSettings(string[] commandLineArgs) public ExecutionSettings BuildExecutionSettings(string[] commandLineArgs)
{ {
string resultFilePath = null; string resultFilePath = null;
string deviceLogsDirectory = null; string deviceLogsDirectory = null;
var optionSet = new CommandLineOptionSet( var optionSet = new CommandLineOptionSet(
new CommandLineOption("editorTestsResultFile", filePath => { resultFilePath = filePath; }), new CommandLineOption("editorTestsResultFile", filePath => { resultFilePath = filePath; }),
new CommandLineOption("testResults", filePath => { resultFilePath = filePath; }), new CommandLineOption("testResults", filePath => { resultFilePath = filePath; }),
new CommandLineOption("deviceLogs", dirPath => { deviceLogsDirectory = dirPath; }) new CommandLineOption("deviceLogs", dirPath => { deviceLogsDirectory = dirPath; })
); );
optionSet.Parse(commandLineArgs); optionSet.Parse(commandLineArgs);
return new ExecutionSettings() return new ExecutionSettings()
{ {
TestResultsFile = resultFilePath, TestResultsFile = resultFilePath,
DeviceLogsDirectory = deviceLogsDirectory DeviceLogsDirectory = deviceLogsDirectory
}; };
} }
void DisplayQuitWarningIfQuitIsGiven(bool quitIsGiven) void DisplayQuitWarningIfQuitIsGiven(bool quitIsGiven)
{ {
if (quitIsGiven) if (quitIsGiven)
{ {
m_LogWarningAction("Running tests from command line arguments will not work when \"quit\" is specified."); m_LogWarningAction("Running tests from command line arguments will not work when \"quit\" is specified.");
} }
} }
void CheckForScriptCompilationErrors() void CheckForScriptCompilationErrors()
{ {
if (m_ScriptCompilationFailedCheck()) if (m_ScriptCompilationFailedCheck())
{ {
throw new SetupException(SetupException.ExceptionType.ScriptCompilationFailed); throw new SetupException(SetupException.ExceptionType.ScriptCompilationFailed);
} }
} }
void LogParametersForRun(string testPlatform, string[] testFilters, string[] testCategories, string testSettingsFilePath) void LogParametersForRun(string testPlatform, string[] testFilters, string[] testCategories, string testSettingsFilePath)
{ {
m_LogAction("Running tests for " + testPlatform); m_LogAction("Running tests for " + testPlatform);
if (testFilters != null && testFilters.Length > 0) if (testFilters != null && testFilters.Length > 0)
{ {
m_LogAction("With test filter: " + string.Join(", ", testFilters)); m_LogAction("With test filter: " + string.Join(", ", testFilters));
} }
if (testCategories != null && testCategories.Length > 0) if (testCategories != null && testCategories.Length > 0)
{ {
m_LogAction("With test categories: " + string.Join(", ", testCategories)); m_LogAction("With test categories: " + string.Join(", ", testCategories));
} }
if (!string.IsNullOrEmpty(testSettingsFilePath)) if (!string.IsNullOrEmpty(testSettingsFilePath))
{ {
m_LogAction("With test settings file: " + testSettingsFilePath); m_LogAction("With test settings file: " + testSettingsFilePath);
} }
} }
ITestSettings GetTestSettings(string testSettingsFilePath) ITestSettings GetTestSettings(string testSettingsFilePath)
{ {
ITestSettings testSettings = null; ITestSettings testSettings = null;
if (!string.IsNullOrEmpty(testSettingsFilePath)) if (!string.IsNullOrEmpty(testSettingsFilePath))
{ {
if (!m_FileExistsCheck(testSettingsFilePath)) if (!m_FileExistsCheck(testSettingsFilePath))
{ {
throw new SetupException(SetupException.ExceptionType.TestSettingsFileNotFound, testSettingsFilePath); throw new SetupException(SetupException.ExceptionType.TestSettingsFileNotFound, testSettingsFilePath);
} }
testSettings = m_TestSettingsDeserializer.GetSettingsFromJsonFile(testSettingsFilePath); testSettings = m_TestSettingsDeserializer.GetSettingsFromJsonFile(testSettingsFilePath);
} }
return testSettings; return testSettings;
} }
static BuildTarget? SetFilterAndGetBuildTarget(string testPlatform, Filter filter) static BuildTarget? SetFilterAndGetBuildTarget(string testPlatform, Filter filter)
{ {
BuildTarget? buildTarget = null; BuildTarget? buildTarget = null;
if (testPlatform.ToLower() == "editmode") if (testPlatform.ToLower() == "editmode")
{ {
filter.testMode = TestMode.EditMode; filter.testMode = TestMode.EditMode;
} }
else if (testPlatform.ToLower() == "playmode") else if (testPlatform.ToLower() == "playmode")
{ {
filter.testMode = TestMode.PlayMode; filter.testMode = TestMode.PlayMode;
} }
else else
{ {
try try
{ {
buildTarget = (BuildTarget)Enum.Parse(typeof(BuildTarget), testPlatform, true); buildTarget = (BuildTarget)Enum.Parse(typeof(BuildTarget), testPlatform, true);
filter.testMode = TestMode.PlayMode; filter.testMode = TestMode.PlayMode;
} }
catch (ArgumentException) catch (ArgumentException)
{ {
throw new SetupException(SetupException.ExceptionType.PlatformNotFound, testPlatform); throw new SetupException(SetupException.ExceptionType.PlatformNotFound, testPlatform);
} }
} }
return buildTarget; return buildTarget;
} }
} }
} }
fileFormatVersion: 2 fileFormatVersion: 2
guid: b7468a027a77337478e133b40b42b4f9 guid: b7468a027a77337478e133b40b42b4f9
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
defaultReferences: [] defaultReferences: []
executionOrder: 0 executionOrder: 0
icon: {instanceID: 0} icon: {instanceID: 0}
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:
using System; using System;
namespace UnityEditor.TestTools.TestRunner.CommandLineTest namespace UnityEditor.TestTools.TestRunner.CommandLineTest
{ {
internal class SetupException : Exception internal class SetupException : Exception
{ {
public ExceptionType Type { get; } public ExceptionType Type { get; }
public object[] Details { get; } public object[] Details { get; }
public SetupException(ExceptionType type, params object[] details) public SetupException(ExceptionType type, params object[] details)
{ {
Type = type; Type = type;
Details = details; Details = details;
} }
public enum ExceptionType public enum ExceptionType
{ {
ScriptCompilationFailed, ScriptCompilationFailed,
PlatformNotFound, PlatformNotFound,
TestSettingsFileNotFound, TestSettingsFileNotFound,
} }
} }
} }
fileFormatVersion: 2 fileFormatVersion: 2
guid: 63572993f2104574099a48392460b211 guid: 63572993f2104574099a48392460b211
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
defaultReferences: [] defaultReferences: []
executionOrder: 0 executionOrder: 0
icon: {instanceID: 0} icon: {instanceID: 0}
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:
using System; using System;
using System.IO; using System.IO;
using UnityEditor.TestRunner.CommandLineParser; using UnityEditor.TestRunner.CommandLineParser;
using UnityEditor.TestTools.TestRunner.Api; using UnityEditor.TestTools.TestRunner.Api;
using UnityEngine; using UnityEngine;
namespace UnityEditor.TestTools.TestRunner.CommandLineTest namespace UnityEditor.TestTools.TestRunner.CommandLineTest
{ {
[InitializeOnLoad] [InitializeOnLoad]
static class TestStarter static class TestStarter
{ {
static TestStarter() static TestStarter()
{ {
if (!ShouldRunTests()) if (!ShouldRunTests())
{ {
return; return;
} }
if (EditorApplication.isCompiling) if (EditorApplication.isCompiling)
{ {
return; return;
} }
executer.ExitOnCompileErrors(); executer.ExitOnCompileErrors();
if (RunData.instance.isRunning) if (RunData.instance.isRunning)
{ {
executer.SetUpCallbacks(RunData.instance.executionSettings); executer.SetUpCallbacks(RunData.instance.executionSettings);
return; return;
} }
EditorApplication.update += UpdateWatch; EditorApplication.update += UpdateWatch;
} }
static void UpdateWatch() static void UpdateWatch()
{ {
EditorApplication.update -= UpdateWatch; EditorApplication.update -= UpdateWatch;
if (RunData.instance.isRunning) if (RunData.instance.isRunning)
{ {
return; return;
} }
RunData.instance.isRunning = true; RunData.instance.isRunning = true;
var commandLineArgs = Environment.GetCommandLineArgs(); var commandLineArgs = Environment.GetCommandLineArgs();
RunData.instance.executionSettings = executer.BuildExecutionSettings(commandLineArgs); RunData.instance.executionSettings = executer.BuildExecutionSettings(commandLineArgs);
executer.SetUpCallbacks(RunData.instance.executionSettings); executer.SetUpCallbacks(RunData.instance.executionSettings);
executer.InitializeAndExecuteRun(commandLineArgs); executer.InitializeAndExecuteRun(commandLineArgs);
} }
static bool ShouldRunTests() static bool ShouldRunTests()
{ {
var shouldRunTests = false; var shouldRunTests = false;
var optionSet = new CommandLineOptionSet( var optionSet = new CommandLineOptionSet(
new CommandLineOption("runTests", () => { shouldRunTests = true; }), new CommandLineOption("runTests", () => { shouldRunTests = true; }),
new CommandLineOption("runEditorTests", () => { shouldRunTests = true; }) new CommandLineOption("runEditorTests", () => { shouldRunTests = true; })
); );
optionSet.Parse(Environment.GetCommandLineArgs()); optionSet.Parse(Environment.GetCommandLineArgs());
return shouldRunTests; return shouldRunTests;
} }
static Executer s_Executer; static Executer s_Executer;
static Executer executer static Executer executer
{ {
get get
{ {
if (s_Executer == null) if (s_Executer == null)
{ {
Func<bool> compilationCheck = () => EditorUtility.scriptCompilationFailed; Func<bool> compilationCheck = () => EditorUtility.scriptCompilationFailed;
Action<string> actionLogger = (string msg) => { Debug.LogFormat(LogType.Log, LogOption.NoStacktrace, null, msg); }; Action<string> actionLogger = (string msg) => { Debug.LogFormat(LogType.Log, LogOption.NoStacktrace, null, msg); };
var apiSettingsBuilder = new SettingsBuilder(new TestSettingsDeserializer(() => new TestSettings()), actionLogger, Debug.LogWarning, File.Exists, compilationCheck); var apiSettingsBuilder = new SettingsBuilder(new TestSettingsDeserializer(() => new TestSettings()), actionLogger, Debug.LogWarning, File.Exists, compilationCheck);
s_Executer = new Executer(ScriptableObject.CreateInstance<TestRunnerApi>(), apiSettingsBuilder, Debug.LogErrorFormat, Debug.LogException, EditorApplication.Exit, compilationCheck); s_Executer = new Executer(ScriptableObject.CreateInstance<TestRunnerApi>(), apiSettingsBuilder, Debug.LogErrorFormat, Debug.LogException, EditorApplication.Exit, compilationCheck);
} }
return s_Executer; return s_Executer;
} }
} }
} }
} }
fileFormatVersion: 2 fileFormatVersion: 2
guid: 4d616d1a494edd144b262cf6cd5e5fda guid: 4d616d1a494edd144b262cf6cd5e5fda
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
defaultReferences: [] defaultReferences: []
executionOrder: 0 executionOrder: 0
icon: {instanceID: 0} icon: {instanceID: 0}
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:
fileFormatVersion: 2 fileFormatVersion: 2
guid: 7e609b27ad2caa14c83dd9951b6c13c6 guid: 7e609b27ad2caa14c83dd9951b6c13c6
folderAsset: yes folderAsset: yes
DefaultImporter: DefaultImporter:
externalObjects: {} externalObjects: {}
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:
namespace UnityEditor.TestTools.TestRunner.GUI namespace UnityEditor.TestTools.TestRunner.GUI
{ {
internal class AssetsDatabaseHelper : IAssetsDatabaseHelper internal class AssetsDatabaseHelper : IAssetsDatabaseHelper
{ {
public void OpenAssetInItsDefaultExternalEditor(string assetPath, int line) public void OpenAssetInItsDefaultExternalEditor(string assetPath, int line)
{ {
var asset = AssetDatabase.LoadMainAssetAtPath(assetPath); var asset = AssetDatabase.LoadMainAssetAtPath(assetPath);
AssetDatabase.OpenAsset(asset, line); AssetDatabase.OpenAsset(asset, line);
} }
} }
} }
fileFormatVersion: 2 fileFormatVersion: 2
guid: 740b3785866edda4b8d1e1a05570a5f8 guid: 740b3785866edda4b8d1e1a05570a5f8
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
defaultReferences: [] defaultReferences: []
executionOrder: 0 executionOrder: 0
icon: {instanceID: 0} icon: {instanceID: 0}
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using UnityEditor.Utils; using UnityEditor.Utils;
using UnityEngine; using UnityEngine;
namespace UnityEditor.TestTools.TestRunner.GUI namespace UnityEditor.TestTools.TestRunner.GUI
{ {
internal class GuiHelper : IGuiHelper internal class GuiHelper : IGuiHelper
{ {
public GuiHelper(IMonoCecilHelper monoCecilHelper, IAssetsDatabaseHelper assetsDatabaseHelper) public GuiHelper(IMonoCecilHelper monoCecilHelper, IAssetsDatabaseHelper assetsDatabaseHelper)
{ {
MonoCecilHelper = monoCecilHelper; MonoCecilHelper = monoCecilHelper;
AssetsDatabaseHelper = assetsDatabaseHelper; AssetsDatabaseHelper = assetsDatabaseHelper;
} }
protected IMonoCecilHelper MonoCecilHelper { get; private set; } protected IMonoCecilHelper MonoCecilHelper { get; private set; }
public IAssetsDatabaseHelper AssetsDatabaseHelper { get; private set; } public IAssetsDatabaseHelper AssetsDatabaseHelper { get; private set; }
public void OpenScriptInExternalEditor(Type type, MethodInfo method) public void OpenScriptInExternalEditor(Type type, MethodInfo method)
{ {
var fileOpenInfo = GetFileOpenInfo(type, method); var fileOpenInfo = GetFileOpenInfo(type, method);
if (string.IsNullOrEmpty(fileOpenInfo.FilePath)) 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."); Debug.LogWarning("Failed to open test method source code in external editor. Inconsistent filename and yield return operator in target method.");
return; return;
} }
if (fileOpenInfo.LineNumber == 1) 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."); 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); AssetsDatabaseHelper.OpenAssetInItsDefaultExternalEditor(fileOpenInfo.FilePath, fileOpenInfo.LineNumber);
} }
public IFileOpenInfo GetFileOpenInfo(Type type, MethodInfo method) public IFileOpenInfo GetFileOpenInfo(Type type, MethodInfo method)
{ {
const string fileExtension = ".cs"; const string fileExtension = ".cs";
var fileOpenInfo = MonoCecilHelper.TryGetCecilFileOpenInfo(type, method); var fileOpenInfo = MonoCecilHelper.TryGetCecilFileOpenInfo(type, method);
if (string.IsNullOrEmpty(fileOpenInfo.FilePath)) if (string.IsNullOrEmpty(fileOpenInfo.FilePath))
{ {
var dirPath = Paths.UnifyDirectorySeparator(Application.dataPath); var dirPath = Paths.UnifyDirectorySeparator(Application.dataPath);
var allCsFiles = Directory.GetFiles(dirPath, $"*{fileExtension}", SearchOption.AllDirectories) var allCsFiles = Directory.GetFiles(dirPath, $"*{fileExtension}", SearchOption.AllDirectories)
.Select(Paths.UnifyDirectorySeparator); .Select(Paths.UnifyDirectorySeparator);
var fileName = allCsFiles.FirstOrDefault(x => var fileName = allCsFiles.FirstOrDefault(x =>
x.Split(Path.DirectorySeparatorChar).Last().Equals(string.Concat(type.Name, fileExtension))); x.Split(Path.DirectorySeparatorChar).Last().Equals(string.Concat(type.Name, fileExtension)));
fileOpenInfo.FilePath = fileName ?? string.Empty; fileOpenInfo.FilePath = fileName ?? string.Empty;
} }
fileOpenInfo.FilePath = FilePathToAssetsRelativeAndUnified(fileOpenInfo.FilePath); fileOpenInfo.FilePath = FilePathToAssetsRelativeAndUnified(fileOpenInfo.FilePath);
return fileOpenInfo; return fileOpenInfo;
} }
public string FilePathToAssetsRelativeAndUnified(string filePath) public string FilePathToAssetsRelativeAndUnified(string filePath)
{ {
if (string.IsNullOrEmpty(filePath)) if (string.IsNullOrEmpty(filePath))
return string.Empty; return string.Empty;
filePath = Paths.UnifyDirectorySeparator(filePath); filePath = Paths.UnifyDirectorySeparator(filePath);
var length = Paths.UnifyDirectorySeparator(Application.dataPath).Length - "Assets".Length; var length = Paths.UnifyDirectorySeparator(Application.dataPath).Length - "Assets".Length;
return filePath.Substring(length); return filePath.Substring(length);
} }
public bool OpenScriptInExternalEditor(string stacktrace) public bool OpenScriptInExternalEditor(string stacktrace)
{ {
if (string.IsNullOrEmpty(stacktrace)) if (string.IsNullOrEmpty(stacktrace))
return false; return false;
var regex = new Regex("in (?<path>.*):{1}(?<line>[0-9]+)"); 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(); var matchingLines = stacktrace.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Where(x => regex.IsMatch(x)).ToList();
if (!matchingLines.Any()) if (!matchingLines.Any())
return false; return false;
var fileOpenInfos = matchingLines var fileOpenInfos = matchingLines
.Select(x => regex.Match(x)) .Select(x => regex.Match(x))
.Select(x => .Select(x =>
new FileOpenInfo new FileOpenInfo
{ {
FilePath = x.Groups["path"].Value, FilePath = x.Groups["path"].Value,
LineNumber = int.Parse(x.Groups["line"].Value) LineNumber = int.Parse(x.Groups["line"].Value)
}).ToList(); }).ToList();
var fileOpenInfo = fileOpenInfos var fileOpenInfo = fileOpenInfos
.FirstOrDefault(openInfo => !string.IsNullOrEmpty(openInfo.FilePath) && File.Exists(openInfo.FilePath)); .FirstOrDefault(openInfo => !string.IsNullOrEmpty(openInfo.FilePath) && File.Exists(openInfo.FilePath));
if (fileOpenInfo == null) if (fileOpenInfo == null)
{ {
return false; return false;
} }
var filePath = FilePathToAssetsRelativeAndUnified(fileOpenInfo.FilePath); var filePath = FilePathToAssetsRelativeAndUnified(fileOpenInfo.FilePath);
AssetsDatabaseHelper.OpenAssetInItsDefaultExternalEditor(filePath, fileOpenInfo.LineNumber); AssetsDatabaseHelper.OpenAssetInItsDefaultExternalEditor(filePath, fileOpenInfo.LineNumber);
return true; return true;
} }
} }
} }
fileFormatVersion: 2 fileFormatVersion: 2
guid: d0138170d24533e47b8e6c250c6d7fbc guid: d0138170d24533e47b8e6c250c6d7fbc
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
defaultReferences: [] defaultReferences: []
executionOrder: 0 executionOrder: 0
icon: {instanceID: 0} icon: {instanceID: 0}
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:
namespace UnityEditor.TestTools.TestRunner.GUI namespace UnityEditor.TestTools.TestRunner.GUI
{ {
internal interface IAssetsDatabaseHelper internal interface IAssetsDatabaseHelper
{ {
void OpenAssetInItsDefaultExternalEditor(string assetPath, int line); void OpenAssetInItsDefaultExternalEditor(string assetPath, int line);
} }
} }
fileFormatVersion: 2 fileFormatVersion: 2
guid: 208e46d59ff6e304db0318377d20f5a1 guid: 208e46d59ff6e304db0318377d20f5a1
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2
defaultReferences: [] defaultReferences: []
executionOrder: 0 executionOrder: 0
icon: {instanceID: 0} icon: {instanceID: 0}
userData: userData:
assetBundleName: assetBundleName:
assetBundleVariant: assetBundleVariant:
using System; using System;
using System.Reflection; using System.Reflection;
namespace UnityEditor.TestTools.TestRunner.GUI namespace UnityEditor.TestTools.TestRunner.GUI
{ {
internal interface IGuiHelper internal interface IGuiHelper
{ {
bool OpenScriptInExternalEditor(string stacktrace); bool OpenScriptInExternalEditor(string stacktrace);
void OpenScriptInExternalEditor(Type type, MethodInfo method); void OpenScriptInExternalEditor(Type type, MethodInfo method);
IFileOpenInfo GetFileOpenInfo(Type type, MethodInfo method); IFileOpenInfo GetFileOpenInfo(Type type, MethodInfo method);
string FilePathToAssetsRelativeAndUnified(string filePath); string FilePathToAssetsRelativeAndUnified(string filePath);
} }
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment