Skip to content

Instantly share code, notes, and snippets.

@michael-wolfenden
Last active July 23, 2019 02:49
Show Gist options
  • Save michael-wolfenden/3cfff65de7f4fced965c99d32e3e2e0b to your computer and use it in GitHub Desktop.
Save michael-wolfenden/3cfff65de7f4fced965c99d32e3e2e0b to your computer and use it in GitHub Desktop.
[Linqpad XUnit Runner] Run xunit within linqpad #xunit
/*
<Query Kind="Program">
<NuGetReference>xunit</NuGetReference>
<NuGetReference>xunit.runner.utility</NuGetReference>
<Namespace>Xunit</Namespace>
<Namespace>Xunit.Runners</Namespace>
<CopyLocal>true</CopyLocal>
</Query>
*/
void Main()
{
XUnitRunner.Run(Assembly.GetExecutingAssembly());
}
[Theory]
[InlineData(3)]
[InlineData(5)]
[InlineData(6)]
public void MyFirstTheory(int value)
{
Assert.True(IsOdd(value));
}
bool IsOdd(int value)
{
return value % 2 == 1;
}
// see: https://github.com/xunit/samples.xunit/blob/1173213302fd3a45bd6e4303371d2f78f1743552/TestRunner/Program.cs
public class XUnitRunner
{
private Assembly _testAssembly;
private object _consoleLock = new object();
private ManualResetEvent finished = new ManualResetEvent(false);
private int _result = 0;
private XUnitRunner(Assembly testAssembly) =>
_testAssembly = testAssembly ?? throw new ArgumentNullException(nameof(testAssembly));
public static int Run(Assembly testAssembly) =>
new XUnitRunner(testAssembly).Run();
private int Run()
{
var newTestAssemblyLocation = CopyTestAssemblyToTheSameFolderAsTheXUnitAssemblies();
using (var runner = AssemblyRunner.WithoutAppDomain(newTestAssemblyLocation))
{
runner.OnDiscoveryComplete = OnDiscoveryComplete;
runner.OnExecutionComplete = OnExecutionComplete;
runner.OnTestFailed = OnTestFailed;
runner.OnTestSkipped = OnTestSkipped;
Console.WriteLine("Discovering...");
runner.Start();
finished.WaitOne();
finished.Dispose();
return _result;
}
}
private string CopyTestAssemblyToTheSameFolderAsTheXUnitAssemblies()
{
var testAssemblyFolder = new DirectoryInfo(Path.GetDirectoryName(_testAssembly.Location));
var xunitFolder = new DirectoryInfo(Path.GetDirectoryName(typeof(Xunit.Assert).Assembly.Location));
var isXunitInASubDirectory = xunitFolder.Parent.FullName == testAssemblyFolder.FullName;
if (!isXunitInASubDirectory)
throw new InvalidOperationException("Please enable 'Copy all non-framework references to a single local folder' (F4 -> Advanced).");
var newTestAssemblyPath = Path.Combine(xunitFolder.FullName, Path.GetFileName(_testAssembly.Location));
File.Copy(_testAssembly.Location, newTestAssemblyPath, overwrite: true);
return newTestAssemblyPath;
}
private void OnDiscoveryComplete(DiscoveryCompleteInfo info)
{
lock (_consoleLock)
Console.WriteLine($"Running {info.TestCasesToRun} of {info.TestCasesDiscovered} tests...");
}
private void OnExecutionComplete(ExecutionCompleteInfo info)
{
lock (_consoleLock)
Console.WriteLine($"Finished: {info.TotalTests} tests in {Math.Round(info.ExecutionTime, 3)}s ({info.TestsFailed} failed, {info.TestsSkipped} skipped)");
finished.Set();
}
private void OnTestFailed(TestFailedInfo info)
{
lock (_consoleLock)
{
Console.WriteLine("[FAIL] {0}: {1}", info.TestDisplayName, info.ExceptionMessage);
if (info.ExceptionStackTrace != null)
Console.WriteLine(info.ExceptionStackTrace);
}
_result = 1;
}
private void OnTestSkipped(TestSkippedInfo info)
{
lock (_consoleLock)
{
Console.WriteLine("[SKIP] {0}: {1}", info.TestDisplayName, info.SkipReason);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment