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 VsixRunSummary Run (VsixTestCase testCase, IMessageBus messageBus, object[] constructorArguments)
		{
			var aggregator = new ExceptionAggregator ();

			var result = new XunitTestCaseRunner (
					testCase, testCase.DisplayName, testCase.SkipReason, constructorArguments, testCase.TestMethodArguments, messageBus,
					aggregator, new CancellationTokenSource ())
				.RunAsync ()
				.Result
				.ToVsixRunSummary ();

			if (aggregator.HasExceptions)
				result.Exception = aggregator.ToException ();

			return result;
		}
Example #3
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);
        }
Example #4
0
        /// <summary>
        /// Runs a single test for a given test method.
        /// </summary>
        /// <param name="messageSink">The message sink 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>
        /// <param name="executionTime">The time spent executing the tests.</param>
        protected void RunTestWithArguments(IMessageSink messageSink,
                                            Type classUnderTest,
                                            object[] constructorArguments,
                                            MethodInfo methodUnderTest,
                                            object[] testMethodArguments,
                                            string displayName,
                                            List<BeforeAfterTestAttribute> beforeAfterAttributes,
                                            ExceptionAggregator parentAggregator,
                                            CancellationTokenSource cancellationTokenSource,
                                            ref decimal executionTime)
        {
            var aggregator = new ExceptionAggregator(parentAggregator);

            if (!messageSink.OnMessage(new TestStarting(this, displayName)))
                cancellationTokenSource.Cancel();
            else
            {
                if (!String.IsNullOrEmpty(SkipReason))
                {
                    if (!messageSink.OnMessage(new TestSkipped(this, displayName, SkipReason)))
                        cancellationTokenSource.Cancel();
                }
                else
                {
                    var beforeAttributesRun = new Stack<BeforeAfterTestAttribute>();
                    var stopwatch = Stopwatch.StartNew();

                    if (!aggregator.HasExceptions)
                        aggregator.Run(() =>
                        {
                            object testClass = null;

                            if (!methodUnderTest.IsStatic)
                            {
                                if (!messageSink.OnMessage(new TestClassConstructionStarting(this, displayName)))
                                    cancellationTokenSource.Cancel();

                                try
                                {
                                    if (!cancellationTokenSource.IsCancellationRequested)
                                        testClass = Activator.CreateInstance(classUnderTest, constructorArguments);
                                }
                                finally
                                {
                                    if (!messageSink.OnMessage(new TestClassConstructionFinished(this, displayName)))
                                        cancellationTokenSource.Cancel();
                                }
                            }

                            if (!cancellationTokenSource.IsCancellationRequested)
                            {
                                aggregator.Run(() =>
                                {
                                    foreach (var beforeAfterAttribute in beforeAfterAttributes)
                                    {
                                        var attributeName = beforeAfterAttribute.GetType().Name;
                                        if (!messageSink.OnMessage(new BeforeTestStarting(this, displayName, attributeName)))
                                            cancellationTokenSource.Cancel();
                                        else
                                        {
                                            try
                                            {
                                                beforeAfterAttribute.Before(methodUnderTest);
                                                beforeAttributesRun.Push(beforeAfterAttribute);
                                            }
                                            finally
                                            {
                                                if (!messageSink.OnMessage(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);

                                            aggregator.Run(() =>
                                            {
                                                var result = methodUnderTest.Invoke(testClass, ConvertArguments(testMethodArguments ?? EmptyArray, parameterTypes));
                                                var task = result as Task;
                                                if (task != null)
                                                    task.GetAwaiter().GetResult();
                                                else
                                                {
                                                    var ex = asyncSyncContext.WaitForCompletion();
                                                    if (ex != null)
                                                        aggregator.Add(ex);
                                                }
                                            });
                                        }
                                        finally
                                        {
                                            SetSynchronizationContext(oldSyncContext);
                                        }
                                    }
                                });

                                foreach (var beforeAfterAttribute in beforeAttributesRun)
                                {
                                    var attributeName = beforeAfterAttribute.GetType().Name;
                                    if (!messageSink.OnMessage(new AfterTestStarting(this, displayName, attributeName)))
                                        cancellationTokenSource.Cancel();

                                    aggregator.Run(() => beforeAfterAttribute.After(methodUnderTest));

                                    if (!messageSink.OnMessage(new AfterTestFinished(this, displayName, attributeName)))
                                        cancellationTokenSource.Cancel();
                                }
                            }

                            aggregator.Run(() =>
                            {
                                IDisposable disposable = testClass as IDisposable;
                                if (disposable != null)
                                {
                                    if (!messageSink.OnMessage(new TestClassDisposeStarting(this, displayName)))
                                        cancellationTokenSource.Cancel();

                                    try
                                    {
                                        disposable.Dispose();
                                    }
                                    finally
                                    {
                                        if (!messageSink.OnMessage(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) : new TestFailed(this, displayName, executionTime, exception);
                        if (!messageSink.OnMessage(testResult))
                            cancellationTokenSource.Cancel();
                    }
                }
            }

            if (!messageSink.OnMessage(new TestFinished(this, displayName, executionTime)))
                cancellationTokenSource.Cancel();
        }
Example #5
0
        /// <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);
        }
        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;
        }
Example #7
0
        /// <summary>
        /// Runs a single test for a given test method.
        /// </summary>
        /// <param name="messageSink">The message sink 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="aggregator">The error aggregator to use for catching exception.</param>
        /// <param name="executionTime">The time spent executing the tests.</param>
        protected bool RunTestWithArguments(IMessageSink messageSink,
                                            Type classUnderTest,
                                            object[] constructorArguments,
                                            MethodInfo methodUnderTest,
                                            object[] testMethodArguments,
                                            string displayName,
                                            List<BeforeAfterTestAttribute> beforeAfterAttributes,
                                            ExceptionAggregator aggregator,
                                            ref decimal executionTime)
        {
            bool cancelled = false;

            if (!messageSink.OnMessage(new TestStarting { TestCase = this, TestDisplayName = displayName }))
                cancelled = true;
            else
            {
                if (!String.IsNullOrEmpty(SkipReason))
                {
                    if (!messageSink.OnMessage(new TestSkipped { TestCase = this, TestDisplayName = DisplayName, Reason = SkipReason }))
                        cancelled = true;
                }
                else
                {
                    var beforeAttributesRun = new Stack<BeforeAfterTestAttribute>();
                    var stopwatch = Stopwatch.StartNew();

                    if (!aggregator.HasExceptions)
                    {
                        aggregator.Run(() =>
                        {
                            object testClass = null;

                            if (!methodUnderTest.IsStatic)
                            {
                                if (!messageSink.OnMessage(new TestClassConstructionStarting { TestCase = this, TestDisplayName = displayName }))
                                    cancelled = true;

                                try
                                {
                                    if (!cancelled)
                                        testClass = Activator.CreateInstance(classUnderTest, constructorArguments);
                                }
                                finally
                                {
                                    if (!messageSink.OnMessage(new TestClassConstructionFinished { TestCase = this, TestDisplayName = displayName }))
                                        cancelled = true;
                                }
                            }

                            if (!cancelled)
                            {
                                aggregator.Run(() =>
                                {
                                    foreach (var beforeAfterAttribute in beforeAfterAttributes)
                                    {
                                        if (!messageSink.OnMessage(new BeforeTestStarting { TestCase = this, TestDisplayName = displayName, AttributeName = beforeAfterAttribute.GetType().Name }))
                                            cancelled = true;
                                        else
                                        {
                                            try
                                            {
                                                beforeAfterAttribute.Before(methodUnderTest);
                                                beforeAttributesRun.Push(beforeAfterAttribute);
                                            }
                                            finally
                                            {
                                                if (!messageSink.OnMessage(new BeforeTestFinished { TestCase = this, TestDisplayName = displayName, AttributeName = beforeAfterAttribute.GetType().Name }))
                                                    cancelled = true;
                                            }
                                        }

                                        if (cancelled)
                                            return;
                                    }

                                    if (!cancelled)
                                    {
                                        var parameterTypes = methodUnderTest.GetParameters().Select(p => p.ParameterType).ToArray();
                                        aggregator.Run(() =>
                                        {
                                            var result = methodUnderTest.Invoke(testClass, ConvertArguments(testMethodArguments ?? EmptyArray, parameterTypes));
                                            var task = result as Task;
                                            if (task != null)
                                                task.GetAwaiter().GetResult();
                                        });
                                    }
                                });

                                foreach (var beforeAfterAttribute in beforeAttributesRun)
                                {
                                    if (!messageSink.OnMessage(new AfterTestStarting { TestCase = this, TestDisplayName = displayName, AttributeName = beforeAfterAttribute.GetType().Name }))
                                        cancelled = true;

                                    aggregator.Run(() => beforeAfterAttribute.After(methodUnderTest));

                                    if (!messageSink.OnMessage(new AfterTestFinished { TestCase = this, TestDisplayName = displayName, AttributeName = beforeAfterAttribute.GetType().Name }))
                                        cancelled = true;
                                }
                            }

                            aggregator.Run(() =>
                            {
                                IDisposable disposable = testClass as IDisposable;
                                if (disposable != null)
                                {
                                    if (!messageSink.OnMessage(new TestClassDisposeStarting { TestCase = this, TestDisplayName = displayName }))
                                        cancelled = true;

                                    try
                                    {
                                        disposable.Dispose();
                                    }
                                    finally
                                    {
                                        if (!messageSink.OnMessage(new TestClassDisposeFinished { TestCase = this, TestDisplayName = displayName }))
                                            cancelled = true;
                                    }
                                }
                            });
                        });
                    }

                    stopwatch.Stop();

                    if (!cancelled)
                    {
                        executionTime = (decimal)stopwatch.Elapsed.TotalSeconds;

                        var exception = aggregator.ToException();
                        var testResult = exception == null ? (TestResultMessage)new TestPassed() : new TestFailed(exception);
                        testResult.TestCase = this;
                        testResult.TestDisplayName = displayName;
                        testResult.ExecutionTime = executionTime;

                        if (!messageSink.OnMessage(testResult))
                            cancelled = true;
                    }
                }
            }

            if (!messageSink.OnMessage(new TestFinished { TestCase = this, TestDisplayName = displayName, ExecutionTime = executionTime }))
                cancelled = true;

            return cancelled;
        }
        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;
        }
Example #9
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;
        }