private bool TryLaunchUnitTestsInAssembly(string[] testNames) { try { var assemblies = AppDomain.CurrentDomain.GetAssemblies(); var testEditorAssembly = assemblies .FirstOrDefault(assembly => assembly.GetName().Name.Equals("UnityEditor.TestRunner")); var testEngineAssembly = assemblies .FirstOrDefault(assembly => assembly.GetName().Name.Equals("UnityEngine.TestRunner")); if (testEditorAssembly == null || testEngineAssembly == null) { ourLogger.Verbose( "Could not find UnityEditor.TestRunner or UnityEngine.TestRunner assemblies in current AppDomain"); return(false); } var launcherTypeString = "UnityEditor.TestTools.TestRunner.EditModeLauncher"; var launcherType = testEditorAssembly.GetType(launcherTypeString); if (launcherType == null) { string testEditorAssemblyProperties = testEditorAssembly.GetTypes().Select(a => a.Name).Aggregate((a, b) => a + ", " + b); throw new NullReferenceException($"Could not find {launcherTypeString} among {testEditorAssemblyProperties}"); } var filterType = testEngineAssembly.GetType("UnityEngine.TestTools.TestRunner.GUI.TestRunnerFilter"); if (filterType == null) { string testEngineAssemblyProperties = testEngineAssembly.GetTypes().Select(a => a.Name).Aggregate((a, b) => a + ", " + b); throw new NullReferenceException($"Could not find \"UnityEngine.TestTools.TestRunner.GUI.TestRunnerFilter\" among {testEngineAssemblyProperties}"); } var filter = Activator.CreateInstance(filterType); var fieldInfo = filter.GetType().GetField("testNames", BindingFlags.Instance | BindingFlags.Public); fieldInfo = fieldInfo ?? filter.GetType().GetField("names", BindingFlags.Instance | BindingFlags.Public); if (fieldInfo == null) { ourLogger.Verbose("Could not find testNames field via reflection"); return(false); } fieldInfo.SetValue(filter, testNames); var clientController = ClientControllerWrapper.TryCreate(myLaunch.SessionId, myLaunch.ClientControllerInfo); clientController?.OnSessionStarted(); object launcher; if (UnityUtils.UnityVersion >= new Version(2018, 1)) { var enumType = testEngineAssembly.GetType("UnityEngine.TestTools.TestPlatform"); if (enumType == null) { ourLogger.Verbose("Could not find TestPlatform field via reflection"); return(false); } var assemblyProviderType = testEditorAssembly.GetType("UnityEditor.TestTools.TestRunner.TestInEditorTestAssemblyProvider"); var testPlatformVal = 2; // All = 255, // 0xFF, EditMode = 2, PlayMode = 4, if (assemblyProviderType != null) { var assemblyProvider = Activator.CreateInstance(assemblyProviderType, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, new[] { Enum.ToObject(enumType, testPlatformVal) }, null); ourLogger.Log(LoggingLevel.INFO, assemblyProvider.ToString()); launcher = Activator.CreateInstance(launcherType, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, new[] { filter, assemblyProvider }, null); } else { try { launcher = Activator.CreateInstance(launcherType, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, new[] { filter, Enum.ToObject(enumType, testPlatformVal) }, null); } catch (Exception) // Unity 2019.2+ with package com.unity.test-framework v 1.0.18 and 1.1.0 ctor was changed. in v 1.1.1 it was added back for compatibility { var apiFilterType = testEditorAssembly.GetType("UnityEditor.TestTools.TestRunner.Api.Filter"); var apiFilter = Activator.CreateInstance(apiFilterType); var testNamesFieldInfo = apiFilter.GetType().GetField("testNames"); testNamesFieldInfo.SetValue(apiFilter, testNames); var array = Array.CreateInstance(apiFilterType, 1); array.SetValue(apiFilter, 0); launcher = Activator.CreateInstance(launcherType, array, Enum.ToObject(enumType, testPlatformVal)); } } } else { launcher = Activator.CreateInstance(launcherType, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, new[] { filter }, null); } var runnerField = launcherType.GetField("m_EditModeRunner", BindingFlags.Instance | BindingFlags.NonPublic); if (runnerField == null) { ourLogger.Verbose("Could not find runnerField via reflection"); return(false); } var runner = runnerField.GetValue(launcher); SupportAbort(runner); var runLifetimeDef = Lifetime.Define(myConnectionLifetime); runLifetimeDef.Lifetime.OnTermination(() => { if (myConnectionLifetime.IsNotAlive) { TestEventsSender.RunFinished(myLaunch, new RunResult(false)); } }); var runStarted = false; try { if (!AdviseTestStarted(runner, "m_TestStartedEvent", test => { if (!(test is TestMethod)) { return; } ourLogger.Verbose("TestStarted : {0}", test.FullName); var testId = TestEventsSender.GetIdFromNUnitTest(test); var parentId = TestEventsSender.GetIdFromNUnitTest(test.Parent); var tResult = new TestResult(testId, test.Method.TypeInfo.Assembly.GetName().Name, string.Empty, 0, Status.Running, parentId); clientController?.OnTestStarted(testId); TestEventsSender.TestStarted(myLaunch, tResult); })) { return(false); } if (!AdviseTestFinished(runner, "m_TestFinishedEvent", result => { if (!(result.Test is TestMethod)) { return; } clientController?.OnTestFinished(); TestEventsSender.TestFinished(myLaunch, TestEventsSender.GetTestResult(result)); })) { return(false); } if (!AdviseSessionFinished(runner, "m_RunFinishedEvent", result => { clientController?.OnSessionFinished(); runLifetimeDef.Terminate(); var runResult = new RunResult(Equals(result.ResultState, ResultState.Success)); TestEventsSender.RunFinished(myLaunch, runResult); })) { return(false); } var runMethod = launcherType.GetMethod("Run", BindingFlags.Instance | BindingFlags.Public); if (runMethod == null) { ourLogger.Verbose("Could not find runMethod via reflection"); return(false); } //run! runMethod.Invoke(launcher, null); runStarted = true; return(true); } finally { if (!runStarted) { runLifetimeDef.Terminate(); } } } catch (Exception e) { ourLogger.Error(e, "Exception while launching Unity Editor tests."); return(false); } }
public static void TestFinished(UnitTestLaunch launch, TestResult testResult) { launch.TestResult(testResult); }
private static void ProcessQueue(Type data, UnitTestLaunch unitTestLaunch) { if (!unitTestLaunch.IsBound) { return; } var baseType = data.BaseType; if (baseType == null) { return; } var instance = baseType.GetProperty("instance"); if (instance == null) { return; } var instanceVal = instance.GetValue(null, new object[] {}); var listField = data.GetField("events"); if (listField == null) { return; } var list = listField.GetValue(instanceVal); var events = (IEnumerable)list; foreach (var ev in events) { var type = (int)ev.GetType().GetField("type").GetValue(ev); var id = (string)ev.GetType().GetField("id").GetValue(ev); var assemblyName = (string)ev.GetType().GetField("assemblyName").GetValue(ev); var output = (string)ev.GetType().GetField("output").GetValue(ev); var resultState = (int)ev.GetType().GetField("testStatus").GetValue(ev); var duration = (double)ev.GetType().GetField("duration").GetValue(ev); var parentId = (string)ev.GetType().GetField("parentId").GetValue(ev); switch (type) { case 0: // TestStarted { var tResult = new TestResult(id, assemblyName, string.Empty, 0, Status.Running, parentId); TestStarted(unitTestLaunch, tResult); break; } case 1: // TestFinished { var status = GetStatus(new ResultState((TestStatus)resultState)); var testResult = new TestResult(id, assemblyName, output, (int)duration, status, parentId); TestFinished(unitTestLaunch, testResult); break; } case 2: // RunFinished { var runResult = new RunResult((TestStatus)resultState == TestStatus.Passed); RunFinished(unitTestLaunch, runResult); break; } case 3: // RunStarted { unitTestLaunch.RunStarted.Value = true; break; } default: { ourLogger.Error("Unexpected TestEvent type."); break; } } } var clearMethod = data.GetMethod("Clear"); clearMethod?.Invoke(instanceVal, new object[] {}); }
public static void TestStarted(UnitTestLaunch launch, TestResult testResult) { launch.TestResult(testResult); }