Skip to content

Commit 6a0965c

Browse files
committed
Made the whole test execution synchronous
1 parent 77d79aa commit 6a0965c

File tree

1 file changed

+103
-88
lines changed

1 file changed

+103
-88
lines changed

src/xunit.execution/Sdk/Frameworks/XunitTestCase.cs

Lines changed: 103 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -426,141 +426,120 @@ protected async Task<decimal> RunTestWithArgumentsAsync(IMessageBus messageBus,
426426
var aggregator = new ExceptionAggregator(parentAggregator);
427427
var output = String.Empty; // TODO: Add output facilities for v2
428428

429-
if (!messageBus.QueueMessage(new TestStarting(this, displayName)))
430-
cancellationTokenSource.Cancel();
429+
if (!messageBus.QueueMessage(new TestStarting(this, displayName))) cancellationTokenSource.Cancel();
431430
else
432431
{
433432
if (!String.IsNullOrEmpty(SkipReason))
434433
{
435-
if (!messageBus.QueueMessage(new TestSkipped(this, displayName, SkipReason)))
436-
cancellationTokenSource.Cancel();
434+
if (!messageBus.QueueMessage(new TestSkipped(this, displayName, SkipReason))) cancellationTokenSource.Cancel();
437435
}
438436
else
439437
{
440438
var beforeAttributesRun = new Stack<BeforeAfterTestAttribute>();
441439

442440
if (!aggregator.HasExceptions)
443-
await aggregator.RunAsync(async () =>
441+
aggregator.Run(() =>
444442
{
445443
object testClass = null;
446444

447-
if (!methodUnderTest.IsStatic)
448-
{
449-
if (!messageBus.QueueMessage(new TestClassConstructionStarting(this, displayName)))
450-
cancellationTokenSource.Cancel();
451-
452-
try
453-
{
454-
if (!cancellationTokenSource.IsCancellationRequested)
455-
{
456-
executionTime.MeassureStep(() => testClass = Activator.CreateInstance(classUnderTest, constructorArguments));
457-
}
458-
}
459-
finally
460-
{
461-
if (!messageBus.QueueMessage(new TestClassConstructionFinished(this, displayName)))
462-
cancellationTokenSource.Cancel();
463-
}
464-
}
445+
testClass = CreateTest(messageBus, classUnderTest, constructorArguments, methodUnderTest, displayName, cancellationTokenSource, executionTime);
465446

466447
if (!cancellationTokenSource.IsCancellationRequested)
467448
{
468-
await aggregator.RunAsync(async () =>
449+
foreach (var beforeAfterAttribute in beforeAfterAttributes)
469450
{
470-
foreach (var beforeAfterAttribute in beforeAfterAttributes)
451+
var attributeName = beforeAfterAttribute.GetType().Name;
452+
if (!messageBus.QueueMessage(new BeforeTestStarting(this, displayName, attributeName)))
453+
cancellationTokenSource.Cancel();
454+
else
471455
{
472-
var attributeName = beforeAfterAttribute.GetType().Name;
473-
if (!messageBus.QueueMessage(new BeforeTestStarting(this, displayName, attributeName)))
474-
cancellationTokenSource.Cancel();
475-
else
456+
try
476457
{
477-
try
478-
{
479-
executionTime.MeassureStep(() => beforeAfterAttribute.Before(methodUnderTest));
480-
beforeAttributesRun.Push(beforeAfterAttribute);
481-
}
482-
finally
483-
{
484-
if (!messageBus.QueueMessage(new BeforeTestFinished(this, displayName, attributeName)))
485-
cancellationTokenSource.Cancel();
486-
}
458+
executionTime.MeassureStep(() => beforeAfterAttribute.Before(methodUnderTest));
459+
beforeAttributesRun.Push(beforeAfterAttribute);
460+
}
461+
finally
462+
{
463+
if (!messageBus.QueueMessage(new BeforeTestFinished(this, displayName, attributeName)))
464+
cancellationTokenSource.Cancel();
487465
}
488-
489-
if (cancellationTokenSource.IsCancellationRequested)
490-
return;
491466
}
492467

493-
if (!cancellationTokenSource.IsCancellationRequested)
468+
if (cancellationTokenSource.IsCancellationRequested)
469+
return;
470+
}
471+
472+
if (!cancellationTokenSource.IsCancellationRequested)
473+
{
474+
var parameterTypes = methodUnderTest.GetParameters().Select(p => p.ParameterType).ToArray();
475+
var oldSyncContext = SynchronizationContext.Current;
476+
477+
try
494478
{
495-
var parameterTypes = methodUnderTest.GetParameters().Select(p => p.ParameterType).ToArray();
496-
var oldSyncContext = SynchronizationContext.Current;
479+
var asyncSyncContext = new AsyncTestSyncContext();
480+
SetSynchronizationContext(asyncSyncContext);
497481

498-
try
482+
aggregator.Run(() =>
499483
{
500-
var asyncSyncContext = new AsyncTestSyncContext();
501-
SetSynchronizationContext(asyncSyncContext);
484+
var result = executionTime.MeassureStep(() => methodUnderTest.Invoke(testClass, Reflector.ConvertArguments(testMethodArguments, parameterTypes)));
502485

503-
await aggregator.RunAsync(async () =>
486+
var task = result as Task;
487+
488+
executionTime.MeassureStep(() =>
504489
{
505-
await executionTime.MeassureStepAsync(async () =>
490+
//Hack: Calling wait to make sure the whole test is executed on the same thread from the beginning to the end
491+
// There must a better way of doing this ...
492+
if (task != null) task.Wait();
493+
else
506494
{
507-
var result = methodUnderTest.Invoke(testClass, Reflector.ConvertArguments(testMethodArguments, parameterTypes));
508-
var task = result as Task;
509-
if (task != null)
510-
await task;
511-
else
512-
{
513-
var ex = await asyncSyncContext.WaitForCompletionAsync();
514-
if (ex != null)
515-
aggregator.Add(ex);
516-
}
517-
518-
});
495+
var waitForCompletion = asyncSyncContext.WaitForCompletionAsync();
496+
waitForCompletion.Wait();
497+
var ex = waitForCompletion.Result;
498+
if (ex != null) aggregator.Add(ex);
499+
}
500+
519501
});
520-
}
521-
finally
522-
{
523-
SetSynchronizationContext(oldSyncContext);
524-
}
502+
});
503+
}
504+
finally
505+
{
506+
SetSynchronizationContext(oldSyncContext);
525507
}
526-
});
508+
}
527509

528510
foreach (var beforeAfterAttribute in beforeAttributesRun)
529511
{
530512
var attributeName = beforeAfterAttribute.GetType().Name;
531513
if (!messageBus.QueueMessage(new AfterTestStarting(this, displayName, attributeName)))
532514
cancellationTokenSource.Cancel();
533515

534-
aggregator.Run(() => executionTime.MeassureStep(() => beforeAfterAttribute.After(methodUnderTest)));
516+
executionTime.MeassureStep(() => beforeAfterAttribute.After(methodUnderTest));
535517

536518
if (!messageBus.QueueMessage(new AfterTestFinished(this, displayName, attributeName)))
537519
cancellationTokenSource.Cancel();
538520
}
539521
}
540522

541-
aggregator.Run(() =>
523+
var disposable = testClass as IDisposable;
524+
if (disposable != null)
542525
{
543-
var disposable = testClass as IDisposable;
544-
if (disposable != null)
545-
{
546-
if (!messageBus.QueueMessage(new TestClassDisposeStarting(this, displayName)))
547-
cancellationTokenSource.Cancel();
526+
if (!messageBus.QueueMessage(new TestClassDisposeStarting(this, displayName)))
527+
cancellationTokenSource.Cancel();
548528

549-
try
550-
{
551-
executionTime.MeassureStep(() =>
552-
{
553-
NotifyTestIfRequired(displayName, disposable, executionTime, aggregator, output);
554-
disposable.Dispose();
555-
});
556-
}
557-
finally
529+
try
530+
{
531+
executionTime.MeassureStep(() =>
558532
{
559-
if (!messageBus.QueueMessage(new TestClassDisposeFinished(this, displayName)))
560-
cancellationTokenSource.Cancel();
561-
}
533+
NotifyTestIfRequired(displayName, disposable, executionTime, aggregator, output);
534+
disposable.Dispose();
535+
});
536+
}
537+
finally
538+
{
539+
if (!messageBus.QueueMessage(new TestClassDisposeFinished(this, displayName)))
540+
cancellationTokenSource.Cancel();
562541
}
563-
});
542+
}
564543
});
565544

566545
if (!cancellationTokenSource.IsCancellationRequested)
@@ -578,6 +557,32 @@ await executionTime.MeassureStepAsync(async () =>
578557
return executionTime.TotalSeconds;
579558
}
580559

560+
private object CreateTest(IMessageBus messageBus, Type classUnderTest, object[] constructorArguments,
561+
MethodInfo methodUnderTest, string displayName, CancellationTokenSource cancellationTokenSource,
562+
ExecutionTime executionTime)
563+
{
564+
object testClass = null;
565+
if (!methodUnderTest.IsStatic)
566+
{
567+
if (!messageBus.QueueMessage(new TestClassConstructionStarting(this, displayName)))
568+
cancellationTokenSource.Cancel();
569+
570+
try
571+
{
572+
if (!cancellationTokenSource.IsCancellationRequested)
573+
{
574+
executionTime.MeassureStep(() => testClass = Activator.CreateInstance(classUnderTest, constructorArguments));
575+
}
576+
}
577+
finally
578+
{
579+
if (!messageBus.QueueMessage(new TestClassConstructionFinished(this, displayName)))
580+
cancellationTokenSource.Cancel();
581+
}
582+
}
583+
return testClass;
584+
}
585+
581586
private void NotifyTestIfRequired(string displayName, object test, ExecutionTime executionTime,
582587
ExceptionAggregator aggregator, string output)
583588
{
@@ -664,6 +669,16 @@ public void MeassureStep(Action step)
664669
total = total + stopwatch.Elapsed;
665670
}
666671

672+
public TResult MeassureStep<TResult>(Func<TResult> step)
673+
{
674+
var stopwatch = Stopwatch.StartNew();
675+
var result = step();
676+
stopwatch.Stop();
677+
total = total + stopwatch.Elapsed;
678+
679+
return result;
680+
}
681+
667682
public TimeSpan Total
668683
{
669684
get { return total; }

0 commit comments

Comments
 (0)