You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've been experimenting with making sure I can cancel AssemblyRunner, and I've run weirdness when cancelling the runner quickly after calling Start or quickly after it reaches AssemblyRunnerStatus.Executing.
I'm looking for best practices on making sure I can deterministically cancel and dispose of the runner.
This snippet will run OnExecutionComplete, but the state is forever Executing
using System;
using System.Reflection;
using Xunit.Runners;
using System.Threading;
using System.Threading.Tasks;
using System.Text;
using System.Collections.Generic;
namespace XUnitExploration
{
public class XUnitRunner
{
object consoleLock = new object();
ManualResetEvent finished = new ManualResetEvent(false);
StringBuilder results = new StringBuilder();
public XUnitRunner()
{
}
public async Task<string> Run()
{
Console.WriteLine("Running");
var testAssembly = Assembly.Load("ExtraXUnit");
using var runner = AssemblyRunner.WithoutAppDomain(testAssembly.Location);
runner.TestCaseFilter = (test) => {
return true;
};
runner.OnDiscoveryComplete = OnDiscoveryComplete;
runner.OnExecutionComplete = OnExecutionComplete;
runner.OnTestFailed = OnTestFailed;
runner.Start();
runner.Cancel();
finished.WaitOne();
while (runner.Status != AssemblyRunnerStatus.Idle)
{
await Task.Delay(1000);
Console.WriteLine(runner.Status);
}
finished.Dispose();
return results.ToString();
}
void OnDiscoveryComplete(DiscoveryCompleteInfo info)
{
Console.WriteLine($"Running {info.TestCasesToRun} of {info.TestCasesDiscovered} tests...");
results.AppendLine($"Running {info.TestCasesToRun} of {info.TestCasesDiscovered} tests...");
}
void OnExecutionComplete(ExecutionCompleteInfo info)
{
Console.WriteLine($"Finished: {info.TotalTests} tests in {info.ExecutionTime}s ({info.TestsFailed} failed, {info.TestsSkipped} skipped)");
results.AppendLine($"Finished: {info.TotalTests} tests in {info.ExecutionTime}s ({info.TestsFailed} failed, {info.TestsSkipped} skipped)");
finished.Set();
}
void OnTestFailed(TestFailedInfo info)
{
Console.WriteLine($"[FAIL] {info.TestDisplayName}: {info.ExceptionMessage}");
results.AppendLine($"[FAIL] {info.TestDisplayName}: {info.ExceptionMessage}");
if (info.ExceptionStackTrace != null)
{
Console.WriteLine(info.ExceptionStackTrace);
results.AppendLine(info.ExceptionStackTrace);
}
}
}
}
If we take a very similar snipped but wait for the Status to be Executing before calling Cancel, it sometimes never calls OnExecutionComplete, therefore the finished.WaitOne() is sometimes never completed.
using System;
using System.Reflection;
using Xunit.Runners;
using System.Threading;
using System.Threading.Tasks;
using System.Text;
using System.Collections.Generic;
namespace XUnitExploration
{
public class XUnitRunner
{
object consoleLock = new object();
ManualResetEvent finished = new ManualResetEvent(false);
StringBuilder results = new StringBuilder();
public XUnitRunner()
{
}
public async Task<string> Run()
{
Console.WriteLine("Running");
var testAssembly = Assembly.Load("ExtraXUnit");
using var runner = AssemblyRunner.WithoutAppDomain(testAssembly.Location);
runner.TestCaseFilter = (test) => {
return true;
};
runner.OnDiscoveryComplete = OnDiscoveryComplete;
runner.OnExecutionComplete = OnExecutionComplete;
runner.OnTestFailed = OnTestFailed;
runner.Start();
while (runner.Status != AssemblyRunnerStatus.Executing)
{
await Task.Delay(10);
Console.WriteLine(runner.Status);
}
runner.Cancel();
finished.WaitOne();
while (runner.Status != AssemblyRunnerStatus.Idle)
{
await Task.Delay(1000);
Console.WriteLine(runner.Status);
}
finished.Dispose();
return results.ToString();
}
void OnDiscoveryComplete(DiscoveryCompleteInfo info)
{
Console.WriteLine($"Running {info.TestCasesToRun} of {info.TestCasesDiscovered} tests...");
results.AppendLine($"Running {info.TestCasesToRun} of {info.TestCasesDiscovered} tests...");
}
void OnExecutionComplete(ExecutionCompleteInfo info)
{
Console.WriteLine($"Finished: {info.TotalTests} tests in {info.ExecutionTime}s ({info.TestsFailed} failed, {info.TestsSkipped} skipped)");
results.AppendLine($"Finished: {info.TotalTests} tests in {info.ExecutionTime}s ({info.TestsFailed} failed, {info.TestsSkipped} skipped)");
finished.Set();
}
void OnTestFailed(TestFailedInfo info)
{
Console.WriteLine($"[FAIL] {info.TestDisplayName}: {info.ExceptionMessage}");
results.AppendLine($"[FAIL] {info.TestDisplayName}: {info.ExceptionMessage}");
if (info.ExceptionStackTrace != null)
{
Console.WriteLine(info.ExceptionStackTrace);
results.AppendLine(info.ExceptionStackTrace);
}
}
}
}
The text was updated successfully, but these errors were encountered:
I've been experimenting with making sure I can cancel
AssemblyRunner
, and I've run weirdness when cancelling the runner quickly after callingStart
or quickly after it reachesAssemblyRunnerStatus.Executing
.I'm looking for best practices on making sure I can deterministically cancel and dispose of the runner.
OnExecutionComplete
, but the state is foreverExecuting
Status
to beExecuting
before callingCancel
, it sometimes never callsOnExecutionComplete
, therefore thefinished.WaitOne()
is sometimes never completed.The text was updated successfully, but these errors were encountered: