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); } }
private void 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; } var launcherTypeString = myLaunch.TestMode == TestMode.Edit ? "UnityEditor.TestTools.TestRunner.EditModeLauncher" : "UnityEditor.TestTools.TestRunner.PlaymodeLauncher"; 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; } fieldInfo.SetValue(filter, testNames); // todo: restore, once Unity fixes UnityEngine.TestTools.TestRunner.GUI.TestRunnerFilter.BuildNUnitFilter // Currently assemblyName filters are added with OR to testNames filers // var assemblyNamesFieldInfo = filter.GetType().GetField("assemblyNames", BindingFlags.Instance | BindingFlags.Public); // if (assemblyNamesFieldInfo == null) // { // ourLogger.Warn("Could not find assemblyNames field via reflection"); // return; // } // assemblyNamesFieldInfo.SetValue(filter, new[] { assemblyName }); if (myLaunch.TestMode == TestMode.Play) { PlayModeSupport.PlayModeLauncherRun(filter, launcherType, testEditorAssembly, testEngineAssembly); } else { 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; } 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 { launcher = Activator.CreateInstance(launcherType, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, new[] { filter, Enum.ToObject(enumType, testPlatformVal) }, null); } } 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; } var runner = runnerField.GetValue(launcher); SupportAbort(runner); if (!AdviseTestStarted(runner, "m_TestStartedEvent", test => { if (!(test is TestMethod)) { return; } ourLogger.Verbose("TestStarted : {0}", test.FullName); var tResult = new TestResult(TestEventsSender.GetIdFromNUnitTest(test), test.Method.TypeInfo.Assembly.GetName().Name, string.Empty, 0, Status.Running, TestEventsSender.GetIdFromNUnitTest(test.Parent)); TestEventsSender.TestStarted(myLaunch, tResult); })) { return; } if (!AdviseTestFinished(runner, "m_TestFinishedEvent", result => { if (!(result.Test is TestMethod)) { return; } var res = TestEventsSender.GetTestResult(result); TestEventsSender.TestFinished(myLaunch, TestEventsSender.GetTestResult(res)); })) { return; } if (!AdviseSessionFinished(runner, "m_RunFinishedEvent", result => { TestEventsSender.RunFinished(myLaunch); })) { return; } var runMethod = launcherType.GetMethod("Run", BindingFlags.Instance | BindingFlags.Public); if (runMethod == null) { ourLogger.Verbose("Could not find runMethod via reflection"); return; } //run! runMethod.Invoke(launcher, null); } } catch (Exception e) { ourLogger.Error(e, "Exception while launching Unity Editor tests."); } }