/// <inheritdoc/> public void Run(IEnumerable<ITestCase> testMethods, IMessageSink messageSink) { bool cancelled = false; var totalSummary = new RunSummary(); string currentDirectory = Directory.GetCurrentDirectory(); try { Directory.SetCurrentDirectory(Path.GetDirectoryName(assemblyInfo.AssemblyPath)); if (messageSink.OnMessage(new TestAssemblyStarting())) { var classGroups = testMethods.Cast<XunitTestCase>().GroupBy(tc => tc.Class).ToList(); if (classGroups.Count > 0) { var collectionSummary = new RunSummary(); if (messageSink.OnMessage(new TestCollectionStarting())) { foreach (var group in classGroups) { var classSummary = new RunSummary(); if (!messageSink.OnMessage(new TestClassStarting { ClassName = group.Key.Name })) cancelled = true; else { cancelled = RunTestClass(messageSink, group, classSummary); collectionSummary.Aggregate(classSummary); } if (!messageSink.OnMessage(new TestClassFinished { Assembly = assemblyInfo, ClassName = group.Key.Name, TestsRun = classSummary.Total })) cancelled = true; if (cancelled) break; } } messageSink.OnMessage(new TestCollectionFinished { Assembly = assemblyInfo, TestsRun = collectionSummary.Total }); totalSummary.Aggregate(collectionSummary); } } messageSink.OnMessage(new TestAssemblyFinished { Assembly = assemblyInfo, TestsRun = totalSummary.Total, TestsFailed = totalSummary.Failed, TestsSkipped = totalSummary.Skipped, ExecutionTime = totalSummary.Time }); } finally { Directory.SetCurrentDirectory(currentDirectory); } }
public async Task<RunSummary> RunAsync() { var summary = new RunSummary(); await this.aggregator.RunAsync(async () => { if (!this.cancellationTokenSource.IsCancellationRequested) { var testClassInstance = this.CreateScenarioClass(); if (!this.cancellationTokenSource.IsCancellationRequested) { await this.BeforeScenarioMethodInvokedAsync(); if (!this.cancellationTokenSource.IsCancellationRequested && !this.aggregator.HasExceptions) { summary.Aggregate(await this.InvokeScenarioMethodAsync(testClassInstance)); } await this.AfterScenarioMethodInvokedAsync(); } var disposable = testClassInstance as IDisposable; if (disposable != null) { this.timer.Aggregate(() => this.aggregator.Run(disposable.Dispose)); } } summary.Time += this.timer.Total; }); return summary; }
protected override async Task<RunSummary> RunTestCollectionAsync(IMessageBus messageBus, ITestCollection testCollection, IEnumerable<IXunitTestCase> testCases, CancellationTokenSource cancellationTokenSource) { var summary = new RunSummary(); var defaultCases = new List<IXunitTestCase>(); var observationTestCases = new List<ObservationTestCase>(); foreach (var testCase in testCases) { if (testCase is ObservationTestCase) observationTestCases.Add(testCase as ObservationTestCase); else defaultCases.Add(testCase); } if (observationTestCases.Any()) { summary.Aggregate( await new ObservationTestCollectionRunner( testCollection, observationTestCases, DiagnosticMessageSink, messageBus, TestCaseOrderer, new ExceptionAggregator(Aggregator), cancellationTokenSource ) .RunAsync() ); } if (defaultCases.Any()) { summary.Aggregate( await base.RunTestCollectionAsync(messageBus, testCollection, defaultCases, cancellationTokenSource) ); } return summary; }
/// <summary> /// Runs the list of test collections. By default, groups the tests by collection and runs them synchronously. /// </summary> /// <param name="messageBus">The message bus to report run status to.</param> /// <param name="cancellationTokenSource">The task cancellation token source, used to cancel the test run.</param> /// <returns>Returns summary information about the tests that were run.</returns> protected virtual async Task <RunSummary> RunTestCollectionsAsync(IMessageBus messageBus, CancellationTokenSource cancellationTokenSource) { var summary = new RunSummary(); foreach (var collection in OrderTestCollections()) { summary.Aggregate(await RunTestCollectionAsync(messageBus, collection.Item1, collection.Item2, cancellationTokenSource)); if (cancellationTokenSource.IsCancellationRequested) { break; } } return(summary); }
/// <summary> /// Runs the list of test cases. By default, it runs the cases in order, synchronously. /// </summary> /// <returns>Returns summary information about the tests that were run.</returns> protected virtual async Task <RunSummary> RunTestCasesAsync() { var summary = new RunSummary(); foreach (var testCase in TestCases) { summary.Aggregate(await RunTestCaseAsync(testCase)); if (CancellationTokenSource.IsCancellationRequested) { break; } } return(summary); }
/// <summary> /// Runs the list of test classes. By default, groups the tests by class and runs them synchronously. /// </summary> /// <returns>Returns summary information about the tests that were run.</returns> protected virtual async Task <RunSummary> RunTestClassesAsync() { var summary = new RunSummary(); foreach (var testCasesByClass in TestCases.GroupBy(tc => tc.Class)) { summary.Aggregate(await RunTestClassAsync((IReflectionTypeInfo)testCasesByClass.Key, testCasesByClass)); if (CancellationTokenSource.IsCancellationRequested) { break; } } return(summary); }
/// <summary> /// Runs the list of test collections. By default, groups the tests by collection and runs them synchronously. /// </summary> /// <param name="messageBus">The message bus to report run status to.</param> /// <param name="cancellationTokenSource">The task cancellation token source, used to cancel the test run.</param> /// <returns>Returns summary information about the tests that were run.</returns> protected virtual async Task <RunSummary> RunTestCollectionsAsync(IMessageBus messageBus, CancellationTokenSource cancellationTokenSource) { var summary = new RunSummary(); foreach (var collectionGroup in TestCases.Cast <TTestCase>().GroupBy(tc => tc.TestMethod.TestClass.TestCollection, TestCollectionComparer.Instance)) { summary.Aggregate(await RunTestCollectionAsync(messageBus, collectionGroup.Key, collectionGroup, cancellationTokenSource)); if (cancellationTokenSource.IsCancellationRequested) { break; } } return(summary); }
/// <summary> /// Runs the list of test methods. By default, orders the tests, groups them by method and runs them synchronously. /// </summary> /// <returns>Returns summary information about the tests that were run.</returns> protected virtual async Task <RunSummary> RunTestMethodsAsync() { var summary = new RunSummary(); var orderedTestCases = TestCaseOrderer.OrderTestCases(TestCases); var constructorArguments = CreateTestClassConstructorArguments(); foreach (var method in orderedTestCases.GroupBy(tc => tc.Method)) { summary.Aggregate(await RunTestMethodAsync((IReflectionMethodInfo)method.Key, method, constructorArguments)); if (CancellationTokenSource.IsCancellationRequested) { break; } } return(summary); }
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; } }
public async Task <RunSummary> RunAsync() { OnTestClassStarting(); var classSummary = new RunSummary(); if (!MessageBus.QueueMessage(new TestClassStarting(TestCollection, TestClass.Name))) { CancellationTokenSource.Cancel(); } else { var orderedTestCases = TestCaseOrderer.OrderTestCases(TestCases); var methodGroups = orderedTestCases.GroupBy(tc => tc.Method); var constructorArguments = CreateTestClassConstructorArguments(); foreach (var method in methodGroups) { var methodSummary = await RunTestMethodAsync(constructorArguments, (IReflectionMethodInfo)method.Key, method); classSummary.Aggregate(methodSummary); if (CancellationTokenSource.IsCancellationRequested) { break; } } } if (!MessageBus.QueueMessage(new TestClassFinished(TestCollection, TestClass.Name, classSummary.Time, classSummary.Total, classSummary.Failed, classSummary.Skipped))) { CancellationTokenSource.Cancel(); } OnTestClassFinished(); return(classSummary); }
protected override async Task<RunSummary> RunTestAsync() { var dataDiscoveryException = this.GetDataDiscoveryException(); if (dataDiscoveryException != null) return this.RunTest_DataDiscoveryException(); var runSummary = new RunSummary(); var testRunners = this.GetTestRunners(); foreach (var testRunner in testRunners) runSummary.Aggregate(await RunTestAsync(testRunner)); // 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(); var cleanupAggregator = this.GetCleanupAggregator(); var toDispose = this.GetToDispose(); foreach (var disposable in toDispose) timer.Aggregate(() => cleanupAggregator.Run(() => disposable.Dispose())); runSummary.Time += timer.Total; return runSummary; }
private async Task<RunSummary> InvokeStepsAsync( ICollection<IStepDefinition> backGroundStepDefinitions, ICollection<IStepDefinition> scenarioStepDefinitions) { var filters = this.scenarioClass.Assembly.GetCustomAttributes(typeof(Attribute)) .Concat(this.scenarioClass.GetCustomAttributes(typeof(Attribute))) .Concat(this.scenarioMethod.GetCustomAttributes(typeof(Attribute))) .OfType<IFilter<IStepDefinition>>(); var stepDefinitions = filters .Aggregate( backGroundStepDefinitions.Concat(scenarioStepDefinitions), (current, filter) => filter.Filter(current)) .ToArray(); var summary = new RunSummary(); string skipReason = null; var teardowns = new List<Action>(); var stepNumber = 0; foreach (var stepDefinition in stepDefinitions) { stepDefinition.SkipReason = stepDefinition.SkipReason ?? skipReason; var stepDisplayName = GetStepDisplayName( this.scenario.DisplayName, ++stepNumber, stepNumber <= backGroundStepDefinitions.Count, stepDefinition.Text, this.scenarioMethodArguments); var step = new Step(this.scenario, stepDisplayName); var interceptingBus = new DelegatingMessageBus( this.messageBus, message => { if (message is ITestFailed && stepDefinition.FailureBehavior == RemainingSteps.Skip) { skipReason = string.Format( CultureInfo.InvariantCulture, "Failed to execute preceding step: {0}", step.DisplayName); } }); var stepRunner = new StepRunner( step, stepDefinition.Body, interceptingBus, this.scenarioClass, this.constructorArguments, this.scenarioMethod, this.scenarioMethodArguments, stepDefinition.SkipReason, new ExceptionAggregator(this.aggregator), this.cancellationTokenSource); summary.Aggregate(await stepRunner.RunAsync()); teardowns.AddRange(stepRunner.Disposables.Select(disposable => (Action)disposable.Dispose) .Concat(stepDefinition.Teardowns.Where(teardown => teardown != null)).ToArray()); } if (teardowns.Any()) { teardowns.Reverse(); var teardownTimer = new ExecutionTimer(); var teardownAggregator = new ExceptionAggregator(); foreach (var teardown in teardowns) { teardownTimer.Aggregate(() => teardownAggregator.Run(() => teardown())); } summary.Time += teardownTimer.Total; if (teardownAggregator.HasExceptions) { summary.Failed++; summary.Total++; var stepDisplayName = GetStepDisplayName( this.scenario.DisplayName, ++stepNumber, false, "(Teardown)", this.scenarioMethodArguments); this.messageBus.Queue( new Step(this.scenario, stepDisplayName), test => new TestFailed(test, teardownTimer.Total, null, teardownAggregator.ToException()), this.cancellationTokenSource); } } return summary; }
private async Task<RunSummary> RunTestCollectionAsync(IMessageBus messageBus, ITestCollection collection, IEnumerable<XunitTestCase> testCases, ITestCaseOrderer orderer, CancellationTokenSource cancellationTokenSource) { var collectionSummary = new RunSummary(); var collectionFixtureMappings = new Dictionary<Type, object>(); var aggregator = new ExceptionAggregator(); if (collection.CollectionDefinition != null) { var declarationType = ((IReflectionTypeInfo)collection.CollectionDefinition).Type; foreach (var interfaceType in declarationType.GetInterfaces().Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollectionFixture<>))) CreateFixture(interfaceType, aggregator, collectionFixtureMappings); var ordererAttribute = collection.CollectionDefinition.GetCustomAttributes(typeof(TestCaseOrdererAttribute)).SingleOrDefault(); if (ordererAttribute != null) orderer = GetTestCaseOrderer(ordererAttribute); } if (messageBus.QueueMessage(new TestCollectionStarting(collection))) { foreach (var testCasesByClass in testCases.GroupBy(tc => tc.Class)) { var classSummary = new RunSummary(); if (!messageBus.QueueMessage(new TestClassStarting(collection, testCasesByClass.Key.Name))) cancellationTokenSource.Cancel(); else { await RunTestClassAsync(messageBus, collection, collectionFixtureMappings, (IReflectionTypeInfo)testCasesByClass.Key, testCasesByClass, orderer, classSummary, aggregator, cancellationTokenSource); collectionSummary.Aggregate(classSummary); } if (!messageBus.QueueMessage(new TestClassFinished(collection, testCasesByClass.Key.Name, classSummary.Time, classSummary.Total, classSummary.Failed, classSummary.Skipped))) cancellationTokenSource.Cancel(); if (cancellationTokenSource.IsCancellationRequested) break; } } foreach (var fixture in collectionFixtureMappings.Values.OfType<IDisposable>()) { try { fixture.Dispose(); } catch (Exception ex) { if (!messageBus.QueueMessage(new ErrorMessage(ex.Unwrap()))) cancellationTokenSource.Cancel(); } } messageBus.QueueMessage(new TestCollectionFinished(collection, collectionSummary.Time, collectionSummary.Total, collectionSummary.Failed, collectionSummary.Skipped)); return collectionSummary; }
/// <inheritdoc/> protected override async Task <RunSummary> RunTestAsync() { var testRunners = new List <XunitTestRunner>(); var toDispose = new List <IDisposable>(); try { var dataAttributes = TestCase.TestMethod.Method.GetCustomAttributes(typeof(DataAttribute)); foreach (var dataAttribute in dataAttributes) { var discovererAttribute = dataAttribute.GetCustomAttributes(typeof(DataDiscovererAttribute)).First(); var args = discovererAttribute.GetConstructorArguments().Cast <string>().ToList(); var discovererType = Reflector.GetType(args[1], args[0]); var discoverer = ExtensibilityPointFactory.GetDataDiscoverer(discovererType); foreach (var dataRow in discoverer.GetData(dataAttribute, TestCase.TestMethod.Method)) { toDispose.AddRange(dataRow.OfType <IDisposable>()); ITypeInfo[] resolvedTypes = null; var methodToRun = TestMethod; if (methodToRun.IsGenericMethodDefinition) { resolvedTypes = TypeUtility.ResolveGenericTypes(TestCase.TestMethod.Method, dataRow); methodToRun = methodToRun.MakeGenericMethod(resolvedTypes.Select(t => ((IReflectionTypeInfo)t).Type).ToArray()); } var parameterTypes = methodToRun.GetParameters().Select(p => p.ParameterType).ToArray(); var convertedDataRow = Reflector.ConvertArguments(dataRow, parameterTypes); var theoryDisplayName = TypeUtility.GetDisplayNameWithArguments(TestCase.TestMethod.Method, DisplayName, convertedDataRow, resolvedTypes); testRunners.Add(new XunitTestRunner(TestCase, MessageBus, TestClass, ConstructorArguments, methodToRun, convertedDataRow, theoryDisplayName, SkipReason, BeforeAfterAttributes, Aggregator, CancellationTokenSource)); } } } catch (Exception ex) { if (!MessageBus.QueueMessage(new TestStarting(TestCase, DisplayName))) { CancellationTokenSource.Cancel(); } else { if (!MessageBus.QueueMessage(new TestFailed(TestCase, DisplayName, 0, null, ex.Unwrap()))) { CancellationTokenSource.Cancel(); } } if (!MessageBus.QueueMessage(new TestFinished(TestCase, DisplayName, 0, null))) { CancellationTokenSource.Cancel(); } return(new RunSummary { Total = 1, Failed = 1 }); } var runSummary = new RunSummary(); foreach (var testRunner in testRunners) { runSummary.Aggregate(await testRunner.RunAsync()); } var timer = new ExecutionTimer(); var aggregator = new ExceptionAggregator(); // REVIEW: What should be done with these leftover errors? foreach (var disposable in toDispose) { timer.Aggregate(() => aggregator.Run(() => disposable.Dispose())); } runSummary.Time += timer.Total; return(runSummary); }
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously public override async Task<RunSummary> RunAsync #pragma warning restore CS1998 ( IMessageSink diagnosticMessageSink , IMessageBus bus , object[] constructorArguments , ExceptionAggregator aggregator , CancellationTokenSource cancellationTokenSource ) { var summary = new RunSummary(); var test = new XunitTest(this, DisplayName); if (Inv == null) { var msg = "Return Type must be Invariant."; bus.QueueMessage ( new TestFailed(test, 0, null, new Exception(msg)) ); summary.Aggregate(new RunSummary { Total = 1, Failed = 1 }); return summary; } var output = new TestOutputHelper(); var timer = new ExecutionTimer(); output.Initialize(bus, test); bus.QueueMessage(new TestStarting(test)); InvariantResult result; timer.Aggregate(() => result = Inv.Results(Config(output)).First()); var xresult = ToXunitResult(test, result, timer.Total); bus.QueueMessage(xresult.Item1); summary.Aggregate(xresult.Item2); return summary; }
/// <inheritdoc/> protected override async Task<RunSummary> RunTestAsync() { var testRunners = new List<XunitTestRunner>(); var toDispose = new List<IDisposable>(); try { var dataAttributes = TestCase.TestMethod.Method.GetCustomAttributes(typeof(DataAttribute)); foreach (var dataAttribute in dataAttributes) { var discovererAttribute = dataAttribute.GetCustomAttributes(typeof(DataDiscovererAttribute)).First(); var args = discovererAttribute.GetConstructorArguments().Cast<string>().ToList(); var discovererType = Reflector.GetType(args[1], args[0]); var discoverer = ExtensibilityPointFactory.GetDataDiscoverer(discovererType); foreach (var dataRow in discoverer.GetData(dataAttribute, TestCase.TestMethod.Method)) { toDispose.AddRange(dataRow.OfType<IDisposable>()); ITypeInfo[] resolvedTypes = null; var methodToRun = TestMethod; if (methodToRun.IsGenericMethodDefinition) { resolvedTypes = TypeUtility.ResolveGenericTypes(TestCase.TestMethod.Method, dataRow); methodToRun = methodToRun.MakeGenericMethod(resolvedTypes.Select(t => ((IReflectionTypeInfo)t).Type).ToArray()); } var parameterTypes = methodToRun.GetParameters().Select(p => p.ParameterType).ToArray(); var convertedDataRow = Reflector.ConvertArguments(dataRow, parameterTypes); var theoryDisplayName = TypeUtility.GetDisplayNameWithArguments(TestCase.TestMethod.Method, DisplayName, convertedDataRow, resolvedTypes); var test = new XunitTest(TestCase, theoryDisplayName); testRunners.Add(new XunitTestRunner(test, MessageBus, TestClass, ConstructorArguments, methodToRun, convertedDataRow, SkipReason, BeforeAfterAttributes, Aggregator, CancellationTokenSource)); } } } catch (Exception ex) { var test = new XunitTest(TestCase, DisplayName); if (!MessageBus.QueueMessage(new TestStarting(test))) CancellationTokenSource.Cancel(); else { if (!MessageBus.QueueMessage(new TestFailed(test, 0, null, ex.Unwrap()))) CancellationTokenSource.Cancel(); } if (!MessageBus.QueueMessage(new TestFinished(test, 0, null))) CancellationTokenSource.Cancel(); return new RunSummary { Total = 1, Failed = 1 }; } var runSummary = new RunSummary(); foreach (var testRunner in testRunners) runSummary.Aggregate(await testRunner.RunAsync()); var timer = new ExecutionTimer(); var aggregator = new ExceptionAggregator(); // REVIEW: What should be done with these leftover errors? foreach (var disposable in toDispose) timer.Aggregate(() => aggregator.Run(() => disposable.Dispose())); runSummary.Time += timer.Total; return runSummary; }
private RunSummary RunTestCollection(IMessageBus messageBus, ITestCollection collection, IEnumerable <XunitTestCase> testCases, ITestCaseOrderer orderer, CancellationTokenSource cancellationTokenSource) { var collectionSummary = new RunSummary(); var collectionFixtureMappings = new Dictionary <Type, object>(); var aggregator = new ExceptionAggregator(); if (collection.CollectionDefinition != null) { var declarationType = ((IReflectionTypeInfo)collection.CollectionDefinition).Type; foreach (var interfaceType in declarationType.GetInterfaces().Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollectionFixture <>))) { CreateFixture(interfaceType, aggregator, collectionFixtureMappings); } var ordererAttribute = collection.CollectionDefinition.GetCustomAttributes(typeof(TestCaseOrdererAttribute)).SingleOrDefault(); if (ordererAttribute != null) { orderer = GetTestCaseOrderer(ordererAttribute); } } if (messageBus.QueueMessage(new TestCollectionStarting(collection))) { foreach (var testCasesByClass in testCases.GroupBy(tc => tc.Class)) { var classSummary = new RunSummary(); if (!messageBus.QueueMessage(new TestClassStarting(collection, testCasesByClass.Key.Name))) { cancellationTokenSource.Cancel(); } else { RunTestClass(messageBus, collection, collectionFixtureMappings, (IReflectionTypeInfo)testCasesByClass.Key, testCasesByClass, orderer, classSummary, aggregator, cancellationTokenSource); collectionSummary.Aggregate(classSummary); } if (!messageBus.QueueMessage(new TestClassFinished(collection, testCasesByClass.Key.Name, classSummary.Time, classSummary.Total, classSummary.Failed, classSummary.Skipped))) { cancellationTokenSource.Cancel(); } if (cancellationTokenSource.IsCancellationRequested) { break; } } } foreach (var fixture in collectionFixtureMappings.Values.OfType <IDisposable>()) { try { fixture.Dispose(); } catch (Exception ex) { if (!messageBus.QueueMessage(new ErrorMessage(ex.Unwrap()))) { cancellationTokenSource.Cancel(); } } } messageBus.QueueMessage(new TestCollectionFinished(collection, collectionSummary.Time, collectionSummary.Total, collectionSummary.Failed, collectionSummary.Skipped)); return(collectionSummary); }
protected override async Task<RunSummary> RunTestAsync() { if (this.dataDiscoveryException != null) { this.MessageBus.Queue( new XunitTest(this.TestCase, this.DisplayName), test => new TestFailed(test, 0, null, this.dataDiscoveryException.Unwrap()), this.CancellationTokenSource); return new RunSummary { Total = 1, Failed = 1 }; } var summary = new RunSummary(); foreach (var scenarioRunner in this.scenarioRunners) { summary.Aggregate(await scenarioRunner.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 disposable in this.disposables) { timer.Aggregate(() => this.cleanupAggregator.Run(() => disposable.Dispose())); } summary.Time += timer.Total; return summary; }
private async Task<RunSummary> InvokeScenarioMethodAsync(object scenarioClassInstance) { var backgroundStepDefinitions = new List<IStepDefinition>(); var scenarioStepDefinitions = new List<IStepDefinition>(); await this.aggregator.RunAsync(async () => { try { foreach ( var backgroundMethod in this.scenario.TestCase.TestMethod.Method.Type.GetMethods(false) .Where(candidate => candidate.GetCustomAttributes(typeof(BackgroundAttribute)).Any()) .Select(method => method.ToRuntimeMethod())) { await this.timer.AggregateAsync(() => backgroundMethod.InvokeAsync(scenarioClassInstance, null)); } backgroundStepDefinitions.AddRange(CurrentThread.StepDefinitions); } catch (Exception ex) { } finally { CurrentThread.StepDefinitions.Clear(); } try { await this.timer.AggregateAsync(() => this.scenarioMethod.InvokeAsync(scenarioClassInstance, this.scenarioMethodArguments)); scenarioStepDefinitions.AddRange(CurrentThread.StepDefinitions); } finally { CurrentThread.StepDefinitions.Clear(); } }); var runSummary = new RunSummary { Time = this.timer.Total }; if (!this.aggregator.HasExceptions) { runSummary.Aggregate(await this.InvokeStepsAsync(backgroundStepDefinitions, scenarioStepDefinitions)); } return runSummary; }