Пример #1
0
        /// <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);
        }
Пример #2
0
        /// <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;
        }