public static async Task Invoke(this Func <Task> action, ExceptionAggregator aggregator, ExecutionTimer timer) { var oldSyncContext = SynchronizationContext.Current; try { var asyncSyncContext = new AsyncTestSyncContext(oldSyncContext); SetSynchronizationContext(asyncSyncContext); await aggregator?.RunAsync( () => timer.AggregateAsync( async() => { await action(); var ex = await asyncSyncContext.WaitForCompletionAsync(); if (ex != null) { aggregator.Add(ex); } })); } finally { SetSynchronizationContext(oldSyncContext); } }
public void Dispose() { var aggregator = new ExceptionAggregator(); var tasks = _collectionFixtureMappings.Values.OfType <IAsyncLifetime>() .Select(asyncFixture => aggregator.RunAsync(asyncFixture.DisposeAsync)) .Concat(_assemblyFixtureMappings.Values.OfType <IAsyncLifetime>() .Select(asyncFixture => aggregator.RunAsync(asyncFixture.DisposeAsync))) .ToArray(); foreach (var disposable in _assemblyFixtureMappings.Values.OfType <IDisposable>() .Concat(_collectionFixtureMappings.Values.OfType <IDisposable>())) { aggregator.Run(disposable.Dispose); } Trace.Listeners.Clear(); Constants.Tracer.Listeners.Clear(); Task.WaitAll(tasks); }
public async Task <RunSummary> RunAsync() { if (!string.IsNullOrEmpty(this.skipReason)) { this.messageBus.Queue( this.scenario, test => new TestSkipped(test, this.skipReason), this.cancellationTokenSource); return(new RunSummary { Total = 1, Skipped = 1 }); } else { var summary = new RunSummary(); var output = string.Empty; var childAggregator = new ExceptionAggregator(this.parentAggregator); if (!childAggregator.HasExceptions) { var tuple = await childAggregator.RunAsync(() => this.InvokeScenarioAsync(childAggregator)); summary.Aggregate(tuple.Item1); output = tuple.Item2; } var exception = childAggregator.ToException(); if (exception != null) { summary.Total++; summary.Failed++; this.messageBus.Queue( this.scenario, test => new TestFailed(test, summary.Time, output, exception), this.cancellationTokenSource); } else if (summary.Total == 0) { summary.Total++; this.messageBus.Queue( this.scenario, test => new TestPassed(test, summary.Time, output), this.cancellationTokenSource); } return(summary); } }
/// <inheritdoc/> protected override async Task <RunSummary> RunTestAsync() { if (dataDiscoveryException != null) { return(RunTest_DataDiscoveryException()); } var runSummary = new RunSummary(); foreach (var testRunner in testRunners) { runSummary.Aggregate(await testRunner.RunAsync()); } // Run the cleanup here so we can include cleanup time in the run summary, // but save any exceptions so we can surface them during the cleanup phase, // so they get properly reported as test case cleanup failures. var timer = new ExecutionTimer(); foreach (var trackedObject in disposalTracker.TrackedObjects) { if (trackedObject is IAsyncDisposable asyncDisposable) { await timer.AggregateAsync(() => cleanupAggregator.RunAsync(asyncDisposable.DisposeAsync)); } if (trackedObject is IDisposable disposable) { timer.Aggregate(() => cleanupAggregator.Run(disposable.Dispose)); } } disposalTracker.Clear(); runSummary.Time += timer.Total; return(runSummary); }
public async Task <RunSummary> RunScenarioAsync() { var runSummary = new RunSummary { Total = 1 }; var output = string.Empty; if (!MessageBus.QueueMessage(new TestStarting(Test))) { CancellationTokenSource.Cancel(); } else { AfterTestStarting(); if (!string.IsNullOrEmpty(SkipReason)) { runSummary.Skipped++; if (!MessageBus.QueueMessage(new TestSkipped(Test, SkipReason))) { CancellationTokenSource.Cancel(); } } else { var aggregator = new ExceptionAggregator(Aggregator); if (!aggregator.HasExceptions) { var tuple = await aggregator.RunAsync(() => InvokeTestAsync(aggregator)); runSummary.Time = tuple.Item1; output = tuple.Item2; } var exception = aggregator.ToException(); TestResultMessage testResult; if (exception == null) { testResult = new TestPassed(Test, runSummary.Time, output); } else if (exception is IgnoreException) { testResult = new TestSkipped(Test, exception.Message); runSummary.Skipped++; } else { testResult = new TestFailed(Test, runSummary.Time, output, exception); runSummary.Failed++; } if (!CancellationTokenSource.IsCancellationRequested) { if (!MessageBus.QueueMessage(testResult)) { CancellationTokenSource.Cancel(); } } } Aggregator.Clear(); BeforeTestFinished(); if (Aggregator.HasExceptions) { if (!MessageBus.QueueMessage(new TestCleanupFailure(Test, Aggregator.ToException()))) { CancellationTokenSource.Cancel(); } } } if (!MessageBus.QueueMessage(new TestFinished(Test, runSummary.Time, output))) { CancellationTokenSource.Cancel(); } return(runSummary); }
/// <summary> /// Runs this fixture. /// </summary> /// <param name="output">The test output helper.</param> /// <returns></returns> public async Task RunAsync(ITestOutputHelper output = null) { _run = true; try { if (RequestMessage == null) { throw new InvalidOperationException($"Must call {nameof(When)} to configure an HTTP request"); } if (!_assertions.Any()) { throw new InvalidOperationException("No assertions to run"); } if (output != null) { _loggerProvider.SetTestOutputHelper(output); } using var client = Factory.CreateClient(); var provider = Factory.Server.Services; // Bootstrap. if (_bootstrapFunctions.Any()) { using var scope = provider.CreateScope(); foreach (var bootstrap in _bootstrapFunctions) { await bootstrap(scope.ServiceProvider); } } var logger = provider.GetRequiredService <ILogger <MvcFunctionalTestFixture <TStartup> > >(); var requestBody = await(RequestMessage.Content?.ReadAsStringAsync() ?? Task.FromResult <string>(null)); logger.LogInformation($"Sending request {RequestMessage}\n{requestBody ?? "<no body>"}"); var response = await client.SendAsync(RequestMessage); var responseBody = await(response.Content?.ReadAsStringAsync() ?? Task.FromResult <string>(null)); logger.LogInformation($"Received {response}\n{responseBody ?? "<no body>"}"); var aggregator = new ExceptionAggregator(); foreach (var assertion in _assertions) { switch (assertion) { case ResponseAssertion ra: aggregator.Run(() => ra.Assertion(response)); break; case ResponseBodyAssertion ra: if (aggregator.TryRun(() => ra.Deserializer(responseBody), out var result)) { foreach (var a in ra.Assertions) { await aggregator.RunAsync(() => a(provider, result)); } } break; case ServiceAssertion sa: using (var scope = provider.CreateScope()) { await aggregator.RunAsync(() => sa.Assertion(scope.ServiceProvider)); } break; case RequestAssertion ra: var context = await ra.ContextFactory(response); var fixture = new MvcFunctionalTestFixture <TStartup>(_loggerProvider, this); ra.Configurator(context, fixture); await aggregator.RunAsync(() => fixture.RunAsync()); break; } } aggregator.ThrowIfHasExceptions(); } finally { Reset(); } }