<PackageReference Include="NUnit" Version="3.6.0" />

NUnitTestAssemblyRunner

Implementation of ITestAssemblyRunner
using NUnit.Framework.Interfaces; using NUnit.Framework.Internal; using NUnit.Framework.Internal.Execution; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Security; using System.Threading; using System.Windows.Forms; namespace NUnit.Framework.Api { public class NUnitTestAssemblyRunner : ITestAssemblyRunner { private static Logger log = InternalTrace.GetLogger("DefaultTestAssemblyRunner"); private ITestAssemblyBuilder _builder; private ManualResetEvent _runComplete = new ManualResetEvent(false); private TextWriter _savedOut; private TextWriter _savedErr; private EventPump _pump; public static int DefaultLevelOfParallelism => Math.Max(Environment.ProcessorCount, 2); public ITest LoadedTest { get; set; } public ITestResult Result { get { if (TopLevelWorkItem != null) return TopLevelWorkItem.Result; return null; } } public bool IsTestLoaded => LoadedTest != null; public bool IsTestRunning { get { if (TopLevelWorkItem != null) return TopLevelWorkItem.State == WorkItemState.Running; return false; } } public bool IsTestComplete { get { if (TopLevelWorkItem != null) return TopLevelWorkItem.State == WorkItemState.Complete; return false; } } private IDictionary<string, object> Settings { get; set; } private WorkItem TopLevelWorkItem { get; set; } private TestExecutionContext Context { get; set; } public NUnitTestAssemblyRunner(ITestAssemblyBuilder builder) { _builder = builder; } public ITest Load(string assemblyName, IDictionary<string, object> settings) { Settings = settings; if (settings.ContainsKey("RandomSeed")) Randomizer.InitialSeed = (int)settings["RandomSeed"]; return LoadedTest = _builder.Build(assemblyName, settings); } public ITest Load(Assembly assembly, IDictionary<string, object> settings) { Settings = settings; if (settings.ContainsKey("RandomSeed")) Randomizer.InitialSeed = (int)settings["RandomSeed"]; return LoadedTest = _builder.Build(assembly, settings); } public int CountTestCases(ITestFilter filter) { if (LoadedTest == null) throw new InvalidOperationException("The CountTestCases method was called but no test has been loaded"); return CountTestCases(LoadedTest, filter); } public ITestResult Run(ITestListener listener, ITestFilter filter) { RunAsync(listener, filter); WaitForCompletion(-1); return Result; } public void RunAsync(ITestListener listener, ITestFilter filter) { log.Info("Running tests"); if (LoadedTest == null) throw new InvalidOperationException("The Run method was called but no test has been loaded"); _runComplete.Reset(); CreateTestExecutionContext(listener); TopLevelWorkItem = WorkItem.CreateWorkItem(LoadedTest, filter); TopLevelWorkItem.InitializeContext(Context); TopLevelWorkItem.Completed += OnRunCompleted; StartRun(listener); } public bool WaitForCompletion(int timeout) { return _runComplete.WaitOne(timeout, false); } public void StopRun(bool force) { if (IsTestRunning) { Context.ExecutionStatus = ((!force) ? TestExecutionStatus.StopRequested : TestExecutionStatus.AbortRequested); Context.Dispatcher.CancelRun(force); } } private void StartRun(ITestListener listener) { _savedOut = Console.Out; _savedErr = Console.Error; Console.SetOut(new TextCapture(Console.Out)); Console.SetError(new EventListenerTextWriter("Error", Console.Error)); if (!Settings.ContainsKey("SynchronousEvents") || !(bool)Settings["SynchronousEvents"]) { QueuingEventListener queuingEventListener = new QueuingEventListener(); Context.Listener = queuingEventListener; _pump = new EventPump(listener, queuingEventListener.Events); _pump.Start(); } if (!Debugger.IsAttached && Settings.ContainsKey("DebugTests") && (bool)Settings["DebugTests"]) Debugger.Launch(); if (Settings.ContainsKey("PauseBeforeRun") && (bool)Settings["PauseBeforeRun"]) PauseBeforeRun(); Context.Dispatcher.Dispatch(TopLevelWorkItem); } private void CreateTestExecutionContext(ITestListener listener) { Context = new TestExecutionContext(); if (Settings.ContainsKey("DefaultTimeout")) Context.TestCaseTimeout = (int)Settings["DefaultTimeout"]; if (Settings.ContainsKey("StopOnError")) Context.StopOnError = (bool)Settings["StopOnError"]; if (Settings.ContainsKey("WorkDirectory")) Context.WorkDirectory = (string)Settings["WorkDirectory"]; else Context.WorkDirectory = Directory.GetCurrentDirectory(); Context.Listener = listener; int levelOfParallelism = GetLevelOfParallelism(); if (levelOfParallelism > 0) Context.Dispatcher = new ParallelWorkItemDispatcher(levelOfParallelism); else Context.Dispatcher = new SimpleWorkItemDispatcher(); } private void OnRunCompleted(object sender, EventArgs e) { if (_pump != null) _pump.Dispose(); Console.SetOut(_savedOut); Console.SetError(_savedErr); _runComplete.Set(); } private int CountTestCases(ITest test, ITestFilter filter) { if (!test.IsSuite) return 1; int num = 0; foreach (ITest test2 in test.Tests) { if (filter.Pass(test2)) num += CountTestCases(test2, filter); } return num; } private int GetLevelOfParallelism() { if (!Settings.ContainsKey("NumberOfTestWorkers")) { if (!LoadedTest.Properties.ContainsKey("LevelOfParallelism")) return DefaultLevelOfParallelism; return (int)LoadedTest.Properties.Get("LevelOfParallelism"); } return (int)Settings["NumberOfTestWorkers"]; } [SecuritySafeCritical] private static void PauseBeforeRun() { Process currentProcess = Process.GetCurrentProcess(); MessageBox.Show($"""{currentProcess.ProcessName}""{currentProcess.Id}""", currentProcess.ProcessName, 0, 64); } } }