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; } }
/// <summary> /// Runs a single test for a given test method. /// </summary> /// <param name="messageBus">The message bus to send results to.</param> /// <param name="classUnderTest">The class under test.</param> /// <param name="constructorArguments">The arguments to pass to the constructor.</param> /// <param name="methodUnderTest">The method under test.</param> /// <param name="testMethodArguments">The arguments to pass to the test method.</param> /// <param name="displayName">The display name for the test.</param> /// <param name="beforeAfterAttributes">The <see cref="BeforeAfterTestAttribute"/> instances attached to the test.</param> /// <param name="parentAggregator">The parent aggregator that contains the exceptions up to this point.</param> /// <param name="cancellationTokenSource">The cancellation token source that indicates whether cancellation has been requested.</param> protected async Task<decimal> RunTestWithArgumentsAsync(IMessageBus messageBus, Type classUnderTest, object[] constructorArguments, MethodInfo methodUnderTest, object[] testMethodArguments, string displayName, List<BeforeAfterTestAttribute> beforeAfterAttributes, ExceptionAggregator parentAggregator, CancellationTokenSource cancellationTokenSource) { var executionTime = 0M; var aggregator = new ExceptionAggregator(parentAggregator); var output = String.Empty; // TODO: Add output facilities for v2 if (!messageBus.QueueMessage(new TestStarting(this, displayName))) cancellationTokenSource.Cancel(); else { if (!String.IsNullOrEmpty(SkipReason)) { if (!messageBus.QueueMessage(new TestSkipped(this, displayName, SkipReason))) cancellationTokenSource.Cancel(); } else { var beforeAttributesRun = new Stack<BeforeAfterTestAttribute>(); var stopwatch = Stopwatch.StartNew(); if (!aggregator.HasExceptions) await aggregator.RunAsync(async () => { object testClass = null; if (!methodUnderTest.IsStatic) { if (!messageBus.QueueMessage(new TestClassConstructionStarting(this, displayName))) cancellationTokenSource.Cancel(); try { if (!cancellationTokenSource.IsCancellationRequested) testClass = Activator.CreateInstance(classUnderTest, constructorArguments); } finally { if (!messageBus.QueueMessage(new TestClassConstructionFinished(this, displayName))) cancellationTokenSource.Cancel(); } } if (!cancellationTokenSource.IsCancellationRequested) { await aggregator.RunAsync(async () => { foreach (var beforeAfterAttribute in beforeAfterAttributes) { var attributeName = beforeAfterAttribute.GetType().Name; if (!messageBus.QueueMessage(new BeforeTestStarting(this, displayName, attributeName))) cancellationTokenSource.Cancel(); else { try { beforeAfterAttribute.Before(methodUnderTest); beforeAttributesRun.Push(beforeAfterAttribute); } finally { if (!messageBus.QueueMessage(new BeforeTestFinished(this, displayName, attributeName))) cancellationTokenSource.Cancel(); } } if (cancellationTokenSource.IsCancellationRequested) return; } if (!cancellationTokenSource.IsCancellationRequested) { var parameterTypes = methodUnderTest.GetParameters().Select(p => p.ParameterType).ToArray(); var oldSyncContext = SynchronizationContext.Current; try { var asyncSyncContext = new AsyncTestSyncContext(); SetSynchronizationContext(asyncSyncContext); await aggregator.RunAsync(async () => { var result = methodUnderTest.Invoke(testClass, ConvertArguments(testMethodArguments ?? EmptyArray, parameterTypes)); var task = result as Task; if (task != null) await task; else { var ex = await asyncSyncContext.WaitForCompletionAsync(); if (ex != null) aggregator.Add(ex); } }); } finally { SetSynchronizationContext(oldSyncContext); } } }); foreach (var beforeAfterAttribute in beforeAttributesRun) { var attributeName = beforeAfterAttribute.GetType().Name; if (!messageBus.QueueMessage(new AfterTestStarting(this, displayName, attributeName))) cancellationTokenSource.Cancel(); aggregator.Run(() => beforeAfterAttribute.After(methodUnderTest)); if (!messageBus.QueueMessage(new AfterTestFinished(this, displayName, attributeName))) cancellationTokenSource.Cancel(); } } aggregator.Run(() => { var disposable = testClass as IDisposable; if (disposable != null) { if (!messageBus.QueueMessage(new TestClassDisposeStarting(this, displayName))) cancellationTokenSource.Cancel(); try { disposable.Dispose(); } finally { if (!messageBus.QueueMessage(new TestClassDisposeFinished(this, displayName))) cancellationTokenSource.Cancel(); } } }); }); stopwatch.Stop(); if (!cancellationTokenSource.IsCancellationRequested) { executionTime = (decimal)stopwatch.Elapsed.TotalSeconds; var exception = aggregator.ToException(); var testResult = exception == null ? (TestResultMessage)new TestPassed(this, displayName, executionTime, output) : new TestFailed(this, displayName, executionTime, output, exception); if (!messageBus.QueueMessage(testResult)) cancellationTokenSource.Cancel(); } } } if (!messageBus.QueueMessage(new TestFinished(this, displayName, executionTime, output))) cancellationTokenSource.Cancel(); return executionTime; }
/// <summary> /// Runs the test. /// </summary> /// <returns>Returns summary information about the test that was run.</returns> public async Task <RunSummary> RunAsync() { 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 { 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 a single test for a given test method. /// </summary> /// <param name="messageBus">The message bus to send results to.</param> /// <param name="classUnderTest">The class under test.</param> /// <param name="constructorArguments">The arguments to pass to the constructor.</param> /// <param name="methodUnderTest">The method under test.</param> /// <param name="testMethodArguments">The arguments to pass to the test method.</param> /// <param name="displayName">The display name for the test.</param> /// <param name="beforeAfterAttributes">The <see cref="BeforeAfterTestAttribute"/> instances attached to the test.</param> /// <param name="parentAggregator">The parent aggregator that contains the exceptions up to this point.</param> /// <param name="cancellationTokenSource">The cancellation token source that indicates whether cancellation has been requested.</param> protected async Task <decimal> RunTestWithArgumentsAsync(IMessageBus messageBus, Type classUnderTest, object[] constructorArguments, MethodInfo methodUnderTest, object[] testMethodArguments, string displayName, List <BeforeAfterTestAttribute> beforeAfterAttributes, ExceptionAggregator parentAggregator, CancellationTokenSource cancellationTokenSource) { var executionTimeInSeconds = 0.0m; var aggregator = new ExceptionAggregator(parentAggregator); var output = String.Empty; // TODO: Add output facilities for v2 if (!messageBus.QueueMessage(new TestStarting(this, displayName))) { cancellationTokenSource.Cancel(); } else { if (!String.IsNullOrEmpty(SkipReason)) { if (!messageBus.QueueMessage(new TestSkipped(this, displayName, SkipReason))) { cancellationTokenSource.Cancel(); } } else { var beforeAttributesRun = new Stack <BeforeAfterTestAttribute>(); var executionTime = new ExecutionTime(); if (!aggregator.HasExceptions) { await aggregator.RunAsync(async() => { object testClass = null; if (!methodUnderTest.IsStatic) { if (!messageBus.QueueMessage(new TestClassConstructionStarting(this, displayName))) { cancellationTokenSource.Cancel(); } try { if (!cancellationTokenSource.IsCancellationRequested) { executionTime.Aggregate(() => testClass = Activator.CreateInstance(classUnderTest, constructorArguments)); } } finally { if (!messageBus.QueueMessage(new TestClassConstructionFinished(this, displayName))) { cancellationTokenSource.Cancel(); } } } if (!cancellationTokenSource.IsCancellationRequested) { await aggregator.RunAsync(async() => { foreach (var beforeAfterAttribute in beforeAfterAttributes) { var attributeName = beforeAfterAttribute.GetType().Name; if (!messageBus.QueueMessage(new BeforeTestStarting(this, displayName, attributeName))) { cancellationTokenSource.Cancel(); } else { try { executionTime.Aggregate(() => beforeAfterAttribute.Before(methodUnderTest)); beforeAttributesRun.Push(beforeAfterAttribute); } finally { if (!messageBus.QueueMessage(new BeforeTestFinished(this, displayName, attributeName))) { cancellationTokenSource.Cancel(); } } } if (cancellationTokenSource.IsCancellationRequested) { return; } } if (!cancellationTokenSource.IsCancellationRequested) { var parameterTypes = methodUnderTest.GetParameters().Select(p => p.ParameterType).ToArray(); var oldSyncContext = SynchronizationContext.Current; try { var asyncSyncContext = new AsyncTestSyncContext(); SetSynchronizationContext(asyncSyncContext); await aggregator.RunAsync(async() => { await executionTime.AggregateAsync(async() => { var result = methodUnderTest.Invoke(testClass, Reflector.ConvertArguments(testMethodArguments, parameterTypes)); var task = result as Task; if (task != null) { await task; } else { var ex = await asyncSyncContext.WaitForCompletionAsync(); if (ex != null) { aggregator.Add(ex); } } }); }); } finally { SetSynchronizationContext(oldSyncContext); } } }); foreach (var beforeAfterAttribute in beforeAttributesRun) { var attributeName = beforeAfterAttribute.GetType().Name; if (!messageBus.QueueMessage(new AfterTestStarting(this, displayName, attributeName))) { cancellationTokenSource.Cancel(); } aggregator.Run(() => executionTime.Aggregate(() => beforeAfterAttribute.After(methodUnderTest))); if (!messageBus.QueueMessage(new AfterTestFinished(this, displayName, attributeName))) { cancellationTokenSource.Cancel(); } } } aggregator.Run(() => { var disposable = testClass as IDisposable; if (disposable != null) { if (!messageBus.QueueMessage(new TestClassDisposeStarting(this, displayName))) { cancellationTokenSource.Cancel(); } try { executionTime.Aggregate(disposable.Dispose); } finally { if (!messageBus.QueueMessage(new TestClassDisposeFinished(this, displayName))) { cancellationTokenSource.Cancel(); } } } }); }); } if (!cancellationTokenSource.IsCancellationRequested) { executionTimeInSeconds = (decimal)executionTime.Total.TotalSeconds; var exception = aggregator.ToException(); var testResult = exception == null ? (TestResultMessage) new TestPassed(this, displayName, executionTimeInSeconds, output) : new TestFailed(this, displayName, executionTimeInSeconds, output, exception); if (!messageBus.QueueMessage(testResult)) { cancellationTokenSource.Cancel(); } } } } if (!messageBus.QueueMessage(new TestFinished(this, displayName, executionTimeInSeconds, output))) { cancellationTokenSource.Cancel(); } return(executionTimeInSeconds); }
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; }