|
|
|
@ -1,4 +1,6 @@ |
|
|
|
using System.Threading.Tasks; |
|
|
|
using System; |
|
|
|
using System.Reflection; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using NUnit.Framework.Interfaces; |
|
|
|
using NUnit.Framework.Internal; |
|
|
|
using NUnit.Framework.Internal.Commands; |
|
|
|
@ -9,6 +11,11 @@ internal class AvaloniaTestCommand : DelegatingTestCommand |
|
|
|
{ |
|
|
|
private readonly HeadlessUnitTestSession _session; |
|
|
|
|
|
|
|
private static FieldInfo s_beforeTest = typeof(BeforeAndAfterTestCommand) |
|
|
|
.GetField("BeforeTest", BindingFlags.Instance | BindingFlags.NonPublic)!; |
|
|
|
private static FieldInfo s_afterTest = typeof(BeforeAndAfterTestCommand) |
|
|
|
.GetField("AfterTest", BindingFlags.Instance | BindingFlags.NonPublic)!; |
|
|
|
|
|
|
|
public AvaloniaTestCommand(HeadlessUnitTestSession session, TestCommand innerCommand) |
|
|
|
: base(innerCommand) |
|
|
|
{ |
|
|
|
@ -23,25 +30,41 @@ internal class AvaloniaTestCommand : DelegatingTestCommand |
|
|
|
// Unfortunately, NUnit has issues with custom synchronization contexts, which means we need to add some hacks to make it work.
|
|
|
|
private async Task<TestResult> ExecuteTestMethod(TestExecutionContext context) |
|
|
|
{ |
|
|
|
var testMethod = innerCommand.Test.Method; |
|
|
|
var methodInfo = testMethod!.MethodInfo; |
|
|
|
|
|
|
|
var result = methodInfo.Invoke(context.TestObject, innerCommand.Test.Arguments); |
|
|
|
// Only Task, non generic ValueTask are supported in async context. No ValueTask<> nor F# tasks.
|
|
|
|
if (result is Task task) |
|
|
|
{ |
|
|
|
await task; |
|
|
|
} |
|
|
|
else if (result is ValueTask valueTask) |
|
|
|
try |
|
|
|
{ |
|
|
|
await valueTask; |
|
|
|
} |
|
|
|
if (innerCommand is BeforeAndAfterTestCommand beforeTestCommand) |
|
|
|
{ |
|
|
|
(s_beforeTest.GetValue(beforeTestCommand) as Action<TestExecutionContext>)?.Invoke(context); |
|
|
|
} |
|
|
|
|
|
|
|
var testMethod = innerCommand.Test.Method; |
|
|
|
var methodInfo = testMethod!.MethodInfo; |
|
|
|
|
|
|
|
context.CurrentResult.SetResult(ResultState.Success); |
|
|
|
var result = methodInfo.Invoke(context.TestObject, innerCommand.Test.Arguments); |
|
|
|
// Only Task, non generic ValueTask are supported in async context. No ValueTask<> nor F# tasks.
|
|
|
|
if (result is Task task) |
|
|
|
{ |
|
|
|
await task; |
|
|
|
} |
|
|
|
else if (result is ValueTask valueTask) |
|
|
|
{ |
|
|
|
await valueTask; |
|
|
|
} |
|
|
|
|
|
|
|
if (context.CurrentResult.AssertionResults.Count > 0) |
|
|
|
context.CurrentResult.RecordTestCompletion(); |
|
|
|
context.CurrentResult.SetResult(ResultState.Success); |
|
|
|
|
|
|
|
return context.CurrentResult; |
|
|
|
if (context.CurrentResult.AssertionResults.Count > 0) |
|
|
|
context.CurrentResult.RecordTestCompletion(); |
|
|
|
|
|
|
|
return context.CurrentResult; |
|
|
|
} |
|
|
|
finally |
|
|
|
{ |
|
|
|
if (innerCommand is BeforeAndAfterTestCommand beforeTestCommand |
|
|
|
&& context.ExecutionStatus != TestExecutionStatus.AbortRequested) |
|
|
|
{ |
|
|
|
(s_afterTest.GetValue(beforeTestCommand) as Action<TestExecutionContext>)?.Invoke(context); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|